I'm building an app which has non-consumable in-app purchases hosted on Apple's servers. I've been successful in getting my in-app purchases to download, but when I save them to the documents directory, I can't seem to locate or access them afterwards.
Here is the function I use to download the file from the download's contentURL. It is called after the download is completed, passing in download.contentURL to move it's location in the cache to the documents folder.
-(void)downloadFromURL: (NSURL *) temporaryURL {
NSLog(#"The download's contentURL is %#", temporaryURL.absoluteString);
NSString *folderName = [[temporaryURL path] lastPathComponent];
NSArray *pathArr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *folder = [pathArr objectAtIndex:0];
NSString *filePath = [folder stringByAppendingPathComponent:folderName];
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
NSError *writeError = nil;
NSData *downloadData = [[NSData alloc] initWithContentsOfURL:temporaryURL];
[downloadData writeToURL: fileURL options:0 error:&writeError];
if( writeError) {
NSLog(#"Error in writing file %#' : \n %# ", filePath , writeError);
return;
}
NSLog(#"File successfully downloaded. Url is %#",fileURL.absoluteString);
myFileURL = fileURL;
}
myFileURL is a global variable that is called upon later to initialize an AVAudioPlayer, but when I call
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:[myFileURL path]]){
NSLog(#"File DOES NOT exist at that url");
} else{
NSLog(#"File DOES exist at that url");
}
It says that a file does not exist at that path. Any ideas or simple ways to write and access in app purchase content downloaded from apple's servers? I've also tried adding "/Contents/filename.mp3" to the end of the URL to no avail.
Resolved using the code found here: http://xinsight.ca/blog/iap-content-download-in-ios6
Related
I'm writing an application for the Apple watch. I'm using the following method (from this SE answer) to write to a log file:
- (void) writeLogWith: (NSString *) content {
//Get the file path
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *fileName = [documentsDirectory stringByAppendingPathComponent:#"whathappened.md"];
//create file if it doesn't exist
if(![[NSFileManager defaultManager] fileExistsAtPath:fileName])
[[NSFileManager defaultManager] createFileAtPath:fileName contents:nil attributes:nil];
//append text to file (you'll probably want to add a newline every write)
NSFileHandle *file = [NSFileHandle fileHandleForUpdatingAtPath:fileName];
[file seekToEndOfFile];
[file writeData:[content dataUsingEncoding:NSUTF8StringEncoding]];
[file closeFile];
return;
}
I'm running it by plugging in my phone and running it directly on my watch. The function is definitely executing (I've stepped thought with the debugger) and it also knows that the file exists and doesn't repeatedly try and create it.
Xcode tells me that the file information is:
Printing description of documentsDirectory:
/var/mobile/Containers/Data/PluginKitPlugin/8503AD6C-6EC9-4522-A867-27109B01B615/Documents
Printing description of documentsDirectory:
(NSString *) documentsDirectory = 0x16d66890
Printing description of fileName:
(NSString *) fileName = 0x16d66950
Printing description of fileName:
/var/mobile/Containers/Data/PluginKitPlugin/8503AD6C-6EC9-4522-A867-27109B01B615/Documents/whathappened.md
I'd like to know if it's writing things correctly, but when I look at the container (following these SE answers), the documents directory is empty.
My question is: where did my file go? And how can I find it?
I think what might be giving you problems is the NSFileHandle object. I have written thousands upon thousands of files to the documents folder and I have never used NSFileHandle to do this. Simply use the built in method on NSString to write your string to the file path.
Try this:
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [[documentsDirectory stringByAppendingPathComponent:#"whathappened"] stringByAppendingPathExtension:#"md"];
if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
[[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
}
NSString *string = #"The String You Want To Write.";
NSError *error;
[string writeToFile:filePath atomically:false encoding:NSUTF8StringEncoding error:&error];
if (error) {
NSLog(#"There was an error writing file\n%#", error.localizedDescription);
}
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
NSLog(#"File exists :)");
}
else {
NSLog(#"File does not exist :(");
}
From other research, the answer appears to be:
If you are storing a file on the Apple Watch, it is stored in it's own container, which isn't visible via xcode.
It indeed, appears to be related to this bug report: https://openradar.appspot.com/radar?id=5021353337946112, found via this SE: How to export shared container of an iOS App with Xcode6.2?
I am trying to upload sqlite file on iCloud. I am using NSFileCoortinator for coping the file from one file to another file but schema of sqlite file is only get copied, I am not getting data in sqlite file….Also sometimes the data is appearing in the sqlite file on iCloud. I don’t understand why this is happening. Is this sqlite file issue or I did wrong in code. If anyone has solution please help me out.
-(void)uploadFile
{
//-------code for uploading data to icloud
NSArray *paths =
NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory,
NSUserDomainMask, YES);
NSString *applicationSupportDirectory = [paths firstObject]
NSString *str=[NSString stringWithFormat:#"%#/XMPPMessageArchiving.sqlite",applicationSupportDirectory]; //copy this file
NSString *fileName = [NSString stringWithFormat:#"XMPPMessageArchiving.sqlite"];
NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
NSURL *fromURL = [NSURL fileURLWithPath:str];
NSURL *toURL = [[ubiq URLByAppendingPathComponent:#"Documents"]
URLByAppendingPathComponent:fileName];;
[coordinator coordinateReadingItemAtURL:fromURL options:0 writingItemAtURL:toURL options:NSFileCoordinatorWritingForReplacing error:nil byAccessor:^(NSURL *newReadingURL, NSURL *newWritingURL)
{
NSError *error=nil;
NSData *data = [[NSFileManager defaultManager] contentsAtPath:fromURL.path];
//if file is already present on icloud replace that file with new file
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:newWritingURL.path];
if (fileExists)
{
[[NSFileManager defaultManager] removeItemAtPath:toURL.path error:NULL];
}
BOOL isCopied= [[NSFileManager defaultManager] copyItemAtPath:newReadingURL.path toPath:newWritingURL.path error:nil];
NSLog(#"file copied= %d",isCopied);
}];
}
The value for file copied is always 1 but still data is not available.
I am working on functionality to save video files in document folder of application in iOS.
How to rename some files programmatically?
try this code :
NSError * err = NULL;
NSFileManager * fm = [[NSFileManager alloc] init];
BOOL result = [fm moveItemAtPath:#"/tmp/test.tt" toPath:#"/tmp/dstpath.tt" error:&err];
if(!result)
NSLog(#"Error: %#", err);
other wise use this method to rename file
- (void)renameFileWithName:(NSString *)srcName toName:(NSString *)dstName
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePathSrc = [documentsDirectory stringByAppendingPathComponent:srcName];
NSString *filePathDst = [documentsDirectory stringByAppendingPathComponent:dstName];
NSFileManager *manager = [NSFileManager defaultManager];
if ([manager fileExistsAtPath:filePathSrc]) {
NSError *error = nil;
[manager moveItemAtPath:filePathSrc toPath:filePathDst error:&error];
if (error) {
NSLog(#"There is an Error: %#", error);
}
} else {
NSLog(#"File %# doesn't exists", srcName);
}
}
There is no Direct API to rename the file . Though when you move the file from one place to another place, if that file in destination path not exists then iOS will create the file in the given name. For file you can just give the New name of your file, how it should be displayed/referenced.
you could check this answer. Good luck!
I have file in my App bundle on iOS. How can I move it to be in Document folder?
Can this be done through some configuration or I need to make custom code for it?
By custom code I mean:
check is this first run of app:
if so, move files to the Document folder.
Please check out NSFileManager which allows you to copy files within the file system as required. You should be aware that Apple will reject your App if the copied file is not flagged to NOT backup to iCloud.
I use the following methods to copy a sqlite database from the bundle to a folder; it should work for your purpose with minor modification.
+ (void)copyBundleFileToStoresDirectory:(NSString *)filename
{
NSError *error;
NSURL *fileURL = [NSURL fileURLWithPath: [[NSBundle mainBundle] pathForResource:filename ofType:nil]];
NSURL *pathURL = [SVOFileSystemMethods documentsSubdirectory:#"Stores" skipBackup:YES];
if (fileURL)
{
if([[NSFileManager defaultManager] copyItemAtURL:fileURL toURL:pathURL error:&error])
{
// NSLog(#"File successfully copied");
}
else
{
[[[UIAlertView alloc]initWithTitle:NSLocalizedString(#"error", nil) message: NSLocalizedString(#"Failed to copy database from bundle.", nil)
delegate:nil cancelButtonTitle:NSLocalizedString(#"OK", nil) otherButtonTitles:nil] show];
NSLog(#"Error description-%# \n", [error localizedDescription]);
NSLog(#"Error reason-%#", [error localizedFailureReason]);
}
}
}
+ (NSURL *) documentsSubdirectory:(NSString *)subdirectoryName skipBackup:(BOOL) skipBackup
{
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:subdirectoryName]; //untested change here -- was literal #"/Stores"
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
{
[[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:YES attributes:nil error:&error]; //Create folder
NSURL *finalURL = [NSURL fileURLWithPath:dataPath];
if (skipBackup)
[SVOFileSystemMethods addSkipBackupAttributeToItemAtURL:finalURL]; // flag to exclude from backups.
return finalURL;
}
else
return [NSURL fileURLWithPath:dataPath]; // already existed
}
//
// flags URL to exclude from backup
//
+ (BOOL) addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
NSError *error = nil;
BOOL success = [URL setResourceValue: [NSNumber numberWithBool: YES]
forKey: NSURLIsExcludedFromBackupKey error: &error];
if(!success)
{
NSLog(#"Error excluding %# from backup %#", [URL lastPathComponent], error);
}
return success;
}
From what I understand, you can't "move" files from the app bundle to the app directory, since that requires deleting them from the bundle. You'll get an access denied, assuming your code is set up right.
You can "copy" files however, since that it simply a read.
In my case, I had a whole bunch of files that I wanted to move to the app's Library directory but was unable. Additionally, the copy operation was far too costly because of the quantity of files.
In this case, I changed the app logic to check for "fresh" information first (that I would save to the Library folder), & if it wasn't there then fall back to the App bundle to look for an old/original copy of the file.
I am new in ios developement .I have created a new appID and enabled iCloud on iTunes Connect.I have enabled entitlements within the app from the summary section. I have included this code for checking for iCloud availability:
NSURL *ubiq = [[NSFileManager defaultManager]
URLForUbiquityContainerIdentifier:nil];
if (ubiq) {
NSLog(#"iCloud access at %#", ubiq);
// TODO: Load document...
} else {
NSLog(#"No iCloud access");
}
i am getting iCloud access at something from nslog.
-(NSString *)getDocumentPath{
NSString * string = #"This is a Sample Text File";
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:#"Sample.txt"];
[string writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:NULL];
return filePath;
}