Can't parse json Data via YAJLiOS - iphone

At first i'm trying to access local file in my app folder:
NSData *data = [NSData dataWithContentsOfFile:
[#"countries.json" stringByExpandingTildeInPath]];
result is always NULL
then i tried to check is file exists:
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString* foofile = [documentsPath stringByAppendingPathComponent:#"countries.json"];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:foofile];
it doesn't exist, and i use following code to access my json file:
NSString *data1 = [[NSBundle mainBundle] pathForResource:#"countries" ofType:#"json"];
NSData *data2 = [[NSData alloc] initWithContentsOfFile:data1];
it getting the file but when i try to parse it:
NSDictionary *dict1 =[data2 yajl_JSON];
i getting an error:
[NSConcreteData yajl_JSON]: unrecognized selector sent to instance 0x6838d60
My questions is next:
Is there any chance to convert NSData to NSConcreteData?
Am i using the right approach to access data?
Api documentation - http://gabriel.github.com/yajl-objc/
Screenshot of my Xcode Build Phases:

According to the YAJL documentation the method you are trying to invoke does in fact exist.
That leaves only one option; you have not fully linked against the YAJL framework.
Make sure it shows up within the list of linked frameworks/libraries of your App target just like CFNetwork.framework shows up in my example.
Since the method you are trying to invoke is in fact part of a category on NSData, make sure you include -ObjC in your Other Linker Flags.
From Apple's Technical Q&A.
This flag causes the linker to load every object file in the library
that defines an Objective-C class or category. While this option will
typically result in a larger executable (due to additional object code
loaded into the application), it will allow the successful creation of
effective Objective-C static libraries that contain categories on
existing classes.

Related

write into plist file using NSDictionary object

Sorry I saw similar questions but they don't seem to have some full answers for me. And i try to put it in order so that people will not hate me or my poor english.
I am working with Xcode 4.2 with storyboard and ARC
I can read from my plist file. My task is simply to write back the updated value(s) to my plist file.
My plist is contain in "supporting files" sub folder of the main folder (where story-board is things goes). the file is call Global.plist and GlobalValue2 is a element of the file type string.
So the read file part looks like this
NSString *plistfile = [[NSBundle mainBundle] pathForResource:#"Global" ofType:#"plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:plistfile];
FirstValueTextBox.text = [[dict valueForKey:#"GlobalValue1"] stringValue];
learn it from some handy youtube video works just fine. updates the value to my text box.
The real problem comes in when I write back my plist file. When i try the following
NSString *plistfile = [[NSBundle mainBundle] pathForResource:#"Global" ofType:#"plist"];
NSMutableDictionary *dict = [NSMutableDictionary
dictionaryWithContentsOfFile:plistfile];
[dict setValue:#"ABC" forKey:#"GlobalValue2"];
SecondValueTextBox.text = [dict valueForKey:#"GlobalValue2"];
[dict writeToFile:plistfile atomically:YES];
the result is I really saw a updated value pop up on the second text box, but the plist file remain unchanged.
The following are the break down of my questions and my guess for the problem
I try to use NSDictionary(not NSMutableDictionary) and call setValue (crash in runtime)
my guess: NSDictionary object itself is readonly so it crash me when i say add value. But why don't it error me when in coding time? if the object is readonly
I use NSMutableDictionary can call setValue. it doesn't crash me and when i call the updated value at "SecondValueTextBox.text = [dict valueForKey:#"GlobalValue2"];" it really return me the updated value. but the content inside of the plist file is not changed. Which is the result I have right now.
my guess: after some search here and there I think "supporting files" is read only too. pure guess did see anyone directly talk about it.
I did try to move on a little more and some people talks about a "document folder" in Xcode that is a read and write place. I think people also talk about write a code to access that folder. Can someone show me the code here.
My last question, can I hook up my Xcode to that "document folder" or where can i see it(the real file folder structure is different from inside Xcode I think). So that i can see and edit my plist file for testing, and i can see the real result without using codes and stuff
I will be much appreciated if people can tell me my guess is right or wrong and the answer to my 3 and 4 question.
In order for your changes to be persisted in your plist, you would indeed need ot copy it from the resource bundle to the documents dirtectory on launch of the application, then use the plist in the documents to read and write.
Here is how you can copy the file:
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:#"Global.plist"];
if ([fileManager fileExistsAtPath:plistPath] == NO) {
NSString *resourcePath = [[NSBundle mainBundle] pathForResource:#"Global" ofType:#"plist"];
[fileManager copyItemAtPath:resourcePath toPath:plistPath error:&error];
}

How to cache or store parsed xml file?

My app parses an xml file from my server, but I want to store parsed xml file and next start of my app, controller initially should load stored xml file, then controller should parse it again to check that there may be an update I did on xml file, if there is, new elements parsed should also be stored again.
I am referring to those app such as magazines, newspaper apps. When you open those kind of apps, it loads stored data that was downloaded previous session. Yet, after it loads, it starts to update the data, and it stores new update again.
Where do I start? What do you guys suggest?
Thanks in advance...
You can use CoreData or SQLite (use Objective-C wrapper FMDB https://github.com/ccgus/fmdb) to persist your XML. Then update the database everytime you see a unique id. Depends on how your XML data is.
It's actually quite easy to store to the documents directory. For example:
NSData *data; //this is your xml file
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docs = [paths objectAtIndex:0];
NSString *filename = [NSString stringWithFormat:#"test.xml"];
NSString *path = [docs stringByAppendingPathComponent:filename];
[data writeToFile:path atomically:YES];
Then to retrieve it later, you can get the path like above, but retrieve the file instead of writing it:
NSData *data = [NSData dataWithContentsOfFile:path];
either CoreData or SQLite can do the trick

NSKeyedUnarchiver: iPhone .v. Simulator

I'm doing:
NSString *current_path = [[NSBundle mainBundle] bundlePath];
NSString *string_path = [NSString stringWithFormat:
#"%#/filedstring", current_path];
my_string_ = [[NSKeyedUnarchiver unarchiveObjectWithFile:string_path] retain];
The archived string is the text from a UITextField which we unarchive here. I've tried with and without current_path.
This all works fine when running in simulator (class member NSString *my_string_ is not nil) but when run on my iPhone my_string_ is nil.
Why is that?
Thanks for the quick responses all.
Adding to Jason Coco's answer, archive to and unarchive here:
NSString *library_path = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
NSUserDomainMask, YES) objectAtIndex:0];
NSString *username_path = [library_path
stringByAppendingPathComponent:#"Caches/filedstring"];
You can't write into the main bundle on the phone, it's not allowed. That's why you don't find your archive there later. The simulator, since it actually runs on Mac OS X doesn't work this way, so it will actually write the file.
If you need to write something, you have to use one of the writeable paths available to your application. For more information, see the iOS Application Programming Guide / The File System. If you're going to do iOS Application Development, you should definitely read and understand this entire document.
As #middaparka says, there is probably something wrong with that file. Here's how I would debug this problem:
First step,
[[NSFileManager defaultManager] fileExistsAtPath: string_path];
Second step,
NSError *err;
NSString *tmp = [NSString stringWithContentsOfFile:string_path encoding:NSUTF8StringEncoding error:&err];
NSLog(#"Contents of string %#",tmp);
Once you've done those, you should have a much clearer idea why your NSKeyedUnarchiver is failing.
Also, check out NSString's stringByAppendingPathComponent: method.

read single line from text file in objective-C

i'm new to iPhone programming and coding in XCode SDK.I want to access and read the configuration file which i have placed in Resource folder in XCode,my configuration file looks like this
#key=value$
#vinu=flower$
#cathy=fruit$
I want to compare the key and access the value from configuration file.
Since i'm working with iPhone OS, i cant use NSWorkspace.Hence i'm using NSFileHandle.
This is how my code looks like,
NSString *path = [[NSBundle mainBundle] pathForResource:#"configuration" ofType:#"txt"];
NSFileHandle *readHandle = [NSFileHandle fileHandleForReadingAtPath:path];
NSString *txtString = [[NSString alloc] initWithData:
[readHandle readDataToEndOfFile] encoding:NSUTF8StringEncoding];
please let me know is the procedure correct, and how to proceed. ??
Thank You.
Do yourself a favor and save it as a plist, and not a straight text file.
However, if you need to read it in like that, the simplest way is to read it into a string and then go from there, ie:
NSString * fileContents = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
If the file is super large and the only reasonable way to read it is line-by-line, then you can quickly see that this is something that has come up before (Particularly: Objective-C: Reading a file line by line).

Loading data files in iPhone project

How does one read a data file in an iPhone project? For example, lets say I have a static file called "level.dat" that is structured as follows:
obstacles: 10
time: 100
obstacle1: 10,20
...
I would like to read the contents of the file into a NSString then do the parsing. How do I read the contents of a file into a string? Also, where in the project should the "level.dat" file reside? Should it be under "Resources" or just in the main directory?
Thanks in advance!
See this answer: How to fopen() on the iPhone? which shows how to get access to resources in your bundle. Once you have the path, just use [NSString stringWithContentsOfFile:encoding:error:].
NSString *path = [[NSBundle mainBundle] pathForResource: #"level" ofType: #"dat"]
NSError *error = nil;
NSString *data = [NSString stringWithContentsOfFile: path
encoding: NSUTF8StringEncoding
error: &error];
While this isn't what you asked for, consider turning your files into plists. You will have to reformat them into XML, but then you can load them straight into a NSDictionary with:
dict = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"levels" ofType:#"plist"]];
Have you considered putting the data in an SQLite database instead of a flat file? I find that the API is very easy to use on the iPhone.
It is how I do all of my data storage on the phone now.
If you need help parsing the data string, there's a helpful article on Cocoa For Scientist