PDA

View Full Version : saving text changes to NSMutableDictionary from UITextView




gbenna
Feb 23, 2012, 05:45 PM
I have an NSMutableDictionary in my mainViewController which loads some text into my DetailViewController. I want the user to be able to add to the text and then save the changes back to the NSMutableDictionary so when the DetailViewController is show again the changes show up. I have researched this some but for the most part I can only find where this can be done in the UITextField. I would like to use the UITextView in case the user wants to add a lot of text which would be longer than the UITextField field. Is This possible to do?
This is the NSMutableDictionary in my mainViewController;


`detailViewController *detailView = [[detailViewController alloc] initWithNibName:@"detailViewController" bundle:nil];

if ((int)index == 0) {
NSMutableDictionary *aDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:
@"some existing text", @"textkey", nil];

detailView.aDictionary = aDictionary;
}`

and this is the code to load it in the DetailViewController;

self.theText.text =[(NSMutableDictionary *)aDictionary objectForKey:@"textkey"];

I have a right navigationBarButton that I want to hide the keyboard and save the text back to the NSMutableDictionary at the same time when touched.

`-(void)doneEditing:(id)sender
{
[(NSMutableDictionary *)aDictionary writeToFile:@"textkey"];
[theText resignFirstResponder];

}

}`

this isn't working and I'm not sure how to proceed. It is very difficult to find tutorial/examples of this.



Sykte
Feb 24, 2012, 08:38 AM
I have an NSMutableDictionary in my mainViewController which loads some text into my DetailViewController. I want the user to be able to add to the text and then save the changes back to the NSMutableDictionary so when the DetailViewController is show again the changes show up. I have researched this some but for the most part I can only find where this can be done in the UITextField. I would like to use the UITextView in case the user wants to add a lot of text which would be longer than the UITextField field. Is This possible to do?
This is the NSMutableDictionary in my mainViewController;


`detailViewController *detailView = [[detailViewController alloc] initWithNibName:@"detailViewController" bundle:nil];

if ((int)index == 0) {
NSMutableDictionary *aDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:
@"some existing text", @"textkey", nil];

detailView.aDictionary = aDictionary;
}`

and this is the code to load it in the DetailViewController;

self.theText.text =[(NSMutableDictionary *)aDictionary objectForKey:@"textkey"];

I have a right navigationBarButton that I want to hide the keyboard and save the text back to the NSMutableDictionary at the same time when touched.

`-(void)doneEditing:(id)sender
{
[(NSMutableDictionary *)aDictionary writeToFile:@"textkey"];
[theText resignFirstResponder];

}

}`

this isn't working and I'm not sure how to proceed. It is very difficult to find tutorial/examples of this.


How to start, doneEditing is not the proper delegate call back for UITextField. Look up UITextField Reference, read over the information and also lookup UITextFieldDelegate. I'll give you a hint, -textFieldDidEndEditing. :)

Why are you needing to cast NSMutableDictionary. It's hard to tell but it looks as it's out of scope. This could be another potential problem.
self.theText.text =[(NSMutableDictionary *)aDictionary objectForKey:@"textkey"];

Why are you writing the dictionary to a file, I'm guessing you want to replace the value and not actually write it to file. Again why the need to cast.

[(NSMutableDictionary *)aDictionary writeToFile:@"textkey"];
[theText resignFirstResponder];

Replace that with this.

[aDictionary setValue:[self theText].text forKey:@"textkey"];
[theText resignFirstResponder];


Yes, you can resize your UITextField depending on the size of the text. The text property of UITextField is NSString, NSString has instance methods to give back the metrics of a string. You can even put constraints depending on your needs.

Hope this helps.

Edit: I believe the size instance methods are only available for UIKit. You would have to look this up to verify.

gbenna
Feb 24, 2012, 04:50 PM
How to start, doneEditing is not the proper delegate call back for UITextField. Look up UITextField Reference, read over the information and also lookup UITextFieldDelegate. I'll give you a hint, -textFieldDidEndEditing. :)

Why are you needing to cast NSMutableDictionary. It's hard to tell but it looks as it's out of scope. This could be another potential problem.
self.theText.text =[(NSMutableDictionary *)aDictionary objectForKey:@"textkey"];

Why are you writing the dictionary to a file, I'm guessing you want to replace the value and not actually write it to file. Again why the need to cast.

[(NSMutableDictionary *)aDictionary writeToFile:@"textkey"];
[theText resignFirstResponder];

Replace that with this.

[aDictionary setValue:[self theText].text forKey:@"textkey"];
[theText resignFirstResponder];


Yes, you can resize your UITextField depending on the size of the text. The text property of UITextField is NSString, NSString has instance methods to give back the metrics of a string. You can even put constraints depending on your needs.

Hope this helps.

Edit: I believe the size instance methods are only available for UIKit. You would have to look this up to verify.


I am using a UITextView

I have found this code to put in for changes;

in my .h

-(void)textViewDidChange:(UITextView *)textView:(id)sender;

and then in my .m

-(void) viewDidLoad{

[super viewDidLoad];

UIBarButtonItem *doneButton =[[UIBarButtonItem alloc]
initWithTitle:@"Done"
style:UIBarButtonItemStyleBordered
target:self
action:@selector(textViewDidChange:(UITextView *)textView:)];

self.navigationItem.rightBarButtonItem = doneButton;
}

-(void)textViewDidChange:(UITextView *)textView:(id)sender
{
[myDictionary setValue:[self aText].text forKey:@"textkey"];
[aText resignFirstResponder];
}

The part I am having trouble with is the part in Bold the parenthesis before the UITextView says it needs another ')' but for the life of me I can't figure out where. Some help please.

And thank everyone for their help and suggestions I couldn't do this without all of you.

Gary

dejo
Feb 24, 2012, 05:09 PM
I have found this code to put in for changes...

Where did you find this code? Because if that @selector bit comes from that code, they are not showing you the proper way to set it up.

You should follow a variation on Sykte's advice and look into UITextViewDelegate.

Sykte
Feb 25, 2012, 07:45 AM
I am using a UITextView

Sorry I either misread or mistyped. However the same still applies. UITextView still has a delegate protocol.



I have found this code to put in for changes;


Finding code isn't necessarily bad however not understanding it is. Do you understand how to use a delegate or a protocol? If not read up on both and fully understand them both before moving forward they are truly a core fundamental.




UIBarButtonItem *doneButton =[[UIBarButtonItem alloc]
initWithTitle:@"Done"
style:UIBarButtonItemStyleBordered
target:self
action:@selector(textViewDidChange:(UITextView *)textView:)];

The part I am having trouble with is the part in Bold the parenthesis before the UITextView says it needs another ')' but for the life of me I can't figure out where. Some help please.


This is really off base. No need for this. See below.



-(void)textViewDidChange:(UITextView *)textView:(id)sender
{
[myDictionary setValue:[self aText].text forKey:@"textkey"];
[aText resignFirstResponder];
}

This looks better however you may want to look over UITextView's other delegate methods and try them out they may or may not suite your needs better. Do you understand when -textViewDidChange is sent and who sends it?

gbenna
Feb 26, 2012, 03:28 PM
Ok I have changed a few things (probably wrong). I have been researching implementing data persistence but... Anyway.

I have the button working so that it hides the keyboard it is written like this.


UIBarButtonItem *saveButton =[[UIBarButtonItem alloc]
initWithTitle:@"Save"
style:UIBarButtonItemStyleBordered
target:self
action:@selector(didChangeValueForKey:)];

self.navigationItem.rightBarButtonItem = saveButton;


then I have changed this part of the code to ;

-(void)didChangeValueForKey:(NSString *)key{



[myDictionary setValue:[self aText].text forKey:@"textkey"];
[aText resignFirstResponder];

NSLog(@"%@", [myDictionary valueForKey:@"textkey"]);

When I look at my NSLog it shows that my textkey now shows the changes that I entered into the textView but when I close the window or app and reopen it it does not show up. I would appreciate if you could point me to a good tutorial on this as I have been looking a reading and researching lot.
Thanks for your help.

gbenna
Feb 29, 2012, 12:15 PM
I have totally rewritten my code for this and I now am saving the changed text as a text file in the apps documents file. I get the name of the saved file from my dictionary in the MainViewController. This way every time a different detailView is loaded by tapping a different image in the mainView the text that is saved can have a different name and be loaded to the correct DetailView as it is called.

Here is my code for the Dictionary.

if ((int)index == 0) {
NSMutableDictionary *myDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:
//this is where I get the name of the text file to load into the UITextView
@"first View Text", @"textkey2",
//This is where I get the name of the text file for saving the added text to the app's documents file
@"first View Text", @"textkey3",nil];

detailViewController.myDictionary = myDictionary;
}

and this is the code I use to save the changed text
- (void)saveAction:(id)sender {


[self.myText2 resignFirstResponder];
//self.navigationItem.rightBarButtonItem = nil; // this will remove the "save" button

NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [documentPaths objectAtIndex:0];
NSString *documentTXTPath = [documentsDirectory stringByAppendingPathComponent:[(NSMutableDictionary *)myDictionary objectForKey:@"textkey3"]];
NSString *savedString = myText2.text;

NSLog(@"The Save file is:%@", savedString);

[savedString writeToFile:documentTXTPath atomically:YES
encoding:NSUTF8StringEncoding error:NULL];

I know it is being save as a text file with this name because when I look in the documents file in the iPhone simulator documents file it is there.

My problem is loading the text file from the chosen key from the dictionary. I have tried to create a path to the file with the called for document in the dictionary but I am having problems opening the actual text file to display the text. Here is my code for this so far.
NSString *textName = [myDictionary objectForKey:@"textkey2"];
NSArray *paths2 = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory2 = [paths2 objectAtIndex:0];

NSString *fullPath2 = [documentsDirectory2 stringByAppendingPathComponent:textName];

self.myText2.text = fullPath2;

When I do this I get a print out of the path not the actual file contents. I have tried to append various places with ofType@"text" but with no luck.

Could someone help me?

dejo
Feb 29, 2012, 12:22 PM
gbenna, just a reminder on how to properly use the [code] tags:

Posting code, please use the [CODE] tags (http://forums.macrumors.com/showthread.php?t=747660)

gbenna
Feb 29, 2012, 03:14 PM
thanks for the instruction about tags

Finally got this working by replacing last line of code

[CODE]
self.myText2.text = fullPath2;


with this code which does what I want it to.


self.myText2.text = [NSString stringWithContentsOfFile:fullPath2 encoding:NSUTF8StringEncoding error:NULL];


Thanks for everyones help