Question on retrieving information on file in application directory? - iphone

i have a program which i can download a video file from a server to the app's directory but how do i retrieve the information about this file (mp4). I would like know the size of that file and it there a way to know when the file is being created as in a date or time? Thanks in advance

NSError *error = nil;
NSDictionary *fileInfo = [[NSFileManager defaultManager] attributesOfItemAtPath: filePath error: &error];
if ( fileInfo ) {
// examine fileInfo, see NSDictionary (NSFileAttributes) in NSFileManager.h
} else {
// handle the error
}

Related

startDownloadingUbiquitousItemAtURL local file path?

Where does startDownloadingUbiquitousItemAtURL:error method save downloaded file in local?
Is it the same as given URL?
Yes , its the same URL
The file in place before it downloads from iCloud to the device is a placeholder of sorts.
You can check the status of the URL with the key NSURLUbiquitousItemIsDownloadedKey
NSURL *foo = file://cloud/container/reference/tofile;
NSNumber *isDownloadedValue = NULL;
BOOL success = [foo getResourceValue:&isDownloadedValue forKey: NSURLUbiquitousItemIsDownloadedKey error:NULL];
if (success && ![isDownloadedValue boolValue]) {
[[NSFileManager defaultManager] startDownloadingUbiquitousItemAtURL:foo error:NULL];
}
Theres no error handling in that snippet which you will want to do in production code.

Parsing Local XML File Works, Downloaded XML File Doesn't

