Advertise here




Advertise here

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Sign In with Google Sign In with OpenID
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.

NSMutableArray addObjectsFromArray returning error

I'm having difficulty modifying a mutable array. I'd say that I am an an Intermediate level ios programmer - I'm not a complete newb, but I often forget some of the basics.

The error I'm getting is:

-[__NSCFArray insertObject:atIndex:]: mutating method sent to immutable object'

Trouble is, I declared and initialized it as an NSMutableArray. I have gone at this from a ton of different angles - I was hoping someone might give me some ideas. Here are the important highlights:

The viewcontroller looks like this:

@interface HomeScreen : UIViewController
{
...
NSMutableArray *arrayOfNewsItems;
}
...
- (void)GoAheadAndGetData;
- (void)getTweets;
- (void)renameKeysIn:(NSMutableArray*)source :(NSMutableArray*) final;
...
(some properties...)

@end

After the first viewController loads, the user clicks a button. The button is connected to a modal segue on the storyboard, so the following method runs:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([sender tag] == 1) { // if the button for loading the table is pushed:
// If there is a valid connection, go ahead and try to connect
if ([self connected]) {
[self GoAheadAndGetData];
} else { ...


...

(This all works fine, by the way)

So from there, the “GoAheadAndGetData” (which is where the array is initialized, and all data is obtained) method looks roughly like this:

- (void)GoAheadAndGetData
{
// This function starts by getting data automatically from my yahoo pipe,
// transfering it into a mutable array, then checks for other feeds

// create the string for making the api call to the yahoo pipes site
NSString* theURL = [NSString stringWithFormat:@"http://... etc..."];

// declare and assign variables necessary to generate the actual request
NSError* err = nil;
NSURLResponse* response = nil;
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] init];
NSURL* URL = [NSURL URLWithString:theURL];
[request setURL:URL];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setTimeoutInterval:30];

// make the actual url request - get the data from yahoo pipes, in json
NSData* jsonData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];

// assign the entire result to a large dictionary object
NSDictionary *entireResults = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&err];

// grab the "value" field
NSDictionary *valueFieldOnly = [entireResults objectForKey:@"value"];

// ****** This is where the array in question is initialized as mutable ********
// grab the "items" field
arrayOfNewsItems = [[NSMutableArray alloc] init];
arrayOfNewsItems = [valueFieldOnly objectForKey:@"items"];
//***************************************************************

// Now check for Twitter feed settings, and merge them into the rest
NSString *settingsKey = [[NSString alloc] initWithString:@"keyTwitterState"];
BOOL toggleValue = [[NSUserDefaults standardUserDefaults] boolForKey:settingsKey];
if (toggleValue) {
NSLog(@"Called getTweets, because twitter state answered as true.");
[self getTweets];
} else {
NSLog(@"twitter state answered as false.");
}
} // end method GoAheadAndGetData

// ******* This all works, so far, also.

The following method is where the error is generated. But I find it baffling - all I'm doing is calling a mutable method on a mutable array. I won't include all of the code here, because it's long, and I'm pretty sure nothing affects anything... most of it is directly from Twitter's api documentation anyway.

- (void)getTweets
{
...
if (!responseData) {
// inspect the contents of error
NSLog(@"Error 1: %@", error);
} else {
NSError *jsonError;
NSMutableArray *timeline = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableLeaves error:&jsonError];
if (timeline) { // at this point, we have an object that we can parse
// Having retrieved the user's home Twitter timeline, we can now merge it with the newsItems.
// The keys in the timeline need to match the arrayofnewsItems, in order for them to be sorted, so call renameKeys

timeline = [self renameKeysIn:timeline];// this works fine
NSLog(@"\nReturned value from rename Keys. \n%@^^Item 1:^^\nTimeline count: %d \narrayOfNewsItems count: %d",[timeline objectAtIndex:0], [timeline count],[arrayOfNewsItems count]);

// Then we can merge them:
// ****************** THIS IS THE MAIN ERROR POINT **********

[arrayOfNewsItems addObjectsFromArray:timeline];

// ******* THIS LINE RETUNS THE Mutable method/non-mutable object error.
NSLog(@"Added the tweet array to the newsitems array. Count: %d",[arrayOfNewsItems count]);

// Then finally, sort:
NSSortDescriptor *sortByDateDescriptor = [[NSSortDescriptor alloc] initWithKey:@"pubDate" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortByDateDescriptor];
NSLog(@"\ncreated sort descriptors. Getting ready to sort the array.");
NSMutableArray *sortedArray = [NSMutableArray arrayWithArray:[arrayOfNewsItems sortedArrayUsingDescriptors:sortDescriptors]];

[arrayOfNewsItems addObjectsFromArray:sortedArray];

} else {
// inspect the contents of jsonError NSLog(@"--------------- Error: ---------------- \n\n%@", jsonError);
}
}
}];

} // if ([twitterAccounts count] > 0)
} // if (granted)
}];
} // end getTweets

And that's basically it. Sorry about the formatting. At this point, I don't feel comfortable hosting the entire project
Post edited by pereirap on

Replies

  • smithdale87smithdale87 Posts: 4,289iPhone Dev SDK Supporter
    arrayOfNewsItems = [[NSMutableArray alloc] init];
    arrayOfNewsItems = [valueFieldOnly objectForKey:@\"items\"];


    The fact that I see these two lines right together in your code, in fact, means you still do not understand some of the fundamentals.

    Sure, you started off right by alloc'ing an NSMutableArray. But then you go and overwrite that with whatever is in valueFieldOnly for the key "items". I don't see anywhere in the code you posted where you have set that value. So it's safe to assume from the error messages you have, that this is only an NSArray. If you are trying to initialize an NSMutableArray to contain the contents of "items", then you could use the the arrayWithArray method to init an NSMutableArray with the contains of "item", or the mutableCopy method to make a mutable copy of "items".
  • DomeleDomele Posts: 2,948Registered Users

    arrayOfNewsItems = [[NSMutableArray alloc] init];
    arrayOfNewsItems = [valueFieldOnly objectForKey:@\"items\"];


    Your first line is redundant since you are replacing the value in the second line. I suspect the object you are getting back from objectForKey: is a regular NSArray, not mutable.


    NSArray *items = [valueFieldOnly objectForKey:@\"items\"];
    arrayOfNewsItems = [[NSMutableArray alloc] initWithArray:items];


    And you should look into using properties btw.
    If you are looking for a quality developer, I'm your man. Give me a PM if you are interested.



    New app - See screenshots and details at www.globaclock.com.



    If you want to
  • pereirappereirap Posts: 9New Users
    smithdale87;427254 said:
    arrayOfNewsItems = [[NSMutableArray alloc] init];
    arrayOfNewsItems = [valueFieldOnly objectForKey:@\"items\"];


    The fact that I see these two lines right together in your code, in fact, means you still do not understand some of the fundamentals.

    Sure, you started off right by alloc'ing an NSMutableArray. But then you go and overwrite that with whatever is in valueFieldOnly for the key "items". I don't see anywhere in the code you posted where you have set that value. So it's safe to assume from the error messages you have, that this is only an NSArray. If you are trying to initialize an NSMutableArray to contain the contents of "items", then you could use the the arrayWithArray method to init an NSMutableArray with the contains of "item", or the mutableCopy method to make a mutable copy of "items".
    Thanks, that helped.
  • pereirappereirap Posts: 9New Users
    Domele;427255 said:

    arrayOfNewsItems = [[NSMutableArray alloc] init];
    arrayOfNewsItems = [valueFieldOnly objectForKey:@\"items\"];


    Your first line is redundant since you are replacing the value in the second line. I suspect the object you are getting back from objectForKey: is a regular NSArray, not mutable.


    NSArray *items = [valueFieldOnly objectForKey:@\"items\"];
    arrayOfNewsItems = [[NSMutableArray alloc] initWithArray:items];


    And you should look into using properties btw.
    Thank you, that helped quite a bit. I originally wrote the array as a property, but went through so many changes while trying to fix this, ended up switching to an Ivar.
Sign In or Register to comment.