I have a Checklist app and I want to save the name of the items and if they are checked or not.
Xcode tells me that my saved file has to be here:
2012-11-11 20:24:42.726 Checklists[1459:c07] Documents directory /Users/astanciu/Library/Application Support/iPhone Simulator/6.0/Applications/F4A90B71-A8CF-4EF8-B628-508C8B50CAD0/Library/Documentation
2012-11-11 20:24:42.728 Checklists[1459:c07] File path /Users/astanciu/Library/Application Support/iPhone Simulator/6.0/Applications/F4A90B71-A8CF-4EF8-B628-508C8B50CAD0/Library/Documentation/Checklists.plist
But in the Library folder I have only Caches and Preferences. Can't find anywhere the Checklists.plist file using Finder.
I am using Mountain Lion 10.8 and Xcode 4.5.2.
Code:
-(void)saveChecklistItems
{
NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:items forKey:#"ChecklistItems"];
[archiver finishEncoding];
[data writeToFile:[self dataFilePath] atomically:YES];
}
-(id)initWithCoder:(NSCoder *)aDecoder
{
if(self = [super initWithCoder:aDecoder])
{
[self loadChecklistItems];
}
return self;
}
-(void)loadChecklistItems
{
NSString *path = [self dataFilePath];
if([[NSFileManager defaultManager] fileExistsAtPath:path])
{
NSData *data = [[NSData alloc] initWithContentsOfFile:path];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
items = [unarchiver decodeObjectForKey:#"ChecklistItems"];
}
else
{
items = [[NSMutableArray alloc] initWithCapacity:20];
}
}
Anyone has an idea what is the problem here ?
Thanks.
You don't show the code for determining self dataFilePath. It appears to reference Library/Documentation which is a non-standard directory.
Either you meant to use the NSDocumentDirectory constant instead of NSDocumatationDirectory in the code you have to determine the path, or you need to ensure that the directory exists before you try to write to it.
Related
I am trying to update an xml file. After suggestion I ended up choosing GdataXml.
So I am trying to update options.xml file.
Original File
<Dat>
<Name>Tom</Name>
<Option>1</Option>
</Dat>
I need to change "Tom" to "Jim" and save in the same file
Here is the code I tried.
-(void)saveToXML
{
NSString* path = [[NSBundle mainBundle] pathForResource:#"options" ofType:#"xml"];
NSData *xmlData = [[NSMutableData alloc] initWithContentsOfFile:path];
NSError *error;
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData options:0 error:&error];
GDataXMLElement *rootElement = [GDataXMLElement elementWithName:#"Dat"];
NSArray *mySettings = [doc.rootElement elementsForName:#"Dat"];
for (GDataXMLElement *mySet in mySettings)
{
NSString *name;
NSArray *names = [mySet elementsForName:#"Name"];
if (names.count > 0)
{
GDataXMLElement *childElement = (GDataXMLElement *) [names objectAtIndex:0];
name = childElement.stringValue;
NSLog(childElement.stringValue);
[childElement setStringValue:#"Jim"];
}
}
[xmlData writeToFile:path atomically:YES];
}
But this is not updating options.xml file. Can some one help on this ?
The missing line of code you are looking for is
NSData *xmlData = doc.XMLData;
from Anupdas answer on your last question. You are currently reading a file into memory, initializing a new object using that memory, updating that new object and then writing the original file's memory into the new file location. So essentially you are reading a file and then writing the same file back to the file location.
I searched a lot but can't open PDF with vfr-reader from documents folder.
NSString *filePath = #"/Users/***/Library/Application Support/iPhone Simulator/5.0/Applications/F2B7E9DE-9996-4F05-BC81-2A2889B4F504/Documents/Number1.pdf";
ReaderDocument *document = [ReaderDocument withDocumentFilePath:filePath password:password];
if (document != nil)
{// document comes nil here
ReaderViewController *readerViewController = [[ReaderViewController alloc] initWithReaderDocument:document];
readerViewController.delegate = self; // Set the ReaderViewController delegate to self
[self.navigationController pushViewController:readerViewController animated:YES];
}
I am sure that filepath is exact the pdf file.
In the example code of reader it opens the pdf from main bundle. But I need to open from resources folder.
Thanks
i facing same issue, may be you also have same one.
if you are not using ARC than just write -fobjc-arc to every pdf reader file in build face. that will solve your problem.
You should use [[NSBundle mainBundle] bundlePath] and stringByAppendingPathComponent: instead of hard-coding the string. This is quite horrible and will only ever work on the iOS Simulator.
You should give file name like below code,don't give directly
NSArray *pathss = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPaths = [pathss objectAtIndex:0];
NSString *filePaths = [documentsPaths stringByAppendingPathComponent:[NSString stringWithFormat:#"%#",fileName]];
I understand this is an old post but none the less I ran into a similar problem as #user1392687 and wanted to share how I resolved the issue (I was loading files from various directories not just the Documents folder).
Problem: Load a series of PDF files out of a directory, populate a table view with filenames and supporting meta data, then upon selecting a cell, open the PDF file using VFR Reader.
Solution: The folder within X-Code is a Folder Reference to enable content updates without having to perform the remove/add cycle of a Group Reference. The function below was used to read all contents - URLs - of a specific folder path then remove all/any simlinks contained within the returned file paths. Prior passing the URL into VRF to load the PDF file [url path] was used for a RFC 1808 (unescaped) path.
+ (NSArray *)enumerateContentsOfFolderWithPath:(NSURL *)aFolderPath
{
NSError *error = nil;
NSArray *contentProperties = #[NSURLIsDirectoryKey,
NSURLIsReadableKey,
NSURLCreationDateKey,
NSURLContentAccessDateKey,
NSURLContentModificationDateKey];
NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:aFolderPath
includingPropertiesForKeys:contentProperties
options:NSDirectoryEnumerationSkipsHiddenFiles
error:&error];
if (error != nil)
DLog(#"Content enumeration error: %#", error);
NSMutableArray *pdfURLs = [NSMutableArray array];
for (NSURL *item in contents)
{
NSURL *fileURL = [NSURL fileURLWithPath: [item path]];
NSURL *noSimlink = [fileURL URLByResolvingSymlinksInPath];
[pdfURLs addObject: noSimlink];
}
return pdfURLs;
}
After populating the table view with the contents of the folder and all supporting metadata, and upon a user touching a row to view the PDF file, the VRF Reader was setup as follows:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Other setup code...
NSURL *item = [pdfURLs objectAtIndex:(NSUInteger) indexPath.row];
[self presentPdfViewerForItem: item];
}
- (void)presentPdfViewerForItem:(NSURL *)aItem
{
NSString *phrase = nil; // Document password (for unlocking most encrypted PDF files)
NSString *filePath = [aItem path];
ReaderDocument *document = [ReaderDocument withDocumentFilePath: filePath password:phrase];
if (document != nil) // Must have a valid ReaderDocument object in order to proceed
{
ReaderViewController *readerViewController = [[ReaderViewController alloc] initWithReaderDocument:document];
readerViewController.delegate = self;
readerViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
readerViewController.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:readerViewController animated:YES completion:nil];
}
}
I know there are a multitude of questions about this on SO but I can't see where I am making the mistake and am hoping some extra eyes will help. I've verified the plist is in my bundle and it is also in my docs directory and it contains data. Here's a screen capture of the app package with the plist at top:
I pass the plist in from another class and have verified that it is the correct plist.
Here's my code:
-(id)init {
if (self = [super init]) {
//set up the appTracker
appTracker = [[OAI_AppTracker alloc] init];
//set up a file manager and error container
fileManger=[NSFileManager defaultManager];
//docs directory path
documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
//track event
appTracker.appEvent = #"File Manager initialized";
[appTracker recordEvent];
}
return self;
}
- (NSDictionary* ) readPlist {
NSError* error;
//set up dictionary to hold our app data
NSDictionary* appData;
//set up destination path
NSString* destinationPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#", plistToRead]];
if ([fileManger fileExistsAtPath:destinationPath]){
//read plist
appData = [[NSDictionary alloc] initWithContentsOfFile:destinationPath];
} else {
//file doesn't exist so we have to move it to the doc folder
NSString *sourcePath=[[[NSBundle mainBundle] resourcePath]stringByAppendingPathComponent:plistToWrite];
[fileManger copyItemAtPath:sourcePath toPath:destinationPath error:&error];
//now read the plist
appData = [[NSDictionary alloc] initWithContentsOfFile:destinationPath];
}
NSLog(#"%#", appData);
return appData;
}
My log shows NULL instead of the data in the plist. Appreciate any help as to what I am doing wrong.
To read your plist try something like this:
NSString *plistPath = [[NSBundle mainBundle] pathForResource:#"PlistFileName" ofType:#"plist"];
NSDictionary *plistData = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
I usually encode my data in a NSFileWrapper like this (I leave out the NSFileWrapper bit):
-(NSData*)encodeObject:(id<NSCoding>)o {
#autoreleasepool {
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:o forKey:#"data"];
[archiver finishEncoding];
return data;
}
}
And I usually get my data back when doing this:
- (id)decodeObjectFromWrapperWithPreferredFilename:(NSString *)p {
NSFileWrapper *wrapper = [self.fileWrapper.fileWrappers objectForKey:p];
if (!wrapper) {
NSLog(#"Unexpected error: Couldn't find %# in file wrapper!", p);
return nil;
}
NSData *data = [wrapper regularFileContents];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
NSLog(#"%#", [unarchiver decodeObjectForKey:#"data"]);
return [unarchiver decodeObjectForKey:#"data"];
}
Sometimes, I get NSData back (it is not nil), but [unarchiver decodeObjectForKey:#"data"] will return NIL. It appears as if there is no object for the key #"data" even though there should be. I guess something must have gone wrong when encoding, but I'm not sure how to trouble shoot this. Can I just take whatever is in data and encode it, not worrying if it has got the right key? I mean there should only ever be one key "data".
Why is your code so complicated :) The NSKeyedArchiver class has helper methods that will do what you want more simply :
// to turn an object into NSData
return [NSKeyedArchiver archivedDataWithRootObject:o];
// To turn NSData into your object again
return [NSKeyedUnarchiver unarchiveObjectWithData:data];
This is my code: (customNames and customNamesArray are static variables)
-(void) loadCustomDataFromDisk
{
NSString *fullPath = [self filePathAndFileName: #"customData.plist"];
if ( ![[NSFileManager defaultManager] fileExistsAtPath: fullPath] )
{
NSLog(#"Loading file fails: File not exist");
customNames = [[NSMutableDictionary alloc] init];
customNamesArray = [[NSMutableArray alloc] init];
}
else
{
NSMutableDictionary *customItems = [[NSMutableDictionary alloc] initWithContentsOfFile: fullPath];
customNames = [customItems objectForKey: #"customNamesDict"];
customNamesArray = [customItems objectForKey: #"customNamesArray"];
if (!customItems)
NSLog(#"Error loading file");
[customItems release];
}
}
-(void) saveCustomDataToDisk
{
NSString *path = [self filePathAndFileName: #"customData.plist"];
NSMutableDictionary *customItems = [[NSMutableDictionary alloc] init];
[customItems setObject: customNames forKey: #"customNamesDict"];
[customItems setObject: customNamesArray forKey: #"customNamesArray"];
BOOL success;
success = [customItems writeToFile:path atomically:YES];
if (!success)
NSLog(#"Error writing file: customDataDict.plist");
[customItems release];
}
According to Build and Analyze, I have a potential leak in loading customItems
NSMutableDictionary *customItems = [[NSMutableDictionary alloc] initWithContentsOfFile: fullPath];
true enough, according to Instruments, I do have a leak in that part. But when I tried release or autoreleasing customItems, my app crashes. Even if I change NSMutableDictionary to NSDictionary, I still have the leak.
How do I fix this?
Any help would be very much appreciated. :) Thanks :)
You have to retain customNames and customNamesArray because you are using reference from dictionary customItems and after passing reference you are releasing it.
customNames = [[customItems objectForKey: #"customNamesDict"] retain];
customNamesArray = [[customItems objectForKey: #"customNamesArray"] retain];
Now you can release customItems.
Your code is right as I can see. You can see answer here and may be it helps - Leak problem with initWithContentsOfFile
I have only one question: You create NSString *fullPath and never release it. Is it autoreleased string? If so - your code is fine.