I have this problem when I fetch an XML file from the internet and then parse it, where I get this error:
Error while parsing the document: Error Domain=SMXMLDocumentErrorDomain Code=1 "Malformed XML document. Error at line 1:1." UserInfo=0x886e880 {LineNumber=1, ColumnNumber=1, NSLocalizedDescription=Malformed XML document. Error at line 1:1., NSUnderlyingError=0x886e7c0 "The operation couldn’t be completed. (NSXMLParserErrorDomain error 5.)"}
Here is an extract from the code (I believe I am only showing the most relevant code, if you need more, please ask.)
// Create a URL Request and set the URL
NSURL *url = [NSURL URLWithString:#"http://***.xml"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// Display the network activity indicator
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
// Perform the request on a new thread so we don't block the UI
dispatch_queue_t downloadQueue = dispatch_queue_create("Download queue", NULL);
dispatch_async(downloadQueue, ^{
NSError* err = nil;
NSHTTPURLResponse* rsp = nil;
// Perform the request synchronously on this thread
NSData *rspData = [NSURLConnection sendSynchronousRequest:request returningResponse:&rsp error:&err];
// Once a response is received, handle it on the main thread in case we do any UI updates
dispatch_async(dispatch_get_main_queue(), ^{
// Hide the network activity indicator
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
if (rspData == nil || (err != nil && [err code] != noErr)) {
// If there was a no data received, or an error...
NSLog(#"No data received.");
} else {
// Cache the file in the cache directory
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString* path = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"init.xml"];
//NSLog(#"%#",path);
[[NSFileManager defaultManager] removeItemAtPath:path error:nil];
[data writeToFile:path atomically:YES];
//NSString *sampleXML = [[NSBundle mainBundle] pathForResource:#"sample" ofType:#"xml"];
NSData *data = [NSData dataWithContentsOfFile:path];
// create a new SMXMLDocument with the contents of sample.xml
NSError *error;
SMXMLDocument *document = [SMXMLDocument documentWithData:data error:&error];
// check for errors
if (error) {
NSLog(#"Error while parsing the document: %#", error);
// return;
}
Firstly, I have connected the iPhone to an XML feed which it has fetched and written to the path of the variable path. Then I check for errors in the XML document and I get that error every time.
However, if I use a local XML file which I have placed in the main folder of my application there is no problem fetching all the data.
Using the code:
NSString *sampleXML = [[NSBundle mainBundle] pathForResource:#"sample" ofType:#"xml"];
So does anyone have an idea as to what I can have done wrong? It seems as if it doesn't download and store the XML file to the iPhone's cache, however NSLog(); seems to show it differently. Obviously the local file is the same as the file on the internet.
Furthermore, I already tried to save the file to the path without any results, though.
A couple of observations:
The key issue would appear to be that you retrieved the data in rspData, but when you write it to your temporary file, you're writing data, not rspData. So change the line that says:
[data writeToFile:path atomically:YES];
to
[rspData writeToFile:path atomically:YES];
Frankly, I don't even see the data variable defined at that point (do you have some ivar lingering about?). I'd be ruthless about getting rid of any ivars or other variables that you don't need, so that you don't accidentally refer to some unused variable. Anyway, just use the rspData that you retrieved rather than some other variable.
Why are you even writing that to a file, only to then read the file into another NSData that you pass to your XML parser? That seems entirely unnecessary. Just go ahead and use the rspData you initially retrieved. If you want to save the NSData to a file so you can examine it later for debugging purposes, that's fine. But there's no point in re-retrieving the NSData from the file, as you already have it in a rspData already.
If you encounter these errors in the future, feel free to examine the contents of the NSData variable with a debugging line of code, something like:
NSLog(#"rspData = %#", [[NSString alloc] initWithData:rspData encoding:NSUTF8StringEncoding]);
When you do that, you can look at the string rendition of the NSData, and usually the problem will become self evident.
As a complete aside, in your debugging error handler, you have a line that says:
NSLog(#"No data received.");
I might suggest you always include any errors that might be provided, e.g.:
NSLog(#"No data received: error = %#", err);
iOS provides useful error messages, so you should avail yourself of those.

Renaming and moving file using NSFIleManager

This is my code to rename and move file from a temporary directory to My Documents directory.
So the problem is within two sections of mode Create a Directory and Attempt to move. The rest all is working correctly..
When I comment out the Create directory section, the Attempt to Move section logs in the console:
Unable to Move the File..Error Code 4.
Now I researched error code 4 and it means that the directory does not exist. So I added the code to create the directory.
Now when I run the program the directory is created but the Attempt to Move section logs:
Unable to Move File..error code 512
Now researching on it it is due to the file already exists. The destination must not exist.
So I am pretty confused, since both error codes are contracting each other.
{
NSError *error;
NSFileManager* manager = [[NSFileManager alloc] init];
NSString* tempFile =[NSTemporaryDirectory() stringByAppendingPathComponent:#"recordTest.caf"];
if (tempFile)
{
// Get the Documents Directory
NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSLog(#"Documents directory: %#",
[manager contentsOfDirectoryAtPath:documentsDirectory error:&error]);
//Get the User File Save Name from the text field
NSString *UserText = [[self FileNameText] text];
// Rename the file, by moving the file
NSString *filePath2 = [documentsDirectory
stringByAppendingPathComponent:[NSString stringWithString:UserText]];
// Create a Directory
if( [manager createDirectoryAtPath:[NSString stringWithFormat:#"%#/%#",documentsDirectory,UserText] withIntermediateDirectories:NO attributes:nil error:&error]!= YES)
{
NSLog(#"Directory error");
}
if([manager fileExistsAtPath:[NSString stringWithFormat:#"%#/%#",documentsDirectory,UserText]])
{
NSLog(#"Path exist");
NSLog(#"Documents directory: %#",
[manager contentsOfDirectoryAtPath:documentsDirectory error:&error]);
}
// Attempt the move
if ([manager moveItemAtPath:tempFile toPath:filePath2 error:&error] != YES)
{
NSLog(#"Unable to move file: %#", [error localizedDescription]);
}
else
{
if ([manager removeItemAtPath:tempFile error:&error] != YES)
NSLog(#"Unable to delete file: %#", [error localizedDescription]);
}
}
[manager release];
}
The problem is most likely that the file you are trying to move doesn't exist.
replace
if (tempFile) //this will return YES every time, telling you you have a string!
with
if ([manager fileExistsAtPath:tempFile]) //this will tell you if the file exists at that path
A few notes
1. To see with your eyes if the file you are looking for really exists, check the simulator application folders at something similar to this:
/Users/yogevshelly/Library/Application\ Support/iPhone\
Simulator/5.0/Applications
then browse to a specific application
2. Don't just append strings to get folders , do something like this:
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [dirPaths objectAtIndex:0];
3. The following line will create a folder with the file's name as the folders name!:
[manager createDirectoryAtPath:filePath2 withIntermediateDirectories:NO attributes:nil error:&error]
creating a folder from a filename seems weird, what you want to do is either copy the file to an existing directory or first create a directory and copy the file into-it
you use the metod
contentsOfDirectoryAtPath: withIntermediateDirectories: attributes:error
this method create directory but you pass it the filename.
i think you create /Documents/filename/ instead of /Documents/filename
As per my understanding the problem part of the code is following one
// Create a Directory
if( [manager createDirectoryAtPath:[NSString stringWithFormat:#"%#/%#",documentsDirectory,UserText] withIntermediateDirectories:NO attributes:nil error:&error]!= YES)
{
NSLog(#"Directory error");
}
You are creating a folder in with the file name in same location .... try commenting the the above code .. it should work.

Write data to a file without removing the old contents in iPhone

I want to write data to a .txt file without replacing its older contents.I have moved the file from the NSMainBundle to the documents directory.I am able to write the the file by using the code
NSData *data=[NSKeyedArchiver archivedDataWithRootObject:recentMainArray];
NSFileHandle *myHandle = [NSFileHandle fileHandleForUpdatingAtPath:filePath];
[myHandle seekToEndOfFile];
[myHandle writeData:data];
[myHandle closeFile];
But when i try to display the contents of the file,i don't have any data in that.File exists in that path also.This is the following code i use to display the contents.
NSFileManager *manager = [NSFileManager defaultManager];
//filePath - > the documents directory file path
if([manager fileExistsAtPath:filePath]) {
NSMutableArray *savedArray = [[NSMutableArray alloc] initWithContentsOfFile:filePath];
NSMutableArray *storedRecentID = [savedArray objectAtIndex:0];
NSMutableArray *storedRecentName = [savedArray objectAtIndex:1];
NSLog(#"ID:%#",[savedArray objectAtIndex:0]);
NSLog(#"Name:%#",[savedArray objectAtIndex:1]);
}
else {
NSLog(#"file not found, save something to create the file");
}
"null" which is printed as result for those two nslogs.
Please anybody let me know a solution for this problem.FYI,i am using a simulator to test,is this creating a problem.Please suggest me a solution.I have searched a lot and i am not able to find a solution.
Thank you all in advance
Read the data into some Mutable structure (dictionary, array, string) and then append your new data into the same satring. Now write the data into the same path. So the new appended data will be written in file.

Where would you place your SQLite database file in an iPhone app?

When I initially create an SQLite database file with pre-inserted datasets for my application, I would have to place this file somewhere in my Xcode project so that it goes to my iPhone application. I guess "ressources" is the right place for that.
What are the basic "steps" for deployment of an SQLite database file in an iPhone application?
creating the database manually
adding the database file to the project (where?)
I'm currently reading the whole SQLite documentation, although that's not much iPhone related.
You need to add the SQLite file to your Xcode project first - the most appropriate place is in the resources folder.
Then in your application delegate code file, in the appDidFinishLaunching method, you need to first check if a writable copy of the the SQLite file has already been created - ie: a copy of the SQLite file has been created in the users document folder on the iPhone's file system. If yes, you don't do anything (else you would overwrite it with the default Xcode SQLite copy)
If no, then you copy the SQLite file there - to make it writable.
See the below code example to do this: this has been taken from Apple's SQLite books code sample where this method is called from the application delegates appDidFinishLaunching method.
// Creates a writable copy of the bundled default database in the application Documents directory.
- (void)createEditableCopyOfDatabaseIfNeeded {
// First, test for existence.
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:#"bookdb.sql"];
success = [fileManager fileExistsAtPath:writableDBPath];
if (success)
return;
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"bookdb.sql"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
if (!success) {
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
}
============
Here's the above code in Swift 2.0+
// Creates a writable copy of the bundled default database in the application Documents directory.
private func createEditableCopyOfDatabaseIfNeeded() -> Void
{
// First, test for existence.
let fileManager: NSFileManager = NSFileManager.defaultManager();
let paths:NSArray = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentsDirectory:NSString = paths.objectAtIndex(0) as! NSString;
let writableDBPath:String = documentsDirectory.stringByAppendingPathComponent("bookdb.sql");
if (fileManager.fileExistsAtPath(writableDBPath) == true)
{
return
}
else // The writable database does not exist, so copy the default to the appropriate location.
{
let defaultDBPath = NSBundle.mainBundle().pathForResource("bookdb", ofType: "sql")!
do
{
try fileManager.copyItemAtPath(defaultDBPath, toPath: writableDBPath)
}
catch let unknownError
{
print("Failed to create writable database file with unknown error: \(unknownError)")
}
}
}
If you're just going to be querying for data, you should be able to leave it in the main bundle.
This, however, is probably not a good practice. If you were to extend your application in the future to allow for database writing, you'd have to figure everything out again...