Please do not post the same thing multiple times. The board software automatically flags certain posts as needing moderator attention. This happens the most often for new users. I'm pretty sure this is made clear at the time you attempt to post. Posting the same thing over and over again just makes that many more posts the moderators have to weed through later. This makes us sad. Don't make us sad. If your post/thread doesn't appear, just wait a while. Don't post it again. If it hasn't shown up by the next day, then you can try again. I normally go through posts in the mornings, and try to check a few times throughout the day, but I'm not here 24/7. There will typically be a significant delay before posts are approved. Just be patient.
I'm having a problem passing an NSMutableArray to another object. I have a UITabBar set up, my first view is trying to pass an array to my second view. My second view will hold a history of everything that happened in my first view.
Here's what I initially did. I created an array in my first view and in my second view. it works to send over the entire array as a pointer to the second view, but if I try to add objects to the already existing array, it doesn't work. I don't get any errors, it just keeps a count of zero objects. Here's my code.
for (int i = 0; i < [resultField.array count]; i++) { [self.historyArray addObject:[resultField.array objectAtIndex:i]]; }
}
If I pass in an NSString to another NSString in this same method, it gets passed in with no problem, but I can't figure out why its not passing each object into the new array.
I want to be able to save the history and add on to it when the user opens the app on the next launch. Please give me some inside on what I'm doing wrong, and suggestions on how to do it right. Thanks in advance.
I'm having a problem passing an NSMutableArray to another object. I have a UITabBar set up, my first view is trying to pass an array to my second view. My second view will hold a history of everything that happened in my first view.
Here's what I initially did. I created an array in my first view and in my second view. it works to send over the entire array as a pointer to the second view, but if I try to add objects to the already existing array, it doesn't work. I don't get any errors, it just keeps a count of zero objects. Here's my code.
for (int i = 0; i < [resultField.test count]; i++) { [self.historyArray addObject:[resultField.array objectAtIndex:i]]; }
}
If I pass in an NSString to another NSString in this same method, it gets passed in with no problem, but I can't figure out why its not passing each object into the new array.
I want to be able to save the history and add on to it when the user opens the app on the next launch. Please give me some inside on what I'm doing wrong, and suggestions on how to do it right. Thanks in advance.
Eliseo,
Are you getting a compile error or a runtime error? And what is that error?
My guess is that your self.historyArray is an NSArray, not an NSMutableArray.
NSArray objects have a fixed set of members, and you can't add, remove, or change the order of the objects within once you create the array. NSMutableArray objects have methods like addObject, removeObject, and sortUsingComparator that let you change the contents and order of the array.
If my guess is wrong you'll have to provide more information.
Regards,
Duncan C WareTo
Animated GIF created with Face Dancer, available for free in the app store.
Are you getting a compile error or a runtime error? And what is that error?
My guess is that your self.historyArray is an NSArray, not an NSMutableArray.
NSArray objects have a fixed set of members, and you can't add, remove, or change the order of the objects within once you create the array. NSMutableArray objects have methods like addObject, removeObject, and sortUsingComparator that let you change the contents and order of the array.
If my guess is wrong you'll have to provide more information.
Hi Duncan! Both Arrays are NSMutableArrays. Here's a sample of what's on my first view...
I alloc and initialized historyArray in my viewDidLoad method. If I pass the entire array from first view to second view, np. But I want add each object individually into the second view array since I'm going to be storing the history in there. I want to be able to keep adding to it until the user decides to clear the history. I'm not sure If I gave you enough information, hopefully I did, but please feel free to ask me for any further details. BTW, I don't get any errors at all, compiles perfectly.
Put an NSLog at the beginning of that method to log the result of [resultField.test count]. That will help you twofold; first, it'll show you if the method is even being called, and second, it'll show you if the for loop isn't ever running because [resultField.test count] is 0 or something.
Then, after the for loop, put another NSLog to log the description of the historyArray. That'll show you whether your problem is reading from the array or writing to the array.
If that doesn't help you find the answer, post the results here for us and maybe we can help you more.
Put an NSLog at the beginning of that method to log the result of [resultField.test count]. That will help you twofold; first, it'll show you if the method is even being called, and second, it'll show you if the for loop isn't ever running because [resultField.test count] is 0 or something.
Then, after the for loop, put another NSLog to log the description of the historyArray. That'll show you whether your problem is reading from the array or writing to the array.
If that doesn't help you find the answer, post the results here for us and maybe we can help you more.
Hi SoulRed. I actually tried doing that. The NSLogs get called, but the count is 0 and the object is null. I even tried adding just one object when alloc and initializing the NSMutable array, but even that resulted a count of 0 and null. I tried adding an NSString, but same thing, count is 0, object is null. No compile errors at all.
Just to Note, I entered the code wrong in this thread, its "resultField.array". The code in my project has all the naming correct.
So [resultField.test count] returns 0? Interesting...that seems to suggest there's something wrong with your first view controller.
One thing I do notice is that you've got [resultField.array objectAtIndex:i] inside your for loop, but you've only got an ivar for NSMutableArray *test. Could it be that you're accessing the wrong NSMutableArray? Perhaps I'm misunderstanding your code, but that looks like a possibility.
So [resultField.test count] returns 0? Interesting...that seems to suggest there's something wrong with your first view controller.
One thing I do notice is that you've got [resultField.array objectAtIndex:i] inside your for loop, but you've only got an ivar for NSMutableArray *test. Could it be that you're accessing the wrong NSMutableArray? Perhaps I'm misunderstanding your code, but that looks like a possibility.
Yea, I'm sorry about that. I entered it wrong here. Its actually as follows...
I alloc and initialized historyArray in my viewDidLoad method. If I pass the entire array from first view to second view, np. But I want add each object individually into the second view array since I'm going to be storing the history in there. I want to be able to keep adding to it until the user decides to clear the history. I'm not sure If I gave you enough information, hopefully I did, but please feel free to ask me for any further details. BTW, I don't get any errors at all, compiles perfectly.
Wait a minute. Something doesn't make sense. In your previous post you said the problem code was:
for (int i = 0; i < [resultField.array count]; i++) { [self.historyArray addObject:[resultField.array objectAtIndex:i]]; } }
But in the headers you just posted, resultField is a UILabel. UILabels don't have a resultField property. Oh, wait. your resultFieldHasAnswer method uses the name "resultField as a parameter for a FirstViewController object. That's really, really confusing. I would strongly suggest against that, especially since your FirstViewController object has a property called resultField. That would lead to such ugly code as resultField.resultField.
It'll automatically take care of the memory management through the fact that it's a property. In addition, you're going to get the same result as adding them all in one-by-one, because you'd be just adding pointers to the same objects that were in resultField.array (literally, the same objects; when you add an object to an array it only stores a pointer to that object and increments its retain count by 1).
If you wanted to actually copy the objects, so the historyArray indexes pointed to objects that were separate copies of the objects in resultField.array, you'd have to specifically copy them using the copy method before inserting them into the array.
Nevertheless, I'm still unsure why it's not working the way you have it, and I'm beginning to suspect more and more that the problem is elsewhere in the code. Try using the code I wrote above just as a test (even if it's not what you want for your app) and see if it works. At the very least it'll provide some more evidence to find the problem.
for (int i = 0; i < [firstViewController.array count]; i++) { [self.historyArray addObject:[firstViewController.array objectAtIndex:i]]; }
NSLog(@\"historyArray number of items %d\", [self.historyArray count]); }
It crashes on NSLog(@"[firstViewController.array count] = %@", [firstViewController.array count]);
I tried using a break point and stepping into the problem, but when it goes into the array it crashes and gives me a bad access. I would guess that would be a memory problem, but how does it get lost in memory if I never release it.
for (int i = 0; i < [firstViewController.array count]; i++) { [self.historyArray addObject:[firstViewController.array objectAtIndex:i]]; }
NSLog(@\"historyArray number of items %d\", [self.historyArray count]); }
It crashes on NSLog(@"[firstViewController.array count] = %@", [firstViewController.array count]);
I tried using a break point and stepping into the problem, but when it goes into the array it crashes and gives me a bad access. I would guess that would be a memory problem, but how does it get lost in memory if I never release it.
Oh crap. Sorry about that. You need to display a count value using %d, the format string for an integer. The log statements I posted used %@, which is the format string for an object. I fixed it in the code above, and marked the offending line in bold.
Regards,
Duncan C WareTo
Animated GIF created with Face Dancer, available for free in the app store.
(I just realized what you're trying to do; the array in the first view controller contains the new user activity and you want to add that to the array that the second view controller already owns, right? I assumed the first view controller's array held all the history data total, and you were just trying to get the pointers in the first array to a separate second array)
EDIT: Just saw Duncan's post, now I understand why the crash happened. Sorry.
It seems the problem would most likely in either the where the first view controller sends over the array, or where the second view controller creates its array. Perhaps posting a bit of that would be helpful? I don't want to ask you to reveal code you want to keep private, but at least consider it so we can have more information about what you're specifically doing.
//This actually works and shows me that temp is not nil or invalid NSString *temp = [NSString stringWithFormat:@\"%@\", answer]; NSLog(@\"temp = %@\", temp);
//Add new temp NSString to historyArray [self.historyArray addObject:temp];
//Problem : Prints null for(int i = 0; i < [self.historyArray count]; i++) { NSLog(@\"historyArray object at index %d is %@\", i, [self.historyArray objectAtIndex:i]); }
//Problem : Prints that 0 objects are in array NSLog(@\"historyArray number of items %d\", [self.historyArray count]); }
So that's my code for both view controllers. So what I'm trying to do is add a NSString to the "historyArray". But every time I try to do that, it shows me that nothing is added to the object. If I do the same array code in the FirstViewController, just to test if adding an object to an array works, everything works like a charm. But I need the SecondViewController to keep track of everything that's going to display in its UITableView History.
When I ran the code, I can see that the NSString is passed on successfully. But never added to the array. I even tried this in the SecondViewController
And when I checked the array, it had a count of 0. No errors, no nothing, everything is compiled without a problem. I'm at a lost on what I'm doing wrong. Should I alloc and init the string, add it to the object, then release it? This is driving me nuts.
Okay I figured out the problem. Since viewDidLoad is not called on the "SecondViewController" until someone clicks on the tab bar for it, I had to do the following...
So here's my other problem...lol. And hopefully is the last thing I ask of you great people. How do I save my data? I tried looking thru the forums but they don't have a straight out answer to what i'm looking for. I wanted to know how to save data using either "applicationWillTerminate" or "applicationDidEnterBackground".
Data gets saved in my "SecondViewController" even if the user never loads the view. How do I tell it to save it when it terminates. If you have to direct me to another post that I may have missed that would be grateful. I again, thank you guys for the help.
Try NSUserDefaults. You can save entire arrays with it, as long as the arrays only contain NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary objects. Since your array will be containing NSString's, you can save it using setObject:forKey: and load it again with arrayForKey:. Note that when you use arrayForKey, the returned array will be immutable, which means you're going to have to do something like self.historyArray = [NSMutableArray arrayWithArray:[[NSUserDefaults standardDefaults] arrayForKey:@"savedHistoryArray"]] instead of just using the NSArray object returned by arrayForKey.
Try NSUserDefaults. You can save entire arrays with it, as long as the arrays only contain NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary objects. Since your array will be containing NSString's, you can save it using setObject:forKey: and load it again with arrayForKey:. Note that when you use arrayForKey, the returned array will be immutable, which means you're going to have to do something like self.historyArray = [NSMutableArray arrayWithArray:[[NSUserDefaults standardDefaults] arrayForKey:@"savedHistoryArray"]] instead of just using the NSArray object returned by arrayForKey.
Hi Soul, thanks again for replying. I actually did this...
Here's my issue though. How do I get it to save when the app terminates. I decided to just save all the history in my FirstViewController, but when the application quits, the "viewdidunload" isn't called. How can I tell my application delegate to save the information on "applicationWillTerminate".
My ViewControllers are set up thru IB, so my applicationDelegate doesn't have any outlets to it. Should I create these outlets? Will that be easier to do, or is there a simpler way? This is my first time saving data like this, so tell it to me like it is...lol. Thanks a million.
You can always reach your applicationDelegate by calling [UIApplication sharedApplication].delegate. So what you can do, is set up an ivar and property on your app delegate, and when your history view controller loads, it should set the property correctly by calling something like (MyAppAppDelegate*)[UIApplication sharedApplication].delegate.historyArrayToSave = historyArray;
Then your app delegate will have a pointer to the history array, and you can save it in the appropriate methods. Remember to #import your App Delegate's header file in your history view controller's .m file. Also, the cast is there so xCode doesn't throw an error for not recognizing historyArrayToSave (or whatever you decide to call it).
I'm pretty sure this should work, I don't see why it wouldn't. :) Good luck!
You can always reach your applicationDelegate by calling [UIApplication sharedApplication].delegate. So what you can do, is set up an ivar and property on your app delegate, and when your history view controller loads, it should set the property correctly by calling something like (MyAppAppDelegate*)[UIApplication sharedApplication].delegate.historyArrayToSave = historyArray;
Then your app delegate will have a pointer to the history array, and you can save it in the appropriate methods. Remember to #import your App Delegate's header file in your history view controller's .m file. Also, the cast is there so xCode doesn't throw an error for not recognizing historyArrayToSave (or whatever you decide to call it).
I'm pretty sure this should work, I don't see why it wouldn't. :) Good luck!
You should make note that with iOS4 saving to user defaults is not guaranteed when the application is terminated. Proper termination, not fast-app switching suspend. The app just gets a kill signal. You should synchronize your NSUserdefaults at that time in order to make sure everything is saved when applicationWillTerminate is called.
Replies
Are you getting a compile error or a runtime error? And what is that error?
My guess is that your self.historyArray is an NSArray, not an NSMutableArray.
NSArray objects have a fixed set of members, and you can't add, remove, or change the order of the objects within once you create the array. NSMutableArray objects have methods like addObject, removeObject, and sortUsingComparator that let you change the contents and order of the array.
If my guess is wrong you'll have to provide more information.
Duncan C
WareTo
Animated GIF created with Face Dancer, available for free in the app store.
- Spam
- Abuse
- Troll
0 • Off Topic Insightful Disagree Dislike Like AwesomeAnd then here's what's in my second view...
I alloc and initialized historyArray in my viewDidLoad method. If I pass the entire array from first view to second view, np. But I want add each object individually into the second view array since I'm going to be storing the history in there. I want to be able to keep adding to it until the user decides to clear the history. I'm not sure If I gave you enough information, hopefully I did, but please feel free to ask me for any further details. BTW, I don't get any errors at all, compiles perfectly.
- Spam
- Abuse
- Troll
0 • Off Topic Insightful Disagree Dislike Like AwesomeThen, after the for loop, put another NSLog to log the description of the historyArray. That'll show you whether your problem is reading from the array or writing to the array.
If that doesn't help you find the answer, post the results here for us and maybe we can help you more.
- Spam
- Abuse
- Troll
0 • Off Topic Insightful Disagree Dislike Like AwesomeJust to Note, I entered the code wrong in this thread, its "resultField.array". The code in my project has all the naming correct.
- Spam
- Abuse
- Troll
0 • Off Topic Insightful Disagree Dislike Like AwesomeOne thing I do notice is that you've got [resultField.array objectAtIndex:i] inside your for loop, but you've only got an ivar for NSMutableArray *test. Could it be that you're accessing the wrong NSMutableArray? Perhaps I'm misunderstanding your code, but that looks like a possibility.
- Spam
- Abuse
- Troll
0 • Off Topic Insightful Disagree Dislike Like AwesomeAnd the code in my second view is like this...
- (void)resultFieldHasAnswer:(FirstViewController *)resultField{
for (int i = 0; i < [resultField.array count]; i++) {
[self.historyArray addObject:[resultField.array objectAtIndex:i]];
}
NSLog(@\"historyArray number of items %d\", [self.historyArray count]);
}
- Spam
- Abuse
- Troll
0 • Off Topic Insightful Disagree Dislike Like Awesome- (void)resultFieldHasAnswer:(FirstViewController *)resultField{
for (int i = 0; i < [resultField.array count]; i++) {
[self.historyArray addObject:[resultField.array objectAtIndex:i]];
}
}
But in the headers you just posted, resultField is a UILabel. UILabels don't have a resultField property. Oh, wait. your resultFieldHasAnswer method uses the name "resultField as a parameter for a FirstViewController object. That's really, really confusing. I would strongly suggest against that, especially since your FirstViewController object has a property called resultField. That would lead to such ugly code as resultField.resultField.
Anyway, I would add tons of debug statements:
Duncan C
WareTo
Animated GIF created with Face Dancer, available for free in the app store.
- Spam
- Abuse
- Troll
0 • Off Topic Insightful Disagree Dislike Like Awesome- (void)resultFieldHasAnswer:(FirstViewController *)resultField{historyArray = [NSMutableArray arrayWithArray:resultField.array];
}
It'll automatically take care of the memory management through the fact that it's a property. In addition, you're going to get the same result as adding them all in one-by-one, because you'd be just adding pointers to the same objects that were in resultField.array (literally, the same objects; when you add an object to an array it only stores a pointer to that object and increments its retain count by 1).
If you wanted to actually copy the objects, so the historyArray indexes pointed to objects that were separate copies of the objects in resultField.array, you'd have to specifically copy them using the copy method before inserting them into the array.
Nevertheless, I'm still unsure why it's not working the way you have it, and I'm beginning to suspect more and more that the problem is elsewhere in the code. Try using the code I wrote above just as a test (even if it's not what you want for your app) and see if it works. At the very least it'll provide some more evidence to find the problem.
- Spam
- Abuse
- Troll
0 • Off Topic Insightful Disagree Dislike Like Awesome- (void)resultFieldHasAnswer:(FirstViewController *)firstViewController{
NSLog(@\"inside resultFieldHasAnswer\");
NSLog(@\"On entry, FirstViewController = %@\", firstViewController);
NSLog(@\"firstViewController = %@\", firstViewController.array);
NSLog(@\"[firstViewController.array count] = %@\", [firstViewController.array count]);
for (int i = 0; i < [firstViewController.array count]; i++) {
[self.historyArray addObject:[firstViewController.array objectAtIndex:i]];
}
NSLog(@\"historyArray number of items %d\", [self.historyArray count]);
}
It crashes on NSLog(@"[firstViewController.array count] = %@", [firstViewController.array count]);
I tried using a break point and stepping into the problem, but when it goes into the array it crashes and gives me a bad access. I would guess that would be a memory problem, but how does it get lost in memory if I never release it.
- Spam
- Abuse
- Troll
0 • Off Topic Insightful Disagree Dislike Like Awesome- Spam
- Abuse
- Troll
0 • Off Topic Insightful Disagree Dislike Like AwesomeDuncan C
WareTo
Animated GIF created with Face Dancer, available for free in the app store.
- Spam
- Abuse
- Troll
0 • Off Topic Insightful Disagree Dislike Like AwesomeEDIT: Just saw Duncan's post, now I understand why the crash happened. Sorry.
It seems the problem would most likely in either the where the first view controller sends over the array, or where the second view controller creates its array. Perhaps posting a bit of that would be helpful? I don't want to ask you to reveal code you want to keep private, but at least consider it so we can have more information about what you're specifically doing.
- Spam
- Abuse
- Troll
0 • Off Topic Insightful Disagree Dislike Like AwesomeFirstViewController.h
FirstViewController.m
SecondViewController.h
SecondViewController.m
So that's my code for both view controllers. So what I'm trying to do is add a NSString to the "historyArray". But every time I try to do that, it shows me that nothing is added to the object. If I do the same array code in the FirstViewController, just to test if adding an object to an array works, everything works like a charm. But I need the SecondViewController to keep track of everything that's going to display in its UITableView History.
When I ran the code, I can see that the NSString is passed on successfully. But never added to the array. I even tried this in the SecondViewController
And when I checked the array, it had a count of 0. No errors, no nothing, everything is compiled without a problem. I'm at a lost on what I'm doing wrong. Should I alloc and init the string, add it to the object, then release it? This is driving me nuts.
- Spam
- Abuse
- Troll
0 • Off Topic Insightful Disagree Dislike Like Awesome- (void)firstViewController:(FirstViewController *)firstViewController hasAnswer:(NSString *)answer{
NSString *temp = [NSString stringWithFormat:@\"%@\", answer];
if(self.historyArray == nil){
self.historyArray = [[NSMutableArray alloc] init];
}
[self.historyArray addObject:temp];
}
So here's my other problem...lol. And hopefully is the last thing I ask of you great people. How do I save my data? I tried looking thru the forums but they don't have a straight out answer to what i'm looking for. I wanted to know how to save data using either "applicationWillTerminate" or "applicationDidEnterBackground".
Data gets saved in my "SecondViewController" even if the user never loads the view. How do I tell it to save it when it terminates. If you have to direct me to another post that I may have missed that would be grateful. I again, thank you guys for the help.
- Spam
- Abuse
- Troll
0 • Off Topic Insightful Disagree Dislike Like Awesome- Spam
- Abuse
- Troll
0 • Off Topic Insightful Disagree Dislike Like Awesome- (void)viewDidLoad {
[super viewDidLoad];
history = [[NSMutableArray alloc] init];
NSString *temp = [[NSUserDefaults standardUserDefaults] valueForKey:@\"History\"];
[history addObjectsFromArray:[temp componentsSeparatedByString:@\", \"]];
}
- (void)saveHistory{
if ([history count] > 0) {
NSString *temp = [history componentsJoinedByString:@\", \"];
[[NSUserDefaults standardUserDefaults] setValue:temp forKey:@\"History\"];
}
}
Here's my issue though. How do I get it to save when the app terminates. I decided to just save all the history in my FirstViewController, but when the application quits, the "viewdidunload" isn't called. How can I tell my application delegate to save the information on "applicationWillTerminate".
My ViewControllers are set up thru IB, so my applicationDelegate doesn't have any outlets to it. Should I create these outlets? Will that be easier to do, or is there a simpler way? This is my first time saving data like this, so tell it to me like it is...lol. Thanks a million.
- Spam
- Abuse
- Troll
0 • Off Topic Insightful Disagree Dislike Like AwesomeThen your app delegate will have a pointer to the history array, and you can save it in the appropriate methods. Remember to #import your App Delegate's header file in your history view controller's .m file. Also, the cast is there so xCode doesn't throw an error for not recognizing historyArrayToSave (or whatever you decide to call it).
I'm pretty sure this should work, I don't see why it wouldn't. :) Good luck!
- Spam
- Abuse
- Troll
0 • Off Topic Insightful Disagree Dislike Like Awesome- Spam
- Abuse
- Troll
0 • Off Topic Insightful Disagree Dislike Like Awesome- Spam
- Abuse
- Troll
0 • Off Topic Insightful Disagree Dislike Like Awesome