I am working on a mac app. I have been struggling to create a directory in "Desktop" on Mac OS. I am working on High Sierra. It was working fine, but suddenly the app is unable to create a directory in Desktop. I get the following permission error. I am using Xcode 9.3 and swift 4.1.
Error Domain=NSCocoaErrorDomain Code=513 "You don’t have permission to save the file “TestDir” in the folder “Desktop”." UserInfo={NSFilePath=/Users/sj/Library/Containers/com.user.TestSync/Data/Desktop/TestDir, NSUnderlyingError=0x60400044cc60 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"
Here is my code:
class DBManager: NSObject {
static func getDirectoryPath() -> URL {
let homeDirectory = URL(fileURLWithPath: NSHomeDirectory())
let desktopPath = homeDirectory.appendingPathComponent("Desktop")
let databaseFolder = desktopPath.appendingPathComponent("TestDir")
return databaseFolder
}
static func createFolderIfNotExist() {
let databaseFolder = DBManager.getDirectoryPath()
if !FileManager().fileExists(atPath: databaseFolder.path) {
do {
try FileManager.default.createDirectory(atPath: databaseFolder.path, withIntermediateDirectories: true, attributes: nil)
} catch {
print(error)
}
}
}
}
The code works fine if I am to create a directory inside "Documents". But for some reason, I am not able to create inside Desktop even if I have provided read/write access for Desktop to everyone. I have also included the screenshot of the directory where I have to create one.
I tried to create a directory inside "Downloads" but ended with same permission issue. But, again I was successful to create directory inside "Library". So, it seems that the OS is not giving permission to create inside alias directory since both Desktop and Downloads are alias.
Any help is highly appreciated.
That is because your macOS Application is running in the "App Sandbox", check your "Capabilities" tab in the target settings.
~/Library/Containers/%BundleID%/Data/Desktop is a soft link to the user's desktop, and you have no write permissions (depending on your entitlements file not even read permissions).
Depending on your use case you can
disable the sandbox mode
let the user pick a folder by opening an "Open" dialog (then you can write to this)
enable read/write in some other protected user folder (like Downloads, etc.) or
create the TestDir directly in your home directory without using any soft linked folder
Besides what mentioned by #ChaosCoder, we also need set NSOpenPanel.canCreateDirectories to true:
panel.canCreateDirectories = true
Delete the App Sandbox data from your Capabilities.
Click on your project in your file navigator, then your project in the TARGETS tab, then make sure "Signing & Capabilities" is selected, then "ALL" then double click the "x" next to "App Sandbox".
Related
We have an issue with downloading any type of file from our server to our phone.
The problem that we have is that we get an access denied error every time we try to save the said file to phone External Memory.
Access to the path "/storage/emulated/0/Download/Test.txt" is denied.
We have given it all the permissions that we found in:
https://developer.android.com/training/data-storage
for both Documents and other files and Media.
Does anyone have any idea why would this be happening? The 'downloading' the file is not the problem, but the saving part is.
After Android 6.0 , we need to request the permissions in runtime . In xamarin , you could use the plugin PermissionsPlugin to request runtime permission .
Usage
using Plugin.Permissions;
using Plugin.Permissions.Abstractions;
bool shouldRequest = await CrossPermissions.Current.ShouldShowRequestPermissionRationaleAsync(Permission.Storage);
if(shouldRequest)
{
PermissionStatus status = await CrossPermissions.Current.RequestPermissionAsync<StoragePermission>();
if(status==PermissionStatus.Granted)
{
//do something you want
}
else
{
//...
}
}
For more details about the plugin you could check the github project site .
Trying to save a file locally from an app running in the iOS 8 Simulator and I'm continually getting access denied exceptions.
In previous apps I've used the following code to get a valid file path:
Environment.GetFolderPath(Environment.SpecialFolder.Personal)
or
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
But I've read that with iOS 8 this has now got to be written as:
NSFileManager.DefaultManager.GetUrls(NSSearchPathDirectory.DocumentDirectory,
NSSearchPathDomain.User)[0]
So I'm using the following code to generate a file path for a .txt file and receiving an access denied exception when trying to save with it:
public void SaveMyFile(string content)
{
NSUrl[] urls;
string filePath;
//
urls = NSFileManager.DefaultManager.GetUrls(NSSearchPathDirectory.DocumentDirectory,
NSSearchPathDomain.User);
filePath = Path.Combine(urls[0].Path, "MyApp", "myFile.txt");
File.WriteAllText(filePath, content);
}
So the file path that it gives me and also denies access to is /Users/Idox/Library/Developer/CoreSimulator/Devices/92498E38-7D50-4081-8A64-83061DC00A86/data/Containers/Data/Application/C35B3E98-C9E3-4ABA-AA7F-CD8419FA0EA5/Documents/MyApp/myFile.txt.
I'm wondering if there's some setting that needs to be toggled to give the app write access to this directory or if the directory itself is invalid.
I've also done a call to Directory.Exists(string path) to check if the directory is there, which it is.
You're missing the Path property on urls[0].Path
filePath = Path.Combine(urls[0].Path, "MyApp", "myFile.txt");
This was fixed in Xamarin.iOS 8.4, so if you're using a recent version of Xamarin you can use Environment.GetFolderPath without problems (which is useful if you want to share code across platforms).
Differences between running OSX App from Finder versus Xcode ???
System is iMac 27” all-in-1 running Mavericks OSX 10.9.5 and latest Xcode 6.0.1
The App reads a binary file and writes two text files, may re-write the binary file, and draws in a
window client area.
App totally runs in Xcode. App, binary file and two text files are in ~/Debug or ~/Release directory.
No problem writing to files. File i/o code does this…
std::fstream out( binary_file, std::ios::in|std::ios::binary);
if ( out )
out.read(buffer, MaxBuffer);
out.close();
ofstream info(“info_file.txt”);
if ( info.is_open() )
info << text;
info.close();
system("chmod 777 info_file.txt"); //tried this, doesn’t help
ofstream clout(“clout_file.txt”);
if ( clout.is_open() )
clout << text;
clout.close();
system("chmod 777 clout_file.txt"); //tried this, doesn’t help
App cannot write to files when run (double clicked) from Finder. Regardless of where App and files are located…
/Users/myname/Applications/Appname
/Users/myname/Library/Application Support/Appname
Other
I should say the App is Archive/Release built in Xcode and placed in destination directory for
Finder situation. Is this the right way? This is my first OSX App but I’ve been programming for
decades.
Permissions for Finder situation are
App: myname Read & Write, staff Read only, everyone Read only
binary file: myname Read & Write, staff Read & Write, everyone Read & Write
text files: myname Read & Write, staff Read & Write, everyone Read & Write
I’ve checked all the permissions in directory tree in Unix terminal also.
/Users/myname/…
Xcode versus Finder, what are the differences? regarding…
user name (byname)
group name (staff, root, admin)
working directory on startup
permissions on App and files (read, write, execute)
location of App and files
would /tmp location for file writing work?
where would be the best place to put App and files?
App working directory is changed by App to be where App and files are located.
Xcode -> Product -> Scheme -> Edit Scheme -> Options -> Working Directory set to same location.
This doesn’t help the Finder run situation.
A MS Windows version of this App works fine.
I have ported it, re-written it, for iMac OSX environment and it runs great in Xcode.
What is wrong with Finder case? Why can’t files be opened in output mode?
I’m thinking of re-writing the file i/o in objective-c style but it would be a pain and should not be
necessary. CString versus NSString is a big pain for me. I have had to use .mm and
objective- c++ source type to get this far.
Ideas welcome and thanks.
Full path names resolves all issues with running from Finder. Multiple directory locations were tried successfully. Awesome thanks to Paul R.
I am creating a sand-boxed application on MAC(10.9).When App Sand-boxed is off then i am able to get files and folders from any path. But when I does App Sand-boxed enabled it's not accessing any files and folders from any path.
Getting file and folder from path ("/Volumes/DriveName" or "/" etc.) when App Sand-boxed is off using Qt 5.0
// for folders
QStringList folderlist;
QDir curDir = QDir(path);
curDir.setFilter(QDir::Dirs);
QFileInfoList list = curDir.entryInfoList();
for(;<list.size;)
{
QfileInfo fileInfo = list.at(i);
folderList << fileInfo.filePath();
}
// for files
QStringList filelist;
QDirIterator dirIn(path,filterfiles,QDir::AllEnteries);
while(dirIn.hasnext())
{
dirIn.next();
QfileInfo fileInfo = dirIn.fileInfo();
filelist<< fileInfo.filePath();
}
What i do same when App sand-boxed is enabled?
That's the point of a sandbox, you can only access resources within the sandbox. A user may add files to the sandbox, but that requires your application to launch a file open dialog box, so they can choose the file they want to work with.
I suggest you start by reading the Apple documentation here.
Using the Xcode iOS Instruments UI Automation tuneup.js javascript library https://github.com/alexvollmer/tuneup_js .
I'm having challenges understanding the current working diretory of my launched instrument.
I have not been able to make a relative path to the tuneup/tuneup.js script. The destination of the relative path is of course "tuneup/tuneup.js". But what is the starting point?
Here's the code:
// This works:
#import "/Users/mikes/Documents/Full/Path/To/File/Tests/tuneup/tuneup.js"
// These do not work:
//#import "tuneup/tuneup.js"
//#import "Tests/tuneup/tuneup.js"
//
// See https://github.com/alexvollmer/tuneup_js
//
test("First Screen", function(target, app) {
var window = app.mainWindow();
window.logElementTree();
});
See tuneup.js reports "Can't find variable" for test() method for a related question.
-Thanks
-Mike
I'm willing to bet that the reason this isn't working is because you created an embedded script in the Instruments document. Instead of choosing "Add > Create Script" in the sidebar of instruments, you need to choose "Add > Import" and import your script file from the file system. That will link the Instruments document to your script file and when you use the #import keyword, it will look in the directory relative to where your script file resides.
Embedded (as opposed to imported) scripts do not have a "current directory" which is why you need to absolute path to the tuneup.js file.