NSMutablearray starts printing from last element instead of first - ios

I´m using this method to initialize an nsmutablearray
- (void)getAllContacts
{
Contact *contact = [[Contact alloc] init];
self.allContacts = [[NSMutableArray alloc] init];
int i=0;
for (i=0; i<5; i++)
{
contact.nome = [[NSString alloc] initWithFormat:#"Bruno %d", i];
[self.allContacts insertObject:contact atIndex:i];
}
}
Pretty straightforward! But right after, i do a for to print it´s elements like:
for (int i=0; i<[self.allContacts count]; i++)
{
Contact *c = [self.allContacts objectAtIndex:i];
NSLog(#"i=%d\nNome:%#", i, c.nome);
}
And it will show me 5 times the last element "Bruno 4". It doesn´t start from 0 and increments. What should i do to start from 0?

Try this:
- (void)getAllContacts
{
Contact *contact = nil;
self.allContacts = [NSMutableArray array];
int i=0;
for (i=0; i<5; i++)
{
contact = [Contact new];
contact.nome = [NSString stringWithFormat:#"Bruno %d", i];
[self.allContacts addObject:contact];
[contact release]
}
}
and please take a look at: Memoy Management

Because you are inserting the same object 5 times into the array. You need to create a new Contact object at every execution of the for loop.

What you are doing is you're actually adding one instance of the Contact class 5 times in the array and only changing nome property. Here is the correct way to do this:
- (void)getAllContacts
{
//alloc init returns a retained object and self.allContacts calls the setter, which additionally retains it.
self.allContacts = [[[NSMutableArray alloc] init] autorelease];
int i=0;
for (i=0; i<5; i++)
{
//Create the Contact object
Contact *contact = [[Contact alloc] init];
//Set the nome property
contact.nome = [NSString stringWithFormat:#"Bruno %d", i];
//Add the instance to the array
[self.allContacts addObject:contact];
//Release the instance because the array retains it and you're not responsible for its memory management anymore.
[contact release];
}
}

Related

Why is my array not being populated?

Ok, I'm a bit out of my league but here goes... I'm working on making some updates to an iPhone app for a client (it hasn't been updated since 2013...just to put into context how old the programming is). While making simple updates to the app, I noticed the twitter feed section kept crashing. I checked the debug and came up with this error.
[_NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array
I know the array is empty... I'm just not sure why. Here's the code where I think it is filling the array
- (void)loadData {
NSURL *tutorialsUrl = [NSURL URLWithString:#"https://twitter.com/EdwinOrange/lists/kentucky-general-assembly"];
NSData *tutorialsHtmlData = [NSData dataWithContentsOfURL:tutorialsUrl];
TFHpple *tutorialsParser = [TFHpple hppleWithHTMLData:tutorialsHtmlData];
NSString *tutorialsXpathQueryString = #"//p[#class='TweetTextSize js-tweet-text tweet-text']";
NSArray *tutorialsNodes = [tutorialsParser searchWithXPathQuery:tutorialsXpathQueryString];
NSMutableArray *newTutorials = [[NSMutableArray alloc] initWithCapacity:0];
for (TFHppleElement *element in tutorialsNodes) {
NSString *strResponse = #"";
for (int l=0; l<[[element children] count]; l++)
{
strResponse =[strResponse stringByAppendingString:[[[element children] objectAtIndex:l] content]];
NSArray *_children = [[[element children] objectAtIndex:l] children];
NSLog(#"count = %d",[_children count]);
for (int k=0; k<[_children count]; k++)
{
NSLog(#"%#",[[_children objectAtIndex:k] children]);
NSArray *_internalChildren = [[_children objectAtIndex:k] children];
for (int j=0; j<[_internalChildren count]; j++)
{
NSLog(#"%#",[[_internalChildren objectAtIndex:j] content]);
strResponse = [strResponse stringByAppendingFormat:#"%#",[[_internalChildren objectAtIndex:j] content]];
}
}
}
Tutorial *tutorial = [[Tutorial alloc] init];
[newTutorials addObject:tutorial];
tutorial.title = strResponse;
NSLog(#"strResponse = %#",strResponse);
NSLog(#"Data---%#",tutorial.title);
}
_data = newTutorials;
delegateObj.arrDetailContent = [_data mutableCopy];
}
It might also we worth it to note the Log does not return any information for the above code. I added an exception breakpoint which breaks at this line (because the _data array is empty)
Tutorial *data = [_data objectAtIndex:indexPath.row];
This may also help to track down the problem (this is at the top of the TwitterController.m)
#pragma mark - Calling Twitter feeds
-(void)getAndParseTwitterFeeds
{
[self loadAtData];
[self loadNames];
[self loadData];
[self loadImages];
[self loadHours];
[self loadLink];
[self loadImages];
[self loadHours];
}
-(void)getFeeds
{
[self getAndParseTwitterFeeds];
}
-(void)getFeedsLocally
{
_link = delegateObj.arrTwitterLink;
_objects = delegateObj.arrObjects;
_members = delegateObj.arrMemberName;
_data = delegateObj.arrDetailContent;
arrProfileImages = delegateObj.arrImages;
_hours = delegateObj.arrHour;
[self updateTableViewWithTheData];
}
Hope that is enough explanation... I'm really hoping someone can help me figure out why the array is not being filled. Thanks!!!!
EDIT: I'm starting to wonder now if the HTML parser is having trouble with images in tweets. This code is from around 2013 which pre-dates twitter's inline images. Could this be causing the array to return empty?
Also of note the arrays _link, _members, _hours, etc. are all being populated correctly and have identical coding up until the "NSString *strResponse" section for loadData.

Adding items to a NSMutableArray - Logic issue

I have 5 animal objects and i trying to save it in a NSMutableDIctionary. However, according to my code below, only the last animal gets saved in the NSMutableDIctionary.
I don't think i am looping it correctly.
for(int i = 0; i < animalCount; i++) {
[allContacts setObject:name forKey:#"name"];
[allContacts setObject:age forKey:#"age"];
[allContacts setObject:gender forKey:#"gender"];
}
The output of the above displays as follows: (Only the last animal object gets displayed)
{
name = fish;
age = 6;
gender = "female";
}
How i want is that, all five animal objects to be saved in the NSMutableDIctionary so i can display them in a UITableView.
{
name = "cow";
age = 4;
gender = "male";
},
{
name = "dog";
age = 15;
gender = "male";
},
{
name = "fish";
age = 6;
gender = "female";
}
Key of NSMutableDictionary is unique.
What you want do is build an Array and every object of this Array is a Dictionary
NSMutableArray * contentsArray = [[NSMutableArray alloc] init];
for(int i = 0; i < animalCount; i++) {
NSMutableDictionary * allContacts = [[NSMutableDictionary alloc] init];
[allContacts setObject:name forKey:#"name"];
[allContacts setObject:age forKey:#"age"];
[allContacts setObject:gender forKey:#"gender"];
[contentsArray addObject:allContacts];
}
First create a NSMutableArray in order to loop and create the dictionaries. Then create individual dictionaries.
NSMutableArray *outputArray = [NSMutableArray array];
for ( int i=0; i< animalCount; i++) {
NSMutableDictionary *internalDictionary = [NSMutableDictionary dictionary];
[internalDictionary setObject:[nameArray objectAtIndex: i] forKey:#"name"];
[internalDictionary setObject:[ageArray objectAtIndex: i] forKey:#"age"];
[internalDictionary setObject:[genderArray objectAtIndex: i] forKey:#"gender"];
[outputArray addObject:internalDictionary];
}
NSLog(#"%#",outputArray);
Cheers!
You need an array of dictionaries, where your keys are constants (name, age, gender) and your values should be considered from their index (you'll need an array of names, ages, and genders), unless you'll have a lot of similar dictionaries:
NSMutableArray * contentsArray = [NSMutableArray new];
for(int i = 0; i < animalCount; i++) {
NSMutableDictionary * allContacts = [[NSMutableDictionary alloc] init];
[allContacts setObject:arrNames[i] forKey:#"name"];
[allContacts setObject:arrAges[i] forKey:#"age"];
[allContacts setObject:arrGenders[i] forKey:#"gender"];
[contentsArray addObject:allContacts];
}
or in modern objective c (simpler & shorter):
NSMutableArray *contentsArray = [NSMutableArray new];
for(int i = 0; i < animalCount; i++) {
[contentsArray addObject:#{#"name" : arrNames[i],
#"age" : arrAges[i],
#"gender" : arrGenders[i]}];
}
The reason is every time you are looping, you are updating the keys of your MSMutableDictionary, but you are not saving it anywhere.
Just take an NSMutableArray and save your dictionaries every time you update it.
So, first initialise the array outside the loop-
NSMutableArray *allContactsArray = [[NSMutableArray alloc] initWithCapacity: animalCount];
Now, run the loop, and save the dictionary every time before you loose it.
for(int i = 0; i < animalCount; i++) {
[allContacts setValue:name forKey:#"name"];
[allContacts setValue:age forKey:#"age"];
[allContacts setValue:gender forKey:#"gender"];
//save the allContacts dictionary in the array
[allContactsArray insertObject:allContacts atIndex:i];
}
This way you also you at what index you are saving your dictionary while adding.
I think you are mistaken. You should be saving dictionaries into an array, to populate tableview.
NSMutableArray *animals = [NSMutableArray array];
for(int i = 0; i < animalCount; i++) {
NSDictionary *dict = #{#"name" : name, #"age" : age, #"gender" : gender};
[animals addObject:dict];
}
Access in cellForRowAtIndexPath using:
NSDictionary *dict = animals[indexPath.row];
cell.textLabel.text = dict[#"name"];

Passing data to BTsidemenu

I have developed an application in which I am using this: BTSimpleSideMenu
In my app I am passing cell label's through this:
-(void)show{
sideMenu.delegate = self;
int count;
count = [rssOutputData count];
for (int i = 0; i < count; i++){
NSString *items = [[rssOutputData objectAtIndex:i]xmltitle];
BTSimpleMenuItem *item = [[BTSimpleMenuItem alloc]initWithTitle:[[rssOutputData objectAtIndex:i]xmltitle] image:[UIImage imageNamed:#"arrow.png"]
onCompletion:^(BOOL success, BTSimpleMenuItem *item) {
catLbl.text = [[rssOutputData objectAtIndex:i]xmltitle];
}];
sideMenu = [[BTSimpleSideMenu alloc]initWithItem:#[item] addToViewController:self];
}
[sideMenu toggleMenu];
}
In this code [[rssOutputData objectAtIndex:i]xmltitle] is actually the data which I am parsing from an XML file. I have a total of 5 entries in it that I want to show in the side menu, but unfortunately through this way the menu is only showing the last entry and only a single row.
I know this might be because it is overwriting entries on the first cell.
Please view the link given above and please help me out with this.
This code will solve your problem your are creating BtSimplemenuitem and BTSimplesidemmenu in every iteration so it will make a lot of sidemenu just change your code to this will work
-(void)show
{
sideMenu.delegate = self;
int count;
NSMutableArray *itemsArry = [[NSMutableArray alloc] init];
count = [rssOutputData count];
for (int i = 0; i < count; i++){
NSString *items = [[rssOutputData objectAtIndex:i]xmltitle];
BTSimpleMenuItem *item = [[BTSimpleMenuItem alloc]initWithTitle:[[rssOutputData objectAtIndex:i]xmltitle] image:[UIImage imageNamed:#"arrow.png"]
onCompletion:^(BOOL success, BTSimpleMenuItem *item) {
catLbl.text = [[rssOutputData objectAtIndex:i]xmltitle];
}];
[itemsArry addObject:item];
}
NSArray *itemSarry=[[NSArray alloc] initWithArray:itemsArry];
sideMenu = [[BTSimpleSideMenu alloc]initWithItem:itemSarry addToViewController:self];
[sideMenu toggleMenu];
}

iOS pass the value instead of reference

When executing the below block. My friends_dict NSMutableDictionary value changes as friend changes. If I'm not wrong this is because the reference of the value in the dictionary is passed along to the friend. How can I pass the value instead of reference and prevent the dictionary from changing.
NSMutableArray *friendsArray = [[NSMutableArray alloc] initWithArray:[friends_dict valueForKey:selectedFriendId]];
for (NSObject *object in [response objectForKey:#"friend_nearby"]){
NSString *id = [NSString stringWithFormat:#"%#",[object valueForKey:#"id"]];
NSString *spotValue = [NSString stringWithFormat:#"%#",[object valueForKey:#"spot"]];
for(int i = 0; i < [friendsArray count]; i++){
FriendDataModel *friend = [[FriendDataModel alloc] init];
friend = [friendsArray objectAtIndex:i];
if ([friend.friendId isEqualToString:id] && ![friend.spot isEqualToString:spotValue] ) {
friend.spot = spotValue; //This is where the dictionary value changes
[friendsArray replaceObjectAtIndex:i withObject:friend];
spotChanged = YES;
}
}
}
Copy the array and pass in the copy.
NSArray *friendList = [friends_dict valueForKey:selectedFriendId];
NSMutableArray *friendsArray = [friendList mutableCopy];

How to create a Multidimensional Array using loop in IOS xcode

I would like to create an array for iOS platform like the PHP syntax below, many thanks ~~
$createArray = array ();
for ($i = 0; $i<10; $i++) {
$createArray[$i]['name'] = $name;
$createArray[$i]['age'] = $age;
}
Save your values in NSDictionary and add that dictionary into your array
NSMutableArray *theArray = [NSMutableArray array];
for (int indexValue = 0; indexValue<10; indexValue++) {
NSMutableDictionary *theDictionary = [[NSMutableDictionary alloc] init];
[theDictionary setObject:name forKey:#"name"];
[theDictionary setObject:age forKey:#"age"];
[theArray addObject:theDictionary]
}
While Retrieving time,
NSString *name = [[theArray objectAtIndex:indexValue] objectForKey:#"name"];
NSString *age = [[theArray objectAtIndex:indexValue] objectForKey:#"age"];
you might find it helpful:
array = [[NSMutableArray alloc] init];
for (int i = 0; i < 8; i++) {
NSMutableArray *subArray = [[NSMutableArray alloc] init];
for (int j = 0; j < 8; j++) {
[subArray addObject:[NSNumber numberWithInt:0]];
}
[array addObject:subArray];
[subArray release];
}
also check this question
Try this.
array = [[NSMutableArray alloc] init];
for (int i = 0; i < 10; i++) {
NSMutableArray *subArray = [[NSMutableArray alloc] init];
for (int j = 0; j < 2; j++) {
//Do your Stuff
// [subArray addObject:name];
// [subArray addObject:Age];
}
[array addObject:subArray];
}
OR
Why can't try with the NSDictionary
You can use this. But this is not better way in IOS.
NSMutableArray *array[20];
for (int i=0;i< 20; i++)
{
array[i] = [NSMutableArray array];
for (int j=0;j<3;j++)
{
NSMutableDictionary *theDictionary = [[NSMutableDictionary alloc] init];
[theDictionary setObject:name forKey:#"name"];
[theDictionary setObject:age forKey:#"age"];
[[array[i] addObject:theDictionary]
}
}
First you to have set An NSMutableDictionary on .h file
#interface MSRCommonLogic : NSObject
{
NSMutableDictionary *twoDimensionArray;
}
then have to use following functions in .m file
- (void)setValuesToArray :(int)rows cols:(int) col value:(id)value
{
if(!twoDimensionArray)
{
twoDimensionArray =[[NSMutableDictionary alloc]init];
}
NSString *strKey=[NSString stringWithFormat:#"%dVs%d",rows,col];
[twoDimensionArray setObject:value forKey:strKey];
}
- (id)getValueFromArray :(int)rows cols:(int) col
{
NSString *strKey=[NSString stringWithFormat:#"%dVs%d",rows,col];
return [twoDimensionArray valueForKey:strKey];
}

Resources