I am trying to set up my TableView, and I am having trouble. The values of my NSArray is different from each other. I know this is hard to understand, but i will try my best to explain.
For example
-(void)setUpContacts{
//set up the contacts
NSString *string = #"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
letterArray = [[NSMutableDictionary alloc]init];
Contacts *contact = [[Contacts alloc]init];
contactNumbers = [contact phoneNumbers];
for (NSDictionary* info in contactNumbers) {
firstLetter = [info objectForKey:#"lastName"];
index = #"_";
if([firstLetter length] > 0){
firstLetter =[firstLetter substringToIndex:1];
firstLetter= [firstLetter capitalizedString];
NSRange range = [string rangeOfString:firstLetter];
if(range.length >= 0){
index= firstLetter;
}
}
if(![letterArray objectForKey:index]){
[letterArray setValue:[NSMutableArray array] forKey:index];
}
[[letterArray objectForKey:index] addObject:info];
}NSLog(#"%#",letterArray);}
-(NSArray *)getLetterArraycount{
NSMutableArray *countArray = [[NSMutableArray alloc]init];
NSNumber *subCount;
for(id key_main in letterArray){
subCount = 0;
for(id key_sub in [letterArray objectForKey:key_main]){
subCount = [NSNumber numberWithInt:[subCount intValue]+1];
}
[countArray addObject:subCount];
}
return countArray;
}
- (void)viewDidLoad{
[super viewDidLoad];
[self setUpContacts];
countArrays = [self getLetterArraycount];
indexPaths = [[NSMutableDictionary alloc]init];
NSArray *temp = [letterArray allKeys];
NSLog(#"%#",temp);
NSLog(#"%#",countArrays);
//set up the tableView
self.myTableView = [[UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
self.myTableView.delegate = self;
self.myTableView.dataSource = self;
self.title = #"Select Friends";
self.myTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view addSubview:myTableView];}
and it logs like this in the Console
C = (
{
firstName = Alex;
kind = Mobile;
lastName = Chang;
name = "Alex Chang (Mobile)";
number = "(555) 555-5555";
},
{
firstName = YuYu;
kind = Mobile;
lastName = Chen;
name = "YuYu Chen (Mobile)";
number = "(408) 112-2334";
},
{
firstName = Chris;
kind = Mobile;
lastName = Choi;
name = "Chris Choi (Mobile)";
number = "(999) 999-9999";
},
{
firstName = Kevin;
kind = Mobile;
lastName = Chung;
name = "Kevin Chung (Mobile)";
number = "1 (231) 241-2312";
}
);
H = (
{
firstName = Danny;
kind = Mobile;
lastName = Huang;
name = "Danny Huang (Mobile)";
number = "(408) 599-9770";
},
{
firstName = Ice;
kind = Mobile;
lastName = Huang;
name = "Ice Huang (Mobile)";
number = "(408) 444-4444";
}
);
K = (
{
firstName = Will;
kind = Mobile;
lastName = King;
name = "Will King (Mobile)";
number = "(415) 123-4567";
}
);
L = (
{
firstName = "";
kind = iPhone;
lastName = LastName;
name = " LastName (iPhone)";
number = "(408) 123-2555";
},
{
firstName = david;
kind = Mobile;
lastName = lub;
name = "david lub (Mobile)";
number = "(666) 666-1111";
}
);
P = (
{
firstName = Jennifer;
kind = Mobile;
lastName = Pie;
name = "Jennifer Pie (Mobile)";
number = "(666) 666-6666";
}
);
S = (
{
firstName = Martin;
kind = Mobile;
lastName = Shen;
name = "Martin Shen (Mobile)";
number = "(415) 333-1234";
},
{
firstName = Francis;
kind = Mobile;
lastName = Shung;
name = "Francis Shung (Mobile)";
number = "(408) 345-6789";
}
);
V = (
{
firstName = Brian;
kind = Mobile;
lastName = Vu;
name = "Brian Vu (Mobile)";
number = "(408) 234-5678";
}
);
Y = (
{
firstName = Qiu;
kind = Mobile;
lastName = Yang;
name = "Qiu Yang (Mobile)";
number = "(408) 567-8901";
}
);
Z = (
{
firstName = Joy;
kind = Mobile;
lastName = Zhou;
name = "Joy Zhou (Mobile)";
number = "(408) 765-4321";
}
);
"_" = (
{
firstName = FirstName;
kind = Mobile;
lastName = "";
name = "FirstName (Mobile)";
number = "1 (408) 234-5141";
}
);
}
2012-04-26 16:14:05.195 UpOut[2693:15803] (
L,
Y,
V,
"_",
Z,
S,
K,
C,
P,
H
MY Question is why doesnt it log "C" first, but instead it Logged "L"
Sounds like you need to learn how to use "NSSortDescriptor" (I've linked the documentation for you).
Here is a related question that might have some useful sample code you can refer to. The key you would want to sort on, in your case, would be the lastName value of each NSDictionary entry.
Alphabetical answers consistently get more upvotes:
NSArray *sortedArray = [countArray sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
Related
Here I want to filter dictionary in the array which contains the "cate = subcat"
could anybody help me please
menuArr :(
{
Cate = subcat;
Description = "Grilled Chicken";
Id = 2;
Image = "http://asaraa.com/our_development/restaurant/admin/logo_image/large/28322grilled_chicken.jpg";
Name = "Grilled Chicken";
Price = 0;
Qty = "";
Title = "grilled chicken";
},
{
Cate = product;
Description = gravey;
Id = 12;
Image = "http://asaraa.com/our_development/restaurant/admin/logo_image/large/27166mutton.jpg";
Name = gravey;
Price = 50;
Qty = 1;
Title = gravey;
},
{
Cate = product;
Description = "Chicken Korma";
Id = 15;
Image = "http://asaraa.com/our_development/restaurant/admin/logo_image/large/77845Indian_chicken_recipes.jpg";
Name = "Chicken Korma";
Price = 99;
Qty = 1;
Title = "Chicken Korma";
},
{
Cate = subcat;
Description = "Chicken Sandwiches";
Id = 16;
Image = "http://asaraa.com/our_development/restaurant/admin/logo_image/large/67831chicken-sandwich-melt-0204_300.jpg";
Name = "Chicken Sandwiches";
Price = 0;
Qty = "";
Title = "Chicken Sandwiches";
}
)
NSString *searchString = #"subcat"
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"Cate = %#",searchString];
NSArray *array = [yourArray filteredArrayUsingPredicate:predicate];
if (array.count > 0)
{
// here goes your code
}
Using Linq to ObjectiveC you can filter it as follows:
NSArray* itemsInCategory = [menuArr where:^BOOL(id dic) {
return [[dic objectForKey:#"Cate"] isEqualToString:#"subcat"];
}];
This finds all the dictionaries where Cate=subcat.
Use NSPredicate
NSArray *filtered = [yourArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"(Cate LIKE[CD] %#)", #"subcat"]];
My array contains three dictionaries per object of the array.
{
avg = {
avg1 = 50;
avg2 = 60;
};
posts = {
alcoholContent = 450;
name = "BBB";
origin = United States;
};
reviews = {
rev1 = "Test review 1";
rev2 = "Test review 2";
};
}
{
avg = {
avg1 = 30;
avg2 = 20;
};
posts = {
alcoholContent = 550;
name = "AAA";
origin = United States;
};
reviews = {
rev1 = "Test review 1";
rev2 = "Test review 2";
};
}
I want to sort array acceding by key "name" (of post dictionary).
How can I do it?
I tried normal sorting methods using sort descriptors, but did not work
Try sortUsingComparator:
[array sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSDictionary *dict1 = obj1;
NSDictionary *dict2 = obj2;
NSString *string1 = [[dict1 objectForKey:#"posts"] objectForKey:#"name"];
NSString *string2 = [[dict2 objectForKey:#"posts"] objectForKey:#"name"];
return [string1 compare:string2];
}];
I am having trouble returning the numberofSections/numberofRows. I have a dictionary full of data
-(void)setUpContacts{
//set up the contacts
NSString *string = #"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
letterArray = [[NSMutableDictionary alloc]init];
Contacts *contact = [[Contacts alloc]init];
contactNumbers = [contact phoneNumbers];
for (NSDictionary* info in contactNumbers) {
firstLetter = [info objectForKey:#"lastName"];
index = #"_";
if([firstLetter length] > 0){
firstLetter =[firstLetter substringToIndex:1];
firstLetter= [firstLetter capitalizedString];
NSRange range = [string rangeOfString:firstLetter];
if(range.length >= 0){
index= firstLetter;
}
}
if(![letterArray objectForKey:index]){
[letterArray setValue:[NSMutableArray array] forKey:index];
}
[[letterArray objectForKey:index] addObject:info];
}
NSLog(#"%#",letterArray);}
and it NSLogs with this
C = (
{
firstName = Alex;
kind = Mobile;
lastName = Chang;
name = "Alex Chang (Mobile)";
number = "(555) 555-5555";
},
{
firstName = YuYu;
kind = Mobile;
lastName = Chen;
name = "YuYu Chen (Mobile)";
number = "(408) 112-2334";
},
{
firstName = Chris;
kind = Mobile;
lastName = Choi;
name = "Chris Choi (Mobile)";
number = "(999) 999-9999";
},
{
firstName = Kevin;
kind = Mobile;
lastName = Chung;
name = "Kevin Chung (Mobile)";
number = "1 (231) 241-2312";
}
);
H = (
{
firstName = Danny;
kind = Mobile;
lastName = Huang;
name = "Danny Huang (Mobile)";
number = "(408) 599-9770";
},
{
firstName = Ice;
kind = Mobile;
lastName = Huang;
name = "Ice Huang (Mobile)";
number = "(408) 444-4444";
}
);
K = (
{
firstName = Will;
kind = Mobile;
lastName = King;
name = "Will King (Mobile)";
number = "(415) 123-4567";
}
);
L = (
{
firstName = "";
kind = iPhone;
lastName = LastName;
name = " LastName (iPhone)";
number = "(408) 123-2555";
},
{
firstName = david;
kind = Mobile;
lastName = lub;
name = "david lub (Mobile)";
number = "(666) 666-1111";
}
);
for the -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; method
how do i retrieve the number of sections for index;
and for the -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; method, how do i retreive the number of rows in the section?
EDIT
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
NSArray *array = [letterArray mutableCopy];
return [[array objectAtIndex:section]count];}
and it gives me this error: -[__NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance 0x8434cc0
Thank you in advance
for -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView you should do something like this:
return [letterArray count];
for -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section you should do something like this:
NSArray *array = letterArray;
return [[array objectAtIndex:section] count];
EDIT
Try this:
-(NSArray *)getLetterArrayCount {
NSMutableArray *countArray = [[NSMutableArray alloc] init];
NSNumber *subCount;
for (id key_main in letterArray) {
subCount = 0;
for (id key_sub in [letterArray objectForKey:key_main]) {
subCount = [NSNumber numberWithInt:[subCount intValue] + 1];
}
[countArray addObject:subCount];
}
return countArray;
}
You should call it once and save it to a class variable and call it like this for sections:
[countArray count];
And for the rows in a section like this:
[[countArray objectAtIndex:section] intValue];
letterArray = [[NSMutableDictionary alloc]init];
indexArray = [[NSMutableArray alloc] init];
[letterArray setValue:[NSMutableArray array] forKey:index];
[indexArray addObject:index];
for -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView :
return [letterArray count];
for -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section :
return [[letterArray objectForKey:[indexArray objectAtIndex:section]] count];
I think it will be helpful to you.
in ur question the letterarray is an NSDictionary. it wont show You the objectAtIndex option. try to change the NSMutableDictionary into NSMutableArray. then you will get the option.
and
return(letterarray.count)
NSMutableArray * arr = [[NSMutableArray alloc]init];
for (NSArray *ar in letterarray){
[arr addObject:ar];
}
Return this arr.count
i am Learning.,.,.
I am creating a multidimensional array for sections / rows based on json data from our API. Looking at the logs the adding rows and sections look good but when I nslog the sections it only shows a bunch of the last object. It seems like the rows are not being added to sections.
What am I doing wrong to make the last API object show in the sections x times? x represents the json count. self.appointments is an NSArray *
According to objective-c multi-dimensional array it should work.
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSMutableArray *sections = [[NSMutableArray alloc] init];
NSMutableArray *rows = [[NSMutableArray alloc] init];
NSString *lastDate = nil;
for (NSDictionary *dict in [json objectForKey:#"data"]) {
NSString *date = [dict objectForKey:#"date"];
NSLog(#"Dates: %# - %#", date, lastDate);
if (date != lastDate) {
if (lastDate == nil) {
NSLog(#"Adding Row 1");
[rows addObject:dict];
lastDate = date;
} else {
NSLog(#"Adding Section 1");
NSLog(#"Adding #rows %i",[rows count]);
[sections addObject:rows];
[rows removeAllObjects];
NSLog(#"Adding Row 2 %#",[dict objectForKey:#"start_time"]);
[rows addObject:dict];
lastDate = date;
}
} else {
NSLog(#"Adding Row 3");
[rows addObject:dict];
}
}
if (rows) {
NSLog(#"Adding Section 2");
NSLog(#"Adding #rows %i",[rows count]);
[sections addObject:rows];
}
NSLog(#"Sections: %#", sections);
self.appointments = [sections mutableCopy]; //I have also tried self.appointments = sections
sections = nil;
rows = nil;
Logs show
Sections: (
(
{
abbrev = "";
account = "";
"addOnService_id" = "";
alert = "";
"appt_id" = 1839384;
"appt_id_unique" = 1839384;
"appt_status_description" = "";
"appt_status_type" = "";
"c_id" = 47;
cost = "0.00";
"coupon_id" = "";
"creation_emp_id" = 2288;
"creation_timestamp" = 201111040717;
"customer_id" = 0;
"customer_notes" = "";
"customer_package_id" = "";
date = 20121228;
"employee_id" = 2288;
"employee_notes" = "";
employer = "";
"end_time" = 570;
"first_name" = "";
"history_id" = 1830959;
key = 134;
"last_emp_id" = 2288;
"last_name" = "";
"last_timestamp" = 201111040717;
"lead_description" = "";
"link_id" = 0;
"location_name" = "Telephonic Setup/Training";
"make_id" = "";
"middle_name" = "";
"model_id" = "";
"model_year" = "";
name = "My Name ";
odometer = "";
"other_vehicle" = "";
"package_name" = "";
"payment_type_description" = "";
"payment_type_id" = "";
"pet_id" = "";
"po_number" = "";
reason = "B.O.B";
"rebook_id" = "";
"recur_id" = 20954;
"rep_id" = "";
"room_id" = 0;
"room_name" = "";
service = "";
"service_id" = 0;
"service_time_description" = "";
spots = 1;
"staff_screen_name" = "John Smith";
"staff_type_id" = 0;
"start_time" = 540;
"status_id" = 0;
tip = "";
"type_id" = 8;
vin = "";
}
),
(
{
abbrev = "";
account = "";
"addOnService_id" = "";
alert = "";
"appt_id" = 1839384;
"appt_id_unique" = 1839384;
"appt_status_description" = "";
"appt_status_type" = "";
"c_id" = 47;
cost = "0.00";
"coupon_id" = "";
"creation_emp_id" = 2288;
"creation_timestamp" = 201111040717;
"customer_id" = 0;
"customer_notes" = "";
"customer_package_id" = "";
date = 20121228;
"employee_id" = 2288;
"employee_notes" = "";
employer = "";
"end_time" = 570;
"first_name" = "";
"history_id" = 1830959;
key = 134;
"last_emp_id" = 2288;
"last_name" = "";
"last_timestamp" = 201111040717;
"lead_description" = "";
"link_id" = 0;
"location_name" = "Telephonic Setup/Training";
"make_id" = "";
"middle_name" = "";
"model_id" = "";
"model_year" = "";
name = "My Name ";
odometer = "";
"other_vehicle" = "";
"package_name" = "";
"payment_type_description" = "";
"payment_type_id" = "";
"pet_id" = "";
"po_number" = "";
reason = "B.O.B";
"rebook_id" = "";
"recur_id" = 20954;
"rep_id" = "";
"room_id" = 0;
"room_name" = "";
service = "";
"service_id" = 0;
"service_time_description" = "";
spots = 1;
"staff_screen_name" = "John Smith";
"staff_type_id" = 0;
"start_time" = 540;
"status_id" = 0;
tip = "";
"type_id" = 8;
vin = "";
}
), ... over and over again.
With:
[sections addObject:rows];
[rows removeAllObjects];
[rows addObject:dict];
you keep adding the same rows object not a new one and keep changing the contents so the last contents display each time.
Try:
[sections addObject:[rows mutableCopy]];
[rows removeAllObjects];
[rows addObject:dict];
That way a new row is added each time.
Perhaps better yet:
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSMutableArray *sections = [NSMutableArray array];
NSMutableArray *rows = [NSMutableArray array];
NSString *lastDate = nil;
for (NSDictionary *dict in [json objectForKey:#"data"]) {
NSString *date = [dict objectForKey:#"date"];
if ([date isEqualToString:lastDate] == NO) {
if (lastDate == nil) {
[rows addObject:dict];
lastDate = date;
} else {
[sections addObject:rows];
rows = [NSMutableArray array];
[rows addObject:dict];
lastDate = date;
}
[rows addObject:dict];
}
}
if (rows) {
[sections addObject:rows];
}
self.appointments = sections;
Note that assigning 0 to an object does not release it, release does. But if you use convenience methods to create objects then they are autoreleased and no further action is necessary to release them.
Also note that when comparing strings one needs to use the isEqualToString: method to compare the contents, just using the = or != only compares the address of the strings.
JSON As Dictionary
{
headers = (
{
backGroundImageUrl = "";
dataField = Name;
headerText = Name;
id = Name;
itemRenderer = "";
toolTip = "";
width = 60;
},
{
backGroundImageUrl = "";
dataField = BidPrice;
headerText = Bid;
id = BidPrice;
itemRenderer = "";
toolTip = "Bid Price";
width = 30;
});
values = (
{
assetCellValueLst = {
AskColorCode = "#B8D1ED";
AskPrice = "102.20";
BidColorCode = "#B8D1ED";
BidPrice = "102.00";
Name = "AR Bonar 11";
PECSAsk = 569;
PECSChg = "(31)";
PECSChgColorCode = "#000000";
PriceChg = "0.00";
PriceChgColorCode = "#000000";
SOLAsk = 604;
SSPAsk = 677;
SSPChgDay = "+3";
SSPChgDayColorCode = "#000000";
YTMAsk = "6.97";
assetGroupName = Argentina;
assetId = ARBONAR11;
iconPath = "images/flag_Argentina.gif";
updated = false;
};
assetId = ARBONAR11;
},
{
assetCellValueLst = {
AskColorCode = "#53840f";
AskPrice = "84.00";
BidColorCode = "#53840f";
BidPrice = "83.75";
Name = "AR Bod 15";
PECSAsk = 945;
PECSChg = 14;
PECSChgColorCode = "#000000";
PriceChg = "-0.10";
PriceChgColorCode = "#53840F";
SOLAsk = 985;
SSPAsk = 1007;
SSPChgDay = "+7";
SSPChgDayColorCode = "#000000";
YTMAsk = "11.74";
assetGroupName = Argentina;
assetId = ARBON15;
iconPath = "images/flag_Argentina.gif";
updated = false;
};
assetId = ARBON15;
});
The above JSON has more headers and values shortened here for clarity. The assestCellValueLst Dictionary can have more or less key-value pair depending on business logic. Same is true for headers dictionary. How should I create a Object Model in Xcode to use it with Core Data Managed Objects ? for a non - persistent store or no store at all
Simplistically, you would just create an entity for each type of dictionary you wanted to persist and have an attribute for each key in the dictionary.
In this case it looks like you would have two entities: Header and Asset. If the headers have a one-to-relationship with assets you might have (pseudocode) entities like this:
Header{
backGroundImageUrl = string;
dataField = string;
headerText = string;
id = string;
itemRenderer = ?;
toolTip = ?
width = integer;
asset<--(required,cascade)-->Asset.header
}
Asset{
assetId = string;
askColorCode = string;
askPrice = float;
bidColorCode = string;
bidPrice = float;
//...etc
header<--(required,nullify)-->Header.asset
}
The basic idea is that the model, well, "models" whatever real world object, event, condition or information you want to persist. In this case, the JSON is providing nice, neat dictionaries with all the data already organized and labeled for you.
+(NSArray *)managedObjectsFromJSONDictionary:(NSDictionary *)dictionary withManagedObjectContext:(NSManagedObjectContext *)moc
{
NSMutableArray *finalArrayOfArrays = [[NSMutableArray alloc] init];
NSArray *allKeys = [dictionary allKeys];
for(NSString *keyName in allKeys)
{
id structureArray = [dictionary valueForKey:keyName];
if([structureArray isKindOfClass:[NSArray class]])
{
NSMutableArray *objectArray = [[NSMutableArray alloc] init];
for(NSDictionary *structureDictionary in (NSArray *)structureArray)
{
[objectArray addObject:[JSONtoManagedObject managedObjectFromDictionary:structureDictionary withManagedObjectContext:moc forEntity:keyName]];
}
[finalArrayOfArrays addObject:objectArray];
[objectArray release];
}
}
return [finalArrayOfArrays autorelease];
}
+(NSManagedObject *)managedObjectFromDictionary:(NSDictionary *)dictionary withManagedObjectContext:(NSManagedObjectContext *)moc forEntity:(NSString *)entityName
{
NSManagedObject *managedObject;
NSArray *arrayOfKeys = [dictionary allKeys];
for(NSString *name in arrayOfKeys)
{
id obj = [dictionary objectForKey:name];
managedObject = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:moc];
if (![obj isKindOfClass:[NSDictionary class]])
{
if([name isEqualToString:#"id"])
[managedObject setValue:obj forKey:#"uniqueID"];
else
[managedObject setValue:obj forKey:name];
}
else
{
NSDictionary *relationshipDictionary = [[managedObject entity] relationshipsByName];
for(NSString *relationshipName in [relationshipDictionary allKeys])
{
NSRelationshipDescription *relationshipDescription = [relationshipDictionary objectForKey:relationshipName];
if(![relationshipDescription isToMany] && [relationshipName isEqualToString:name])
{
NSManagedObject *childObject = [JSONtoManagedObject managedObjectFromDictionary:obj withManagedObjectContext:moc forEntity:relationshipName];
[managedObject setValue:childObject forKey:relationshipName];
continue;
}
NSMutableSet *relationshipSet = [managedObject mutableSetValueForKey:relationshipName];
NSArray *relationshipArray = [obj valueForKey:relationshipName];
for(NSDictionary *insideDictoinary in relationshipArray)
{
NSManagedObject *childObject = [JSONtoManagedObject managedObjectFromDictionary:insideDictoinary withManagedObjectContext:moc forEntity:relationshipName];
[relationshipSet addObject:childObject];
}
}
}//end else
} // for
return managedObject;
}