I successfully test my in app purchase function and downloaded the content. However I am not sure of an right way to transfer it to Document folder. I tested with the code:
-(void)paymentQueue:(SKPaymentQueue *)queue updatedDownloads:(NSArray *)downloads
{
for (SKDownload *download in downloads)
{
switch (download.downloadState) {
case SKDownloadStateActive:
NSLog(#"Download progress = %f",
download.progress);
NSLog(#"Download time = %f",
download.timeRemaining);
break;
case SKDownloadStateFinished:
[self downloadFromURL:download.contentURL];///<--This is the function.
break;
}
}
}
-(void)downloadFromURL: (NSURL *) temporaryURL {
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;
NSFileManager *filemgr;
NSArray *filelist;
int count;
int i;
filemgr =[NSFileManager defaultManager];
filelist = [filemgr contentsOfDirectoryAtPath:folder error:NULL];
count = [filelist count];
NSLog(#"file count %i",count);
for (i = 0; i < count; i++)
NSLog(#"%#", filelist[i]);
}
I get a #"File successfully downloaded. Url is %#" from the code above but NSLog(#"%#", filelist[i]); give me no content. What else is missing here? I found out about this link
but not sure how to incorporate into my code. Any pointer will be good.
Let's check:
-(void)downloadFromURL: (NSURL *) temporaryURL {
// at this time, file is downloaded successfully???
// I think you should check here
NSURL * temporaryURL;
NSFileManager *fm = [NSFileManager defaultManager];
BOOL existed = [fm fileExistsAtPath:temporaryURL.path];
if(existed) // file is existed
else // file is not existed == maybe download fails
}
Related
I am downloading the resources from server and writing it to the documents directory successfully by using this code below
NSString *fileName = [[[NSURL URLWithString:url] path] lastPathComponent];
NSArray *pathArr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *folder = [pathArr objectAtIndex:0];
NSString *filePath = [folder stringByAppendingPathComponent:fileName];
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
NSLog(#"File written");
NSError *writeError = nil;
[webData writeToURL: fileURL options:0 error:&writeError];
if( writeError) {
NSLog(#" Error in writing file %#' : \n %# ", filePath , writeError );
return;
}
NSLog(#"%#",fileURL);
Now I want to access those files to use it.I have tried this code
-(UIImage *) loadImage:(NSString *)fileName ofType:(NSString *)extension inDirectory:(NSString *)directoryPath
{
UIImage * result = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:#"%#/%#.%#", directoryPath, fileName, extension]];
return result;
}
Now method used is like this:
UIImage *imageFromWeb = [self loadImage:#"metaioman" ofType:#"png" inDirectory:folder];
_imgview.image=imageFromWeb;
But no luck...please help
Thank you
Firstly check file exists using NSFileManager.
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *pathForFile = [NSString stringWithFormat:#"%#/%#.%#", directoryPath, fileName, extension]
UIImage * result = nil;
if ([fileManager fileExistsAtPath:pathForFile]){
//file exists
result = [UIImage imageWithContentsOfFile:pathForFile];
}
else
{
//file doesnot exists or wrong filename.
}
return result;
Reference : http://beageek.biz/save-and-load-uiimage-in-documents-directory-on-iphone-xcode-ios/
My folder contains only one sub-folder, and I don't know sub-folder's name. This sub-folder contains a html file, and once again I don't know the html file's name.
My question is how I can get full path of this file by using
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *folderPath = [documentsDirectory stringByAppendingPathComponent:filename];
//- access sub-folder?
//- access html file?
EDITED:
I wrote a method to return the only one sub-folder as follow:
+ (NSString*) get1stSubFolder:(NSString*)folder
{
NSDirectoryEnumerator *directoryEnumerator = [[NSFileManager defaultManager] enumeratorAtPath:folder];
//- no recursive
[directoryEnumerator skipDescendents];
NSString* file;
while (file = [directoryEnumerator nextObject])
{
BOOL isDirectory = NO;
BOOL subFileExists = [[NSFileManager defaultManager] fileExistsAtPath:file isDirectory:&isDirectory];
if (subFileExists && !isDirectory) {
return file;
}
}
return nil;
}
I always get nil as result. Do you know where was I wrong at?
Use NSDirectoryEnumerator. It should help you.
Use NSDirectoryEnumerator like this.
NSURL *documentsDirectoryURL = [NSURL URLWithString:NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0] ];
///If the folder you want to browse for subfolders is NSDocumentDirectory.
NSArray *keys = [NSArray arrayWithObject:NSURLIsDirectoryKey];
NSDirectoryEnumerator *enumerator = [[[NSFileManager alloc] init]
enumeratorAtURL:documentsDirectoryURL
includingPropertiesForKeys:keys
options:0
errorHandler:^(NSURL *url, NSError *error) {
return YES;
}];
for (NSURL *url in enumerator) {
NSError *error;
NSNumber *isDirectory = nil;
if (! [url getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:&error]) {
NSLog(#"Error %#",error);
}
else if ([isDirectory boolValue]) {
NSLog(#"Folder URL: %#",url);
}else{
NSLog(#"File URL: %#",url);
}
}
I have developed app in which i am downloading image from server and displaying in UITableView
App rejection reason
In particular, we found that on launch and/or content download, your app stores 2.67 MB. To check how much data your app is storing:
The iOS Data Storage Guidelines indicate that only content that the user creates using your app, e.g., documents, new files, edits, etc., should be backed up by iCloud.
Temporary files used by your app should only be stored in the /tmp directory; please remember to delete the files stored in this location when the user exits the app.
Data that can be recreated but must persist for proper functioning of your app - or because customers expect it to be available for offline use - should be marked with the "do not back up" attribute. For NSURL objects, add the NSURLIsExcludedFromBackupKey attribute to prevent the corresponding file from being backed up. For CFURLRef objects, use the corresponding kCFURLIsExcludedFromBackupKey attribute.
Here is my code shows how i am downloading data from server and displaying it:
- (BOOL)fileExist:(NSString *)name //Check's whether image Exists in Doc Dir.
{
BOOL theSuccess;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:name];
NSFileManager *fileManager = [NSFileManager defaultManager];
theSuccess = [fileManager fileExistsAtPath:fullPath];
if(theSuccess){
return YES;
} else {
return NO;
}
}
- (void)downloadFile:(NSString *)urlFile withName:(NSString *)fileName //If image not exists it will download image.
{
NSString *trimmedString = [urlFile stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if ([trimmedString length]>0)
{
HTTPEaterResponse *response = [HTTPEater get:[NSString stringWithFormat:#"%#",trimmedString]];
if ([response isSuccessful])
{
[self saveImage:[[UIImage alloc] initWithData:[response body]] withName:fileName];
}
}
}
-(void)saveImage:(UIImage *)image withName:(NSString *)name //After downloading image it stores in Doc dir.
{
NSString *pngPath = [NSHomeDirectory() stringByAppendingPathComponent:[#"Documents/" stringByAppendingString:name]];
[UIImagePNGRepresentation(image) writeToFile:pngPath atomically:YES];
}
- (UIImage *)loadImage:(NSString *)name //Used for displaying.
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:name];
UIImage *img = [UIImage imageWithContentsOfFile:fullPath];
return img;
}
Code for displaying data:
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
...
if ([dicImages valueForKey:[[msg_array objectAtIndex:indexPath.row] valueForKey:#"merchantimage"]])
{
cell.MerchntLogo.image=[dicImages valueForKey:[[msg_array objectAtIndex:indexPath.row] valueForKey:#"merchantimage"]];
}
else
{
if (!isDragging_msg && !isDecliring_msg)
{
if ([[[msg_array objectAtIndex:indexPath.row] valueForKey:#"merchantimage"] length]!=0)
{
[dicImages setObject:[UIImage imageNamed:#"rowDefault.png"] forKey:[[msg_array objectAtIndex:indexPath.row] valueForKey:#"merchantimage"]];
[self performSelectorInBackground:#selector(downloadImage_3:) withObject:indexPath];
}
}
else
{
cell.MerchntLogo.image=[UIImage imageNamed:#"rowDefault.png"];
}
}
...
}
-(void)downloadImage_3:(NSIndexPath *)path{
if ([[[msg_array objectAtIndex:path.row] valueForKey:#"merchantimage"] length]!=0)
{
NSString *str=[[msg_array objectAtIndex:path.row] valueForKey:#"merchantimage"];
UIImage *img = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:str]]];
[dicImages setObject:img forKey:[[msg_array objectAtIndex:path.row] valueForKey:#"merchantimage"]];
[tblProdDetail performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
}
}
Please help me figure out why my app has been rejected, and what I can do to rectify the problem.
Your app is clearly violating Apple's Data storage guidelines which states that only user-generated data should be stored in the Documents folder. This data is automatically backed up to iCloud and goes against the 5GB cap. If an app stores too much data in this folder (as deemed by Apple), then it can be rejected from the App Store.
Your data wont classify as user generated content and it exceeds 2 MB which is the limit.
You can prevent the data from being backed up by referring here.
https://developer.apple.com/library/ios/qa/qa1719/_index.html
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
const char* filePath = [[URL path] fileSystemRepresentation];
const char* attrName = "com.apple.MobileBackup";
u_int8_t attrValue = 1;
BOOL result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
return result;
}
You need to do what they a talking about. Mark files
Just add in didFinishLaunching
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentsDirectory = [paths objectAtIndex:0];
[self applyAttributes:documentsDirectory];
And then implements this methods
#pragma mark - Application's Documents directory
// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
-(void)applyAttributes:(NSString *)folderPath
{
NSArray *filesArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:folderPath error:nil];
NSEnumerator *filesEnumerator = [filesArray objectEnumerator];
NSString *fileName;
while (fileName = [filesEnumerator nextObject]) {
// NSLog(#"apply to %#", [[NSURL fileURLWithPath:[folderPath stringByAppendingPathComponent:fileName]] path]);
if([self addSkipBackupAttributeToItemAtURL:[NSURL fileURLWithPath:[folderPath stringByAppendingPathComponent:fileName]]])
{
//NSLog(#"success applying");
}
//NSDictionary *fileDictionary = [[NSFileManager defaultManager] attributesOfItemAtPath:[folderPath stringByAppendingPathComponent:fileName] error:nil];
//fileSize += [fileDictionary fileSize];
}
}
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
if([[NSFileManager defaultManager] fileExistsAtPath: [URL path]])
{
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;
}
return NO;
}
Use this method to bypass storing data on iCloud
Pass file path to this method
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
const char* filePath = [[URL path] fileSystemRepresentation];
const char* attrName = "com.apple.MobileBackup";
u_int8_t attrValue = 1;
BOOL result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
return result;
}
I want to retrieve in an array of the name of the files in Resources folder that have the .html extension. I have done this:
NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:#"Resources"];
NSError *error = nil;
NSArray *documentArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory error:&error];
for (int i=0; i < [documentArray count] - 1; i++) {
NSLog(#"value %#", [documentArray objectAtIndex:i]);
}
But the for loop displays continously null. Anyone knows how can I get this task right? thank you
Don't use NSHomeDirectory. Use [[NSBundle mainBundle] resourcePath] to get path to app's resources.
Edited: here's your example code.
NSString *resPath = [[NSBundle mainBundle] resourcePath];
NSError *error = nil;
NSArray *filenames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:resPath error:&error];
if (!error)
{
for (NSString * filename in filenames)
{
NSString *extension = [filename pathExtension];
if ([extension isEqualToString:#"html"])
{
NSLog(#"%#", filename);
}
}
}
I am trying to download image files and store in NSDocumentDirectory. In order to do so, I has to turn off data backup on iCloud and iTunes. Below are my codes:
+(void)saveData:(NSData*)thedata:(NSString*)fileName
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *localFilePath = [documentsDirectory stringByAppendingPathComponent:fileName];
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager createFileAtPath:localFilePath contents:thedata attributes:nil];
//prevent files from backup on iCloud or iTune
NSURL *fileURL = [NSURL URLWithString:localFilePath];
[self addSkipBackupAttributeToItemAtURL:fileURL];
}
and for my addskipbackupattributetoitematurl:
+(BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)fileURL
{
if (![[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]])
{
NSLog(#"File %# doesn't exist!",[fileURL path]);
return NO;
}
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer isEqualToString:#"5.0.1"])
{
const char* filePath = [[fileURL path] fileSystemRepresentation];
const char* attrName = "com.apple.MobileBackup";
u_int8_t attrValue = 1;
int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
NSLog(#"Excluded '%#' from backup",fileURL);
return result == 0;
}
else if (&NSURLIsExcludedFromBackupKey)
{
NSError *error = nil;
BOOL result = [fileURL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error];
if (result == NO)
{
NSLog(#"Error excluding '%#' from backup. Error: %#",fileURL, error);
return NO;
}
else
{
NSLog(#"Excluded '%#' from backup",fileURL);
return YES;
}
}
else
{
return YES;
}
}
However, the BOOL result = [fileURL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error]; created the following message
CFURLSetResourcePropertyForKey failed because it was passed this URL which has no scheme: /var/mobile/Applications/CF69D567-1D37-4053-BFA8-5D0FCBD9C2B2/Documents/coffee.jpg
I'm just wondering if any encountered this problem??
Solved. once I changed
NSURL *fileURL = [NSURL URLWithString:localFilePath];
to
NSURL *fileURL = [NSURL fileURLWithPath:localFilePath];
everything work perfectly.
Swift:
let fileURL = URL(fileURLWithPath: somepath)