I get this json from web service and I need to group it depending on "PRICELISTCATEGORY" value. I tried the following code, but I get repeated rows and sections in the table. I collect the web service array in self.arrayPriceList. What am I doing wrong?
After collecting the array from json web service, I call [self didReceiveResponseJson:self.arrayPriceList];
-(NSMutableDictionary *)priceListCategoryDitionaryAllReadyExist:(NSString *)price {
for(NSMutableDictionary *priceListDict in self.arrayPriceList){
if([[[priceListDict objectForKey:#"PRICELISTCATEGORY"] objectForKey:#"text"] isEqualToString:price])
//return the existing array refrence to add
return priceListDict;
}
// if we dont found then we will come here and return nil
return nil;
}
-(void)didReceiveResponseJson:(NSMutableArray *)jsonArray {
for(NSDictionary *priceDict in jsonArray) {
NSMutableDictionary *existingPriceListDict=[self priceListCategoryDitionaryAllReadyExist:[[priceDict objectForKey:#"PRICELISTCATEGORY"] objectForKey:#"text"]];
NSMutableArray *existingTempArray = [NSMutableArray array];
if(existingPriceListDict != nil) {
//if name exist add in existing array....
[existingTempArray addObject:priceDict];
}
else {
// create new price list array
NSMutableArray *newPriceListArray=[[NSMutableArray alloc] init];
// Add name dictionary in it
[newPriceListArray addObject:priceDict];
// add this newly created pricelist array in globalNameArray
[self.arrayPriceList addObject:newPriceListArray];
}
}
//so at the end print global array you will get dynamic array with the there respetive dict.
//NSLog(#"Table array %#", self.arrayPriceList);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TGAPriceListCell *cell = [tableView dequeueReusableCellWithIdentifier:#"TGAPriceListCellId" forIndexPath:indexPath];
NSDictionary *dict;
if (self.isFiltered) {
dict = [self.arrayFilteredPriceList objectAtIndex:indexPath.row];
} else {
dict = [self.arrayPriceList objectAtIndex:indexPath.section];
}
cell.lblAPNBarCode.text = [[dict objectForKey:#"APNBARCODE"] objectForKey:#"text"];
cell.lblAvgCost.text = [[dict objectForKey:#"AVERAGECOST"] objectForKey:#"text"];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (self.isFiltered) {
return self.arrayFilteredPriceList.count;
} else {
NSArray *arrayPrice = [self.arrayPriceList objectAtIndex:section];
return [arrayPrice count];
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [self.arrayPriceList count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSDictionary *arrayPrice = [self.arrayPriceList objectAtIndex:section];
if([arrayPrice count]) {
return [[arrayPrice objectForKey:#"PRICELISTCATEGORY"] objectForKey:#"text"];
}
else
return nil;
}
After calling didReceiveResponseJson in viewDidLoad
self.arrayPriceList = [NSMutableArray array];
self.dictPriceList = [NSMutableDictionary dictionary];
I made changes in tableview datasource methods
-(void)didReceiveResponseJson:(NSMutableArray *)jsonArray {
for (NSDictionary *dict in jsonArray ) {
NSString *strPriceListCategory = [[dict objectForKey:#"PRICELISTCATEGORY"] objectForKey:#"text"];
if ([[self.dictPriceList allKeys] containsObject:strPriceListCategory]) {
NSMutableArray *arrayTemp = [self.dictPriceList objectForKey:strPriceListCategory];
[arrayTemp addObject:dict];
[self.dictPriceList setObject:arrayTemp forKey:strPriceListCategory];
} else {
NSMutableArray *arrayTemp = [[NSMutableArray alloc] initWithObjects:dict, nil];
[self.dictPriceList setObject:arrayTemp forKey:strPriceListCategory];
}
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TGAPriceListCell *cell = [tableView dequeueReusableCellWithIdentifier:#"TGAPriceListCellId" forIndexPath:indexPath];
NSDictionary *dict;
if (self.isFiltered) {
dict = [self.arrayFilteredPriceList objectAtIndex:indexPath.row];
} else {
NSArray *arrayPriceListAllKeys = [self.dictPriceList allKeys];
NSArray *arrayPrice = [self.dictPriceList objectForKey:[arrayPriceListAllKeys objectAtIndex:indexPath.section]];
dict = [arrayPrice objectAtIndex:indexPath.row];
}
cell.lblAPNBarCode.text = [[dict objectForKey:#"APNBARCODE"] objectForKey:#"text"];
cell.lblAvgCost.text = [[dict objectForKey:#"AVERAGECOST"] objectForKey:#"text"];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (self.isFiltered) {
return self.arrayFilteredPriceList.count;
} else {
NSArray *arrayPriceListAllKeys = [self.dictPriceList allKeys];
NSArray *arrayPrice = [self.dictPriceList objectForKey:[arrayPriceListAllKeys objectAtIndex:section]];
return [arrayPrice count];
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[self.dictPriceList allKeys] count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSString *price = [[self.dictPriceList allKeys] objectAtIndex:section];
return price;
}
Related
I have UITableView with countries and their phone codes
- (NSArray *)sortedCountryLetters {
if (_sortedCountryLetters == nil) {
[self countriesInfo];
}
return _sortedCountryLetters;
}
- (NSDictionary *)countriesInfo {
if (_countriesInfo == nil) {
NSMutableArray *countries = [NSMutableArray new];
for (NSString *key in [AppDelegate phoneCodes]) {
[countries addObject:#{
#"key": key,
#"name": [_locale displayNameForKey:NSLocaleCountryCode value:key],
#"code": [AppDelegate phoneCodes][key]
}];
}
NSMutableArray *firstLetters = [NSMutableArray new];
NSMutableDictionary *result = [NSMutableDictionary new];
for (NSDictionary *country in countries) {
NSString *name = country[#"name"];
NSString *firstLetter = [[name substringToIndex:1] uppercaseString];
if ([[result allKeys] containsObject:firstLetter]) {
NSMutableArray *letterCountries = result[firstLetter];
[letterCountries addObject:country];
}
else {
result[firstLetter] = [#[country] mutableCopy];
[firstLetters addObject:firstLetter];
}
}
[firstLetters sortUsingComparator:^NSComparisonResult(NSString *letter1, NSString *letter2) {
return [letter1 compare:letter2];
}];
_sortedCountryLetters = [firstLetters copy];
for (NSString *firstLetter in [result allKeys]) {
NSMutableArray *letterCountries = result[firstLetter];
[letterCountries sortUsingComparator:^NSComparisonResult(NSDictionary *obj1, NSDictionary *obj2) {
NSString *name1 = obj1[#"name"];
NSString *name2 = obj2[#"name"];
return [[name1 lowercaseString] compare:[name2 lowercaseString]];
}];
}
_countriesInfo = [result copy];
}
return _countriesInfo;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[[self countriesInfo] allKeys] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSString *firstLetter = [self sortedCountryLetters][section];
NSArray *letterCountries = [self countriesInfo][firstLetter];
return [letterCountries count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"countryCell"];
NSString *firstLetter = [self sortedCountryLetters][indexPath.section];
NSArray *letterCountries = [self countriesInfo][firstLetter];
NSDictionary *country = letterCountries[indexPath.row];
[[cell textLabel] setText:country[#"name"]];
[[cell textLabel] setTextColor:[OmwThemes defaultColorForegroundMain]];
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [self sortedCountryLetters][section];
}
- (NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return [self sortedCountryLetters];
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
[tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:index] atScrollPosition:UITableViewScrollPositionTop animated:YES];
return [[self sortedCountryLetters] indexOfObject:title];
}
Section indices already shows at table view right side, but tapping do nothing.
In debug I saw that tableView:sectionForSectionIndexTitle:atIndex: method never called.
Table view is connected to datasource and delegate. I did try both plain and group table view styles.
What did I miss?
Update:
My table view look:
I'm making a title indexed event invitation list. I have an array with EventStatus objects. I'm making the _data array for table like,
for (int i = 0; i < eventStatusList.count; i++) {
NSString *firstName = ((OCEventStatus*)eventStatusList[i]).user.firstName;
[_sortedUsers setObject:((OCEventStatus*)eventStatusList[i]).user.firstName forKey:[firstName substringToIndex:1]];
}
_sortedUserTitles = [[[_sortedUsers allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)] mutableCopy];
_data = [eventStatusList mutableCopy];
[self.dataTableView reloadData];
and I think this for loop thing is too slow. Is there a way to do this in a good manner? Following is the title index making up logic with UITablrViewDataSource methods.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [_sortedUserTitles count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
NSString *sectionTitle = [_sortedUserTitles objectAtIndex:section];
NSArray *sectionUsers = [_sortedUsers objectForKey:sectionTitle];
return [sectionUsers count];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
// return animalSectionTitles;
return _alphabetArray;
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
return [_sortedUserTitles indexOfObject:title];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [_sortedUserTitles objectAtIndex:section];
}
This is error because of in the _sortedUsers dictionary has a string instead of an array. How may I fix this? And also please suggest a fast, good manner to implement this title index.
If you want to create an List of Firstnames try this perhaps.
At interface:
#property(nonatomic, strong)NSMutableDictionary *dict;
#property(nonatomic, strong)NSMutableArray *alphabet;
_dict = [NSMutableDictionary new];
_alphabet = [NSMutableArray new];
[eventStatusList sortUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
OCEventStatus *ev1 = (OCEventStatus*)obj1;
OCEventStatus *ev2 = (OCEventStatus*)obj2;
return [ev1.firstName compare:ev2.firstName];
}];
for(OCEventStatus *state in eventStatusList){
NSString *firstchar = [[state.firstName substringToIndex:1] lowercaseString];
if([dict objectForKey:firstchar]==nil){
NSMutableArray *tmp = [NSMutableArray new];
[tmp addObject:state];
[_dict setObject:tmp forKey:firstchar];
[_alphabet addObject:firstChar];
}else{
[[dict objectForKey:firstchar] addObject:state];
}
}
Now you have an Array of firstnames in a Dictionary which has the first letter as the key for Example: a -> ["Alfred","Albert",...]
In the Datasource methods you have to return it like this...
-(NSInteger)numberOfSectionsInTableView:(UITableView*)tableView{
return dict.count;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection;(NSInteger)section
{
return [dict objectForKey:[alphabet objectAtIndex:section]].count;
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
OVEventStatus *state = [[dict objectForKey:[alphabet objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
cell.textLabel.text = state.firstName;
return cell;
}
Please try if this fits for you
Update:
If you also want to Sort the Arrays I would recommend to sort the eventListBy firstName first! So you have the correct order when you loop over the eventStatusList.
I'm sorting my array by last name alphabetically. I'd like to separate this into sections with the appropriate header above each section (A, B, C, etc.).
Here's what I've tried below:
// Here is where I refresh the data and sort it based on last name
- (void)refreshData {
[[PCMSSessionManager sharedSession] refreshPCMSDataWithCompletion:^(BOOL success, NSString *errorMessage, id resultObject) {
if (success) {
NSLog(#"yay!");
self.membersArray = [[PCMSSessionManager sharedSession] memberArr];
// Let's sort the array
self.sortedArray = [self.membersArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
NSString *first = [(PCMSMember*)a lastName];
NSString *second = [(PCMSMember*)b lastName];
return [first compare:second];
}];
[self.tableView reloadData];
} else {
NSLog(#"boooo!!!!");
}
}];
}
- (NSDictionary *)indexedMembers
{
NSMutableDictionary *indexedContacts = [NSMutableDictionary new];
for (PCMSMember *member in self.sortedArray)
{
NSString *sortString = member.lastName;
NSString *sortLetter = [sortString substringToIndex:1];
/* see if that letter already exists as an index */
BOOL foundKey = NO;
for (NSString *key in [indexedContacts allKeys])
{
if ([key isEqualToString:sortLetter])
{
foundKey = YES;
}
}
NSMutableArray *valueArray;
if (foundKey)
{
valueArray = [((NSArray *)indexedContacts[sortLetter]) mutableCopy];
}
else
{
valueArray = [NSMutableArray new];
}
[valueArray addObject:member];
indexedContacts[sortLetter] = [valueArray copy];
}
return [indexedContacts copy];
}
// Here's my table data
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[[self indexedMembers] allKeys] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSDictionary *indexedContacts = [self indexedMembers];
NSArray *myKeys = [indexedContacts allKeys];
NSString *key = myKeys[section];
return [((NSArray *)[self indexedMembers][key]) count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"cellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
// Configure the cell...
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
if (self.isPhysician == YES) {
NSString *key = [[self indexedMembers] allKeys][indexPath.section];
PCMSMember *currentMember = ((NSArray *)[self indexedMembers][key])[indexPath.row];
cell.textLabel.text = [NSString stringWithFormat:#"%# %#", currentMember.firstName, currentMember.lastName];
}
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [[self indexedMembers] allKeys][section];
}
UPDATE:
This is getting me closer to what I want.
The data is loading, it's being grouped properly and the headers are showing.
But it's not in alphabetical order.
How can I improve this code to show alphabetically?
It's showing in alphabetical order in my console, just not in the app.
The NSMutableDictionary is unordered by definition. It is not the natural choice if you rely on the order of the stored objects. I suggest you to use NSMutableArray instead. To store the tableview data for each section you can use this mini class
#interface MembersWithSameInitial : NSObject
#property (strong) NSString* initial;
#property (strong) NSMutableArray<PCMSMember*>* members;
#end
#implementation MembersWithSameInitial
#end
After you have sorted the members, all the data for the tableview can be produced with this before tableView reload.
NSMutableArray<MembersWithSameInitial*>* groupedMembers = [[NSMutableArray alloc] init];
for (PCMSMember* member in sortedArray) {
NSString* inicial = [member.lastName substringToIndex:1];
MembersWithSameInitial* last = [groupedMembers lastObject];
if (last && [last.initial isEqualToString:inicial]) {
[last.members addObject:member];
} else {
MembersWithSameInitial* newGroup = [[MembersWithSameInitial alloc] init];
newGroup.initial = inicial;
newGroup.members = [[NSMutableArray alloc] initWithObjects:member, nil];
[groupedMembers addObject:newGroup];
}
}
Since the structure of groupedMembers fits to a grouped tableView, the dataSource methods will have trivial implementations. Assuming, that you have stored groupedMembers in a property.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.groupedMembers.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.groupedMembers[section].members.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//...
PCMSMember *currentMember = self.groupedMembers[indexPath.section].members[indexPath.row];
//...
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return groupedMembers[section].initial;
}
Suggestion:
Create two properties
#property NSMutableArray *keys; // for the letters in alphabetical order
#property NSMutableDictionary *indexedContacts; // same as your implementation.
In the method refreshData call the method to create the data source and then reload the table view on the main thread.
Actually you don't need the properties memberArray and sortedArray anymore. The sorted array is passed to the method to create the data source.
- (void)refreshData {
[[PCMSSessionManager sharedSession] refreshPCMSDataWithCompletion:^(BOOL success, NSString *errorMessage, id resultObject) {
if (success) {
NSLog(#"yay!");
self.membersArray = [[PCMSSessionManager sharedSession] memberArr];
// Let's sort the array
NSArray *sortedArray = [self.membersArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
NSString *first = [(PCMSMember*)a lastName];
NSString *second = [(PCMSMember*)b lastName];
return [first compare:second];
}];
[self indexMembers:sortedArray];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
} else {
NSLog(#"boooo!!!!");
}
}];
}
The method indexMembers initializes the properties keys and indexedContacts and creates the data source.
- (void)indexMembers:(NSArray *)sortedMembers
{
self.keys = [[NSMutableArray alloc] init];
self.indexedContacts = [[NSMutableDictionary alloc] init];
for (PCMSMember *member in sortedMembers)
{
NSString *sortString = member.lastName;
NSString *sortLetter = [sortString substringToIndex:1];
/* see if that letter already exists as an index */
NSArray *keyArray = self.indexedContacts[sortLetter];
NSMutableArray *valueArray;
if (keyArray) {
// array for key exists, use it
valueArray = [keyArray mutableCopy];
} else {
// array for key does not exist, create a new one
valueArray = [NSMutableArray new];
// and add the letter to keys
[self.keys addObject:sortLetter];
}
[valueArray addObject:member];
self.indexedContacts[sortLetter] = [valueArray copy];
}
}
numberOfSectionsInTableView returns the number of keys
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.keys.count;
}
numberOfRowsInSection gets the appropriate array for the given section and returns the number of items.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *letter = self.keys[section];
NSArray *memberArray = self.indexedContacts[letter];
return memberArray.count;
}
In cellForRowAtIndexPath use the method dequeueReusableCellWithIdentifier: forIndexPath: to get always a valid cell. Then like in numberOfRowsInSection get the actual member array and populate the label.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"cellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
// Configure the cell...
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
if (self.isPhysician == YES) {
NSString *letter = self.keys[indexPath.section];
NSArray *memberArray = self.indexedContacts[letter];
PCMSMember *currentMember = memberArray[indexPath.row];
cell.textLabel.text = [NSString stringWithFormat:#"%# %#", currentMember.firstName, currentMember.lastName];
}
return cell;
}
titleForHeaderInSection simply returns the letter for the section
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return self.keys[section];
}
You're calling indexedMembers too much. This is very expensive.
I couldn't test the code, maybe there is a self or something else missing but you get an impression of the workflow.
I am trying to display State (in section title) and City (in table rows) from this url. Top Cities will come in first section followed by state and cities. Issue is I am not able to assign respective array of cities for sectioned state title row. Here's what I tried..
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(#"Json dictionary = %#", json);
self.dictListSateMaster = [json objectForKey:#"RaffleInstanceLocations"];
for (NSDictionary *dict in [self.dictListSateMaster objectForKey:#"listStateMaster"])
{
ViewLocationsObjct *viewLocationsObjct = [[ViewLocationsObjct alloc] init];
viewLocationsObjct.StateNameStr = [dict objectForKey:#"StateName"];
[self.arrayListStateMaster addObject:[dict objectForKey:#"StateName"]];
for (NSDictionary *dictnry in [dict objectForKey:#"listCityMaster"])
{
//*********-- Need corrections here
ViewLocationStateMaster *viewLocNewObjct = [[ViewLocationStateMaster alloc] init];
viewLocNewObjct.CityName = [dictnry objectForKey:#"CityName"];
[self.arrayListCityMaster addObject:viewLocNewObjct];
}
}
for (NSDictionary *dict in [self.dictListSateMaster objectForKey:#"listTopCities"])
{
ViewLocationsObjct *viewLocationsObjct = [[ViewLocationsObjct alloc] init];
viewLocationsObjct.CityName = [dict objectForKey:#"CityName"];
[self.arrayTopCities addObject:viewLocationsObjct];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return self.arrayListStateMaster.count+1; //+1 to append to top cities section at the top
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellId = #"cellId";
ViewLocationsTblCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId forIndexPath:indexPath];
if (indexPath.section == 0)
{
ViewLocationsObjct *viewLocationObj = [self.arrayTopCities objectAtIndex:indexPath.row];
cell.locationLabl.text = viewLocationObj.CityName;
}
else
{
//*********-- Need corrections here
//NSString *sectionTitle = [self.arrayListStateMaster objectAtIndex:indexPath.section];
//NSMutableArray *arrayCities = [self.dictListSateMaster objectForKey:sectionTitle];
//cell.locationLabl.text = [arrayCities objectAtIndex:indexPath.row];
ViewLocationStateMaster *viewLoc = [self.arrayListCityMaster objectAtIndex:indexPath.row];
cell.locationLabl.text = viewLoc.CityName;
}
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 0)//return top cities for 1st section
{
return self.arrayTopCities.count;
}
else
{
return self.arrayListCityMaster.count;
}
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if (section == 0)
{
return #"Top Cities";
}
else
{
if (self.arrayListStateMaster.count > 0)
{
return [self.arrayListStateMaster objectAtIndex:section-1];//-1 to remove index of top cities section at the top
}
else
{
return #"";
}
}
}
OK so here's how my problem was solved !
NSDictionary *dictRaffleInstLocations = [json objectForKey:#"RaffleInstanceLocations"];
sectionArray = [dictRaffleInstLocations objectForKey:#"listStateMaster"];
topCityArray = [dictRaffleInstLocations objectForKeyedSubscript:#"listTopCities"];
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 0) {
return topCityArray.count;
}else
return [[[sectionArray objectAtIndex:section-1]objectForKey:#"listCityMaster"] count];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return sectionArray.count+1;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if (section == 0) {
return #"Top Cities";
}else
return [[sectionArray objectAtIndex:section-1]objectForKey:#"StateName"];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellId = #"MyCellLocation";
ViewLocationsTblCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId forIndexPath:indexPath];
if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0f)
{
cell.layoutMargins = UIEdgeInsetsZero;
cell.preservesSuperviewLayoutMargins = NO;
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
NSString *titleString = #"";
if (indexPath.section == 0) {
titleString = [[topCityArray objectAtIndex:indexPath.row]objectForKey:#"CityName"];
}else{
NSArray *cityArray = [sectionArray[indexPath.section-1]objectForKey:#"listCityMaster"];
titleString = [cityArray[indexPath.row]objectForKey:#"CityName"];
}
cell.locationLabl.text = titleString;
return cell;
}
I have a very simple app to learn how to work with sections in UITableView but there is an exception -
2013-09-17 08:46:19.956 Sections[4497:c07] * -[__NSArrayI
objectAtIndex:]: message sent to deallocated instance 0x9566d40
The whole methods are below - need help.
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle] pathForResource:#"sortednames" ofType:#"plist"];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
self.names = dict;
NSArray *array = [[_names allKeys] sortedArrayUsingSelector:#selector(compare:)];
_keys = array;
}
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
NSLog(#"%lu", (unsigned long)[_keys count]);
return [_keys count];
}
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *key = [_keys objectAtIndex:section];
NSArray *nameSection = [_names objectForKey:key];
return [nameSection count];
}
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSString *key = [_keys objectAtIndex:section];
NSArray *nameSection = [_names objectForKey:key];
static NSString *SectionsTableIdentifier = #"SectionsTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SectionsTableIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SectionsTableIdentifier];
}
cell.textLabel.text = [nameSection objectAtIndex:row];
return cell;
}
- (NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSString *key = [_keys objectAtIndex:section];
return key;
}
You must retain _keys array like that:
_keys = [[[_names allKeys] sortedArrayUsingSelector:#selector(compare:)] retain];
Here you are first taking values in other array and then passing it to _keys..thats not proper way of doing it..
just directly pass the values to _keys like below
_keys = [[_names allKeys] sortedArrayUsingSelector:#selector(compare:)];
also check for self.names, you are doing the same thing there.
Hope this will help you.