PDA

View Full Version : Saving an Array into .plist File.




TalShani
Jul 26, 2010, 04:58 AM
Hey guys,
I have a View-Based application.
There I have a TextView, with some text, and a button that when I press it,
it loads an UIAlertView.
I customized the AlertView to have a text field,
The alert also have 2 buttons, Cancel, and Submit.
I built some code that when I press the button "Submit",
The app will save an array, that contains the TextView,
and the TextField that in the Alert.
The code:

- (NSString *) savePath
{
NSArray *pathArray =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [[pathArray objectAtIndex:0] stringByAppendingPathComponent:@"save.plist"];
}

- (IBAction) saveMe
{
UIAlertView *myAlertView = [[UIAlertView alloc] initWithTitle:@"How would you like to call to your story?"
message:@"-" delegate:self
cancelButtonTitle:@"Cancel" otherButtonTitles:@"Save", nil];
UITextField *myTextField = [[UITextField alloc] initWithFrame:CGRectMake(12.0, 70.0, 260.0, 20.0)];
[myTextField setBackgroundColor:[UIColor whiteColor]];
[myAlertView addSubview:myTextField];
myTextField.font = [UIFont fontWithName:@"Arial" size: 15.0];
myTextField.text = nameForSave;
[myAlertView show];
[myTextField release];
[myAlertView release];
}
- (void)alertView:(UIAlertView *)myAlertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
NSLog(@"cancel");
}
else
{
NSLog(@"save");
NSArray *values = [[NSArray alloc] initWithObjects:result.text,nameForSave,nil];
[values writeToFile:[self savePath] atomically:YES];
[values release];
}
}

- result.text = TextView.
Somehow, when I'm trying to run it, Its giving me the error (on console):
2010-07-26 12:50:51.704 saveTest[8080:207] save
wait_fences: failed to receive reply: 10004003
And when I'm checking on the .plist file it not showing anything.
Hope you will answer me as soon as possible, Tal Shani.
* Sorry if there is any typos.



robbieduncan
Jul 26, 2010, 05:14 AM
When you say "result.text = TextView" what exactly do you mean? That it's a UITextView (if so please use the correct class names, accuracy in imperative). If so this is a problem: you cannot serialise arbitrary objects into a plist. You can only save the well documented plist types (http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/NSArray.html#//apple_ref/occ/instm/NSArray/writeToFile:atomically:) into a plist. If you are trying to encode the object look at NSCoder (http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSCoder_Class/Reference/NSCoder.html)

TalShani
Jul 26, 2010, 05:41 AM
When you say "result.text = TextView" what exactly do you mean? That it's a UITextView (if so please use the correct class names, accuracy in imperative). If so this is a problem: you cannot serialise arbitrary objects into a plist. You can only save the well documented plist types (http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/NSArray.html#//apple_ref/occ/instm/NSArray/writeToFile:atomically:) into a plist. If you are trying to encode the object look at NSCoder (http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSCoder_Class/Reference/NSCoder.html)
Oh, sorry, I meant UITextView,
And what do you mean?
I thought that I can write to .plist file an array as the same way I'm loading an array from it,
Can you please explain me the problem in more specific explanation?
I didn't understand the sentence : you cannot serialize arbitrary objects into a plist, what do you mean?
I've read the documentation again, and I can see any problem with my code,
It says the classes works with WriteToFile is:
NSString, NSData, NSArray, or NSDictionary
My array is using NSString, so I can't find any problem with it.
Thanks again, Tal.

robbieduncan
Jul 26, 2010, 05:45 AM
I cannot explain it any more clearly that I have. If results.text is a UITextView then adding that to an array means it cannot be saved to a plist. You say it's an NSString which leads me to believe that results is a UITextView, not results.text. Again if this is the case you must be more precise and accurate. Expecting us to guess what you really mean when you type one thing and mean another is not a good way to go about getting help.

TalShani
Jul 26, 2010, 05:57 AM
I cannot explain it any more clearly that I have. If results.text is a UITextView then adding that to an array means it cannot be saved to a plist. You say it's an NSString which leads me to believe that results is a UITextView, not results.text. Again if this is the case you must be more precise and accurate. Expecting us to guess what you really mean when you type one thing and mean another is not a good way to go about getting help.

result is a UITextView, how do you recommend to write it
into an array and it will work out just fine?

robbieduncan
Jul 26, 2010, 06:36 AM
result is a UITextView,

So why write "result.text = TextView"? result.text is a NSString.

A quick Google of the message indicates a number of potential solutions (http://www.iphonedevsdk.com/forum/iphone-sdk-development-advanced-discussion/17373-wait_fences-failed-receive-reply-10004003-a.html).

TalShani
Jul 26, 2010, 07:58 AM
So why write "result.text = TextView"? result.text is a NSString.

A quick Google of the message indicates a number of potential solutions (http://www.iphonedevsdk.com/forum/iphone-sdk-development-advanced-discussion/17373-wait_fences-failed-receive-reply-10004003-a.html).

Already tried it, won't work.
Same error, it doesn't change anything.

robbieduncan
Jul 26, 2010, 08:12 AM
Then start simplfying what you have till you find the error. This is very basic debugging. Any competent programmer should be able to work this backwards. I'd start be removing all your extra views from the UIAlertView...

TalShani
Jul 26, 2010, 11:03 AM
Then start simplfying what you have till you find the error. This is very basic debugging. Any competent programmer should be able to work this backwards. I'd start be removing all your extra views from the UIAlertView...

I did exactly what you said,
I started removing all the data until I got only the saving command,
Then I created NSLog's all over the app, so I will know what happens at every time,
I discovered that the issue is on the saving command:

- (NSString *) savePath
{
NSArray *pathArray =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
return [[pathArray objectAtIndex:0] stringByAppendingPathComponent:@"stories.plist"];
}
- (IBAction) saveMe
{
stringByAppendingPathComponent:@"stories.plist"];
NSLog(@"save");
NSArray *values = [[NSArray alloc] initWithObjects:takeText.text,nil];
[values writeToFile:[self savePath] atomically:YES];
[values release];
}

Can you see any problem with the saving commands?
Hope to here from you soon,
Tal.

robbieduncan
Jul 26, 2010, 11:06 AM
What is this in saveMe:

stringByAppendingPathComponent:@"stories.plist"];

TalShani
Jul 26, 2010, 11:29 AM
What is this in saveMe:

stringByAppendingPathComponent:@"stories.plist"];

Its part of the path deceleration.

robbieduncan
Jul 26, 2010, 11:33 AM
Its part of the path deceleration.

It is not compilable. It is not legal Objective-C. Either copy and paste the exact complete code you are using or accept that we are left guessing and cannot help.

TalShani
Jul 26, 2010, 12:08 PM
It is not compilable. It is not legal Objective-C. Either copy and paste the exact complete code you are using or accept that we are left guessing and cannot help.

I gave you to full code twice, plus the code of the error,
All the things that I published it is the entire code.

dejo
Jul 26, 2010, 01:06 PM
robbieduncan is referring to the first line of your saveMe method (highlighted in red below):
- (IBAction) saveMe
{
stringByAppendingPathComponent:@"stories.plist"];
NSLog(@"save");
NSArray *values = [[NSArray alloc] initWithObjects:takeText.text,nil];
[values writeToFile:[self savePath] atomically:YES];
[values release];
}
This is not a valid Objective-C statement and your code will not compile. What is it doing here?

TalShani
Jul 26, 2010, 01:11 PM
robbieduncan is referring to the first line of your saveMe method (highlighted in red below):
- (IBAction) saveMe
{
stringByAppendingPathComponent:@"stories.plist"];
NSLog(@"save");
NSArray *values = [[NSArray alloc] initWithObjects:takeText.text,nil];
[values writeToFile:[self savePath] atomically:YES];
[values release];
}
This is not a valid Objective-C statement and your code will not compile. What is it doing here?

Oh, I guess I had copy problem, this is the SaveMe action :
NSLog(@"save");
NSArray *values = [[NSArray alloc] initWithObjects:takeText.text,nil];
[values writeToFile:[self savePath] atomically:YES];
[values release];
And this is the file path statement :
- (NSString *) savePath
{
NSArray *pathArray =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [[pathArray objectAtIndex:0] stringByAppendingPathComponent:@"stories.plist"];
}

dejo
Jul 26, 2010, 01:19 PM
Alright. Now with the stripped down code, what exact problems are you seeing / what is not working?

TalShani
Jul 26, 2010, 01:32 PM
Alright. Now with the stripped down code, what exact problems are you seeing / what is not working?

It needs to add an array into .plist file (like 2 new objects),
It doesn't save it, no error, just don't work.

dejo
Jul 26, 2010, 01:41 PM
It needs to add an array into .plist file (like 2 new objects)...
First of all, you are only supplying 1 object to your array (takeText.text), not 2.
Second, what do you mean by "adding an array into .plist"? Are you trying to append that information into an existing .plist?

It doesn't save it, no error, just don't work.
Then you need to follow robbieduncan's advice and start applying basic debugging methods to figure out why. Perhaps start by actually capturing the BOOL that writeToFile:atomically: returns and seeing if it is YES or NO.

TalShani
Jul 27, 2010, 04:00 AM
First of all, you are only supplying 1 object to your array (takeText.text), not 2.
Second, what do you mean by "adding an array into .plist"? Are you trying to append that information into an existing .plist?


Then you need to follow robbieduncan's advice and start applying basic debugging methods to figure out why. Perhaps start by actually capturing the BOOL that writeToFile:atomically: returns and seeing if it is YES or NO.

I already debugged, That's how I discovered that the save doesn't work.
And yes, I need to add into an existing .plist the the array (stories.plist).

dejo
Jul 27, 2010, 10:09 AM
I already debugged, That's how I discovered that the save doesn't work.
That's not really debugging. You discovered the code doesn't work as expected. Debugging is discovering why / where the code doesn't work as expected.

So, what have you done (please be specific) to determine the cause of the problem you are encountering?

And yes, I need to add into an existing .plist the the array (stories.plist).
Then you will need to do more than just writeToFile:atomically: which will overwrite the current contents of the .plist file.

TalShani
Jul 27, 2010, 10:57 AM
That's not really debugging. You discovered the code doesn't work as expected. Debugging is discovering why / where the code doesn't work as expected.

So, what have you done (please be specific) to determine the cause of the problem you are encountering?


Then you will need to do more than just writeToFile:atomically: which will overwrite the current contents of the .plist file.

First, I cleaned the code, and stayed just with the things I need (Basic).
The I created breakpoints and NSLogs, so I can see exactly what is the things that don't work.

And the existing .plist file don't have any data in it, its blank, the app should add it.

Can you please help me solve this annoying problem?
Thanks, Tal.

dejo
Jul 27, 2010, 11:38 AM
What is the return value of your writeToFile:atomically: call?

TalShani
Jul 27, 2010, 11:51 AM
What is the return value of your writeToFile:atomically: call?

Blank, I wrote the array to .plist file name "stories.plist",
at ObjectAtIndex:0.
Then I created an NSString that equals to the .plist file ObjectAtIndex:0,
An after that I showed the NSString on UITextField and it turned blank.

dejo
Jul 27, 2010, 11:53 AM
No, blank is not an option. writeToFile:atomically: returns a BOOL, so the value would have to be either YES or NO.

chown33
Jul 27, 2010, 12:24 PM
Blank, I wrote the array to .plist file name "stories.plist",
at ObjectAtIndex:0.
Then I created an NSString that equals to the .plist file ObjectAtIndex:0,
An after that I showed the NSString on UITextField and it turned blank.

What is the length of the file, as stored at the pathname?

If you remove that file and run the program, is the file recreated? If so, then your file-writing code is working. The problem lies in the contents of the NSArray. If the file is not recreated, then you have a file-writing problem. Notice how I have broken the problem into two possible outcomes, and logically determined what each outcome means. This is a fundamental analysis skill.

If the file is recreated and has a non-zero length, then exactly what data is in the file? If it's an array with no elements, then that means your NSArray contained no elements when it was written. If it's an array with one string element, and the text of the string is "", then your NSArray contained @"" when it was written. Again, notice that I've broken the problem down into sub-components (contents of file, two possible interpretations of file contents), and logically determined what each one means.

If your array contains no elements, then takeText.text must be returning nil. If your array contains one "" element, then takeText.text must be returning @"". Here, I'm logically working backwards from the two possible outcomes, and making testable statements about how the NSArray 'values' came to have either zero or one element.

If takeText.text is nil, what might cause that?
One possibility is that takeText itself is nil. There are other possibilities. You have to look at the variables while debugging your code.

If takeText.text is an empty string, what might cause that?


A testable statement means an observable condition or state of some variable, whose answer can be determined by running the program in a debugger and actually observing what happens. If you can't determine the answer by observing something, then it's an untestable statement, and has no practical use because it can't be tested by any observation.

If a testable statement is too complex, it needs to be broken down into smaller testable statements. This is called decomposition and is fundamental to creating all software.

If you can't create testable statements about your code, then you probably don't understand what the code is doing, or what its sub-parts are doing. You fix this by learning what the code is doing. Otherwise it's all just magic, and you can't debug magic.


All the above is nothing but basic debugging logic and analysis. The logic means understanding the logical consequences of different observed states and outcomes (file exists or it doesn't; file contains some data or it doesn't; etc.). The analysis means working backwards from outcomes, and working forwards from existing state (a string variable is either nil or "" or some other text; an array contains either 0 or 1 elements; etc.).

TalShani
Jul 27, 2010, 01:44 PM
What is the length of the file, as stored at the pathname?

If you remove that file and run the program, is the file recreated? If so, then your file-writing code is working. The problem lies in the contents of the NSArray. If the file is not recreated, then you have a file-writing problem. Notice how I have broken the problem into two possible outcomes, and logically determined what each outcome means. This is a fundamental analysis skill.

If the file is recreated and has a non-zero length, then exactly what data is in the file? If it's an array with no elements, then that means your NSArray contained no elements when it was written. If it's an array with one string element, and the text of the string is "", then your NSArray contained @"" when it was written. Again, notice that I've broken the problem down into sub-components (contents of file, two possible interpretations of file contents), and logically determined what each one means.

If your array contains no elements, then takeText.text must be returning nil. If your array contains one "" element, then takeText.text must be returning @"". Here, I'm logically working backwards from the two possible outcomes, and making testable statements about how the NSArray 'values' came to have either zero or one element.

If takeText.text is nil, what might cause that?
One possibility is that takeText itself is nil. There are other possibilities. You have to look at the variables while debugging your code.

If takeText.text is an empty string, what might cause that?


A testable statement means an observable condition or state of some variable, whose answer can be determined by running the program in a debugger and actually observing what happens. If you can't determine the answer by observing something, then it's an untestable statement, and has no practical use because it can't be tested by any observation.

If a testable statement is too complex, it needs to be broken down into smaller testable statements. This is called decomposition and is fundamental to creating all software.

If you can't create testable statements about your code, then you probably don't understand what the code is doing, or what its sub-parts are doing. You fix this by learning what the code is doing. Otherwise it's all just magic, and you can't debug magic.


All the above is nothing but basic debugging logic and analysis. The logic means understanding the logical consequences of different observed states and outcomes (file exists or it doesn't; file contains some data or it doesn't; etc.). The analysis means working backwards from outcomes, and working forwards from existing state (a string variable is either nil or "" or some other text; an array contains either 0 or 1 elements; etc.).

As you see, I have already created the file (.plist) so I can't check this possibilities, what do you recommend, change the method to create the file or just leave it there blank until someone will enter a value in it?

dejo
Jul 27, 2010, 04:03 PM
...what do you recommend, change the method to create the file or just leave it there blank until someone will enter a value in it?
It doesn't matter. You need to accept the fact that no matter what is contained in your pre-existing .plist file, writeToFile:atomically: is going to write over it with whatever new information you provide it. So, say, you started your app and stories.plist contained an array of 5 elements. Once you call
NSArray *values = [[NSArray alloc] initWithObjects:takeText.text,nil];
[values writeToFile:[self savePath] atomically:YES];
your stories.plist is only going to contain 1 element (the value of takeText.text).

chown33
Jul 27, 2010, 04:45 PM
As you see, I have already created the file (.plist) so I can't check this possibilities, what do you recommend, change the method to create the file or just leave it there blank until someone will enter a value in it?

Delete the existing file manually. Then run your program again.

Are you running on the simulator or the device? Does the program work correctly on the simulator?

dejo
Jul 27, 2010, 05:29 PM
Delete the existing file manually.
Except files in the Documents directory can't be removed or added manually. That directory can only be altered from within the app.