I'm taking over some code since another dev has moved on and his search bar has an error. I've searched the other threads for help on this, but none of them seem to be my error. Here is a screen shot of mine and the code.
http://imgur.com/gO6wuPb
2014-09-17 11:25:34.665 Moca[11388:60b] * Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ valueForUndefinedKey:]: this class is not key value coding-compliant for the key itemName.'
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [searchResults count];
} else {
return [[[BNRItemStore sharedStore] allItems] count];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 71;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"UITableViewCell";
UITableViewCell *cell = (UITableViewCell *)[self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//there are two tableviews involved here - one is the main one, and one is associated with searchDisplayController
//self.tableView is set automatically between the main one and the search one.
// Configure the cell...
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSArray *items = [[BNRItemStore sharedStore] allItems];
BNRItem *item = nil;
if (tableView == self.searchDisplayController.searchResultsTableView) {
item = [searchResults objectAtIndex:indexPath.row];
} else {
item = items[indexPath.row];
}
if ([item.subcategory isEqual:#"Urgent"]) {
cell.imageView.image=[UIImage imageNamed:#"Urgent.png"];
}
else if ([item.subcategory isEqual:#"Emergency"]) {
cell.imageView.image=[UIImage imageNamed:#"Emergency.png"];
}
else if ([item.subcategory isEqual:#"Standard"]) {
cell.imageView.image=[UIImage imageNamed:#"Standard.png"];
}
else if ([item.subcategory isEqual:#"Normal"]) {
cell.imageView.image=[UIImage imageNamed:#"Normal.png"];
}
else {
cell.imageView.image=[UIImage imageNamed:#"Informational.png"];
}
cell.textLabel.text = item.changeOrder;
cell.detailTextLabel.text =item.title;
return cell;
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSArray *items = [[BNRItemStore sharedStore] allItems];
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"itemName contains[c] %#", searchText];
searchResults = [items filteredArrayUsingPredicate:resultPredicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
EDIT add item details
#import <Foundation/Foundation.h>
#interface BDDetailedChange : NSObject
+ (instancetype)randomItem;
- (instancetype)initWithItemName:(NSString *)name
valueInDollars:(NSString *)value
serialNumber:(NSString *)sNumber;
#property (nonatomic, copy) NSString *itemName;
#property (nonatomic, copy) NSString *serialNumber;
#property (nonatomic, copy) NSString *valueInDollars;
#property (nonatomic, readonly, strong) NSDate *dateCreated;
#property (nonatomic, copy) NSString *subcategory; //Emergency
#property (nonatomic, copy) NSString *service;
#property (nonatomic, copy) NSString *associatedCIs;
#property (nonatomic, copy) NSString *environment;// Production
#property (nonatomic, copy) NSString *approvalGroup;
#property (nonatomic, copy) NSString *initiator;
#property (nonatomic, copy) NSString *coordinator;
#property (nonatomic, copy) NSString *riskLevel;// Low
#property (nonatomic, copy) NSString *performingGroup;
#property (nonatomic, copy) NSString *implementationPlan;
#property (nonatomic, copy) NSString *validationPlan;
#property (nonatomic, copy) NSString *recoveryScope;
#end
BNR item .h
#interface BNRItem : NSObject
{
NSString *_approverEid;
NSString *_assignmentGroup;
NSString *_changeOrder;
NSString *_subcategory; //Emergency
NSString *_title; //title
}
- (void)setApproverEid: ( NSString *)aEid;
- (NSString*)approverEid;
- (void)setAssignmentGroup: ( NSString *)aGrp;
- (NSString*)assignmentGroup;
- (void)setChangeOrder: ( NSString *)co;
- (NSString*)changeOrder;
- (void)setSubcategory: ( NSString *)sub;
- (NSString*)subcategory;
- (void)setTitle: ( NSString *)title;
- (NSString*)title;
#end
BNRItem.m
#import "BNRItem.h"
#implementation BNRItem
- (void)setApproverEid:(NSString *)aEid
{
_approverEid = aEid;
}
- (void)setAssignmentGroup: ( NSString *)aGrp
{
_assignmentGroup = aGrp;
}
- (void)setChangeOrder: ( NSString *)co
{
_changeOrder=co;
}
- (void)setSubcategory: ( NSString *)sub
{
_subcategory= sub;
}
- (void)setTitle: ( NSString *)title
{
_title = title;
}
- (NSString*)approverEid
{
return _approverEid;
}
- (NSString*)assignmentGroup
{
return _assignmentGroup;
}
- (NSString*)changeOrder
{
return _changeOrder;
}
- (NSString*)subcategory
{
return _subcategory;
}
- (NSString*)title
{
return _title;
}
#end
Related
I am very new to Objective.I am trying to make a simple application and after adding more view I get this error "Thread 1 Signal SIGABRT" and the app wont open in iOS Simulator. The error points to this line of code:
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
I tried searching before but I didn't understand what the other answers were talking about.
NamesTableViewController.h is :
#import <UIKit/UIKit.h>
#interface NamesTableViewController : UITableViewController <UISearchDisplayDelegate, UISearchBarDelegate>
#property (strong, nonatomic) IBOutlet UISearchBar *searchBar;
#end
NamesTableViewController.m is:
#import "NamesTableViewController.h"
#interface NamesTableViewController ()
#property (nonatomic, copy) NSDictionary *propertyList;
#property (nonatomic, copy) NSArray *letters;
#property (nonatomic, copy)NSMutableArray *filteredNames;
#property (nonatomic, strong)UISearchController *searchController;
#end
#implementation NamesTableViewController
#synthesize propertyList, letters, filteredNames, searchController;
- (void)viewDidLoad {
[super viewDidLoad];
UITableView *tableView = (id)[self.view viewWithTag:1];
[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"Cell"];
filteredNames = [[NSMutableArray alloc]init];
searchController = [[UISearchController alloc]init];
self.searchController.searchResultsUpdater = self;
NSString *path = [[NSBundle mainBundle] pathForResource:#"names" ofType:#"plist"];
self.propertyList = [NSDictionary dictionaryWithContentsOfFile:path];
self.letters = [[self.propertyList allKeys] sortedArrayUsingSelector:#selector(compare:)];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (tableView.tag == 1){
return self.letters.count;
}else {
return 1;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView.tag == 1) {
NSString *letter = self.letters[section];
NSArray *keyValues = [self.propertyList[letter] allKeys];
return keyValues.count;
} else {
return [filteredNames count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
if (tableView.tag == 1){
NSString *letter = self.letters[indexPath.section];;
NSArray *keyValues = [[self.propertyList[letter] allKeys] sortedArrayUsingSelector:#selector(compare:)];
cell.textLabel.text = keyValues[indexPath.row];
} else{
cell.textLabel.text = filteredNames[indexPath.row];
}
return cell;
}
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return self.letters;
}
-(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if (tableView.tag == 1) {
return letters [section];
} else {
return nil;
}
}
#pragma mark Search Display Delegate Methods
-(void)searchDisplayController:(UISearchController *)controller didLoadSearchResultsTableView:(UITableView *)tableView {
[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"Cell"];
}
-(BOOL)searchDisplayController:(UISearchController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[filteredNames removeAllObjects];
if (searchString.length > 0) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains [search] %#", self.searchBar.text];
for (NSString *letter in letters) {
NSArray *matches = [[self.propertyList[letter] allKeys]filteredArrayUsingPredicate:predicate];
[filteredNames addObjectsFromArray:matches];
}
}
return YES;
}
#end
If you want more information just say it to me by answers and I will edit my question and then you will edit your answer
[keys allKeys] returns an single-level array. Therefore there can be only one section.
Edit:
For better understanding and readability I replaced names with letters and keys with propertyList
• .h
The methods numberOfRowsInSection and cellForRowAtIndexPath retrieve the section letter and then the appropriate keys from the property list.
A dictionary as data source is not the best choice because there are many repetitive tasks to perform for example the sorting. Better create an nested array as data source in viewDidLoad
#interface NamesTableViewController ()
#property (nonatomic, copy) NSDictionary *propertyList;
#property (nonatomic, copy) NSArray *letters;
#end
• .m
#implementation NamesTableViewController
#synthesize propertyList, letters;
- (void)viewDidLoad {
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle] pathForResource:#"names" ofType:#"plist"];
self.propertyList = [NSDictionary dictionaryWithContentsOfFile:path];
self.letters = [[self.propertyList allKeys] sortedArrayUsingSelector:#selector(compare:)];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.letters.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSString *letter = self.letters[section];
NSArray *keyValues = [self.propertyList[letter] allKeys];
return keyValues.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
NSString *letter = self.letters[indexPath.section];
NSArray *keyValues = [[self.propertyList[letter] allKeys] sortedArrayUsingSelector:#selector(compare:)];
cell.textLabel.text = keyValues[indexPath.row];
return cell;
}
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return self.letters;
}
#end
I can't figure out why I am unable to set the value of an instance of PFObject. It is working successfully elsewhere in the app, but I must be doing something wrong in this view. I'd really appreciate your help figuring out what I'm missing. Thanks.
Basically
self.ABC.type = #"Frustrated";
NSLog(#"why is this null? -----> %#",self.ABC.type);
2015-10-18 18:26:29.277 XX [885:109003] why is this null? -----> (null)
Why is the value not being assigned? It should log as ... I'm not null or frustrating... I'm working, see -----> Frustrated !!!!!! but it is not working!
I'm therefore unable to set the object in Parse bc it's nil and the app crashes.
Below should be all and more of the code you need, but let me know it you have questions or suggestions. Thanks!:
FCollectionViewController.m:
#import "FCollectionViewController.h"
#import "FCell.h"
#import "SectionHeaderView.h"
#import "MBProgressHUD.h"
#import "Helper.h"
#interface FCollectionViewController()
<UICollectionViewDelegate, MBProgressHUDDelegate>
#property (nonatomic, strong) NSDictionary *presetsDictionary;
#property (nonatomic, strong) NSArray *presets;
#property (nonatomic, strong) NSIndexPath *textViewIndexPath;
#property (nonatomic, strong) FCell *fCell;
#property (nonatomic, strong) MBProgressHUD *HUD;
#property (nonatomic, strong) NSArray *headTitleArray;
#end
#implementation FCollectionViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.headTitleArray = [NSArray arrayWithObjects:
#"type",
#"model",
#"feature", nil];
PFQuery *query = [PFQuery queryWithClassName:#"Presets"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
NSMutableArray *keys = [[NSMutableArray alloc] init];
NSMutableArray *values = [[NSMutableArray alloc] init];
for (PFObject *obj in objects) {
[keys addObject:[obj objectForKey:#"key"]];
[values addObject:[obj objectForKey:#"value"]];
}
self.presetsDictionary = [NSDictionary dictionaryWithObjects:values forKeys:keys];
self.presets = [[NSMutableArray alloc] initWithObjects:
[self.presetsDictionary objectForKey:#"type"],
[self.presetsDictionary objectForKey:#"model"],
[self.presetsDictionary objectForKey:#"feature"],nil];
NSLog(#"self.presets ----> %#", self.presets);
[self.collectionView reloadData];
}];
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return [self.presets count];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [self.presets[section] count];
}
- (UICollectionReusableView*)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
UICollectionReusableView * view = nil;
if ([kind isEqualToString:UICollectionElementKindSectionHeader])
{
ItemSectionHeaderView *header = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:NSStringFromClass([ItemSectionHeaderView class])
forIndexPath:indexPath];
header.captionLabel.text = self.headTitleArray[indexPath.section];
view = header;
}
return view;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell;
FCell *aCell = (FCell *)[collectionView dequeueReusableCellWithReuseIdentifier:#"fCell" forIndexPath:indexPath];
aCell.label.text = self.presets[indexPath.section][indexPath.row];
aCell.label.textAlignment = NSTextAlignmentCenter;
cell = aCell;
return cell;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
CGSize size;
....
return size;
}
#pragma mark <UICollectionViewDelegate>
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSArray * selectedRows = self.collectionView.indexPathsForSelectedItems;
for (NSIndexPath * selectedRow in selectedRows) {
if ((selectedRow.section == indexPath.section) && (selectedRow.row != indexPath.row)) {
[self.collectionView deselectItemAtIndexPath:selectedRow animated:NO];
}
}
switch (indexPath.section) {
case 0:
self.aBC.type = #"Frustrated";
NSLog(#"why isn't this being assigned? -----> %#",self.ABC.type);
break;
case 1:
self.aBC.model = self.presets[indexPath.section][indexPath.row];
NSLog(#"why is this null?!!!! -----> %#",self.ABC.model);
NSLog(#"this DOES log the value I want!! -----> %#",self.presets[indexPath.section][indexPath.row]);
break;
case 2:
...
default:
break;
}
}
FCollectionViewController.h:
#import <UIKit/UIKit.h>
#import "ABC.h"
#interface FCollectionViewController : UICollectionViewController
//<UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
#property (nonatomic, strong) ABC *aBC;
#end
ABC.h:
#import <Foundation/Foundation.h>
#interface ABC : NSObject
#property (nonatomic, strong) NSString *type;
#property (nonatomic, strong) NSString *model;
#property (nonatomic, strong) NSString *feature;
#property (nonatomic, strong) PFObject *pfObj;
#property (nonatomic, strong) PFUser *user;
- (id)initWithPFObject:(PFObject *)anObject;
#end
ABC.m:
#import "ABC.h"
#implementation ABC
- (id)initWithPFObject:(PFObject *)anObject
{
if(self = [super init])
{
[anObject fetchIfNeeded];
self.pfObj = anObject;
self.type = [anObject objectForKey:#"type"];
self.model = [anObject objectForKey:#"model"];
...
}
return self;
}
#end
FCell.h:
#import <UIKit/UIKit.h>
#interface FCell : UICollectionViewCell
#property (weak, nonatomic) IBOutlet UILabel *label;
#end
FCell.m:
#import "FCell.h"
#implementation FCell
-(void)setHighlighted:(BOOL)highlighted
{
[super setHighlighted:highlighted];
self.selectedBackgroundView = [[UIView alloc] initWithFrame:self.frame];
self.selectedBackgroundView.backgroundColor = [UIColor darkGrayColor];
[self setNeedsDisplay];
}
#end
aBC isn't initialized anywhere. You declare it, but it isn't initialized. So setting aBC.type isn't actually setting anything.
Add self.aBC = [[ABC alloc] init]; in your viewDidLoad method.
#interface PADiscover : NSObject
#property (nonatomic, assign) unsigned int dw3C;
#property (nonatomic, assign) BOOL isSet;
#property (nonatomic, assign) PAContactModel model;
#end
In another VC
#property (nonatomic, strong) NSMutableDictionary *shakeDict;
Then I add some objects to shakeDict
- (void)viewDidLoad {
NSNumber *num = [NSNumber numberWithUnsignedInt:message.sDeviceInfo.dw3CId];
PADiscover *discover = [[PADiscover alloc] init];
discover.dw3C = message.sDeviceInfo.dw3CId;
discover.model = message.sDeviceInfo.dwDeviceType;
discover.isSet = message.sDeviceInfo.fgPasswdFlag;
[_shakeDict setObject:discover forKey:[NSString stringWithFormat:#"%#", num]];
[_shakeTV reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
}
PADiscover *discover = [[_shakeDict allKeys] objectAtIndex:indexPath.row];
**cell.textLabel.text = [NSString stringWithFormat:#"ID %u, ISSet %d", discover.dw3C, discover.isSet];//crashed!**
cell.detailTextLabel.text = [NSString stringWithFormat:#"model %d", discover.model];
cell.detailTextLabel.font = [UIFont boldSystemFontOfSize:11];
return cell;
}
It seems cannot deference PADiscover successfully,but I'm not sure when place I get some wrong.
can anyone explain that for me?
Try this,
NSString *key = [[_shakeDict allKeys] objectAtIndex:indexPath.row];
PADiscover *discover = [_shakeDict objectForKey:key];
instead of
PADiscover *discover = (PADiscover *)[[_shakeDict allKeys] objectAtIndex:indexPath.row];
At least this line may be error:
#property (nonatomic, assign) PAContactModel model;
change to strong if a model class.
#property (nonatomic, strong) PAContactModel model;
I think just showing my whole code is better than my explanation.. actually I'm not good at expressing something in English.X(
this code is .h file for .m file below.
#import <UIKit/UIKit.h>
#define kImageValueTag 0
#define kNameValueTag 1
#define kSubtitleValueTag 2
#define kMemoValueTag 3
#class PhonebookDetailedViewController;
#interface PhonebookViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
{
UITableViewCell *tvCell;
UITableView *tableView;
UISearchBar *searchBar;
NSString *fullName;
NSMutableDictionary *names, *pictures;
NSArray *keys, *sortedKeys, *sortedAllValues;
PhonebookDetailedViewController *childController;
}
#property (nonatomic, retain) IBOutlet UITableViewCell *tvCell;
#property (nonatomic, retain) IBOutlet UISearchBar *searchBar;
#property (nonatomic, retain) IBOutlet UITableView *tableView;
#property (nonatomic, retain) UIImage *phoneImage;
#property (nonatomic, retain) NSString *fullName;
#property (nonatomic, retain) NSMutableDictionary *names;
#property (nonatomic, retain) NSMutableDictionary *pictures;
#property (nonatomic, retain) NSArray *keys;
#property (nonatomic, retain) NSArray *sortedKeys;
#property (nonatomic, retain) NSArray *sortedAllValues;
#end
this code is for the .m file that implement showing a table. When I try to scroll the table down, the error named EXC_BAD_ACCESS is suddenly called at - (NSString *)tableView: titleForHeaderInSection: method. I guess sortedKeys releases at somewhere because I can do [sortedKeys count] before error, but cannot when error comes. I don't know where it releases and why it releases, however. Please show your ideas to me. Any ideas are okay. Thank you in advance.
#import "PhonebookViewController.h"
#import "PhonebookDetailedViewController.h"
#import "NSString-SortForIndex.h"
#implementation PhonebookViewController
#synthesize tvCell;
#synthesize searchBar;
#synthesize tableView;
#synthesize phoneImage;
#synthesize fullName;
#synthesize names, pictures;
#synthesize keys, sortedAllValues, sortedKeys;
//- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
//{
// self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
// if (self) {
// // Custom initialization
// }
// return self;
//}
//- (void)didReceiveMemoryWarning
//{
// // Releases the view if it doesn't have a superview.
// [super didReceiveMemoryWarning];
//
// // Release any cached data, images, etc that aren't in use.
//}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect bounds = self.tableView.bounds;
bounds.origin.y = bounds.origin.y + searchBar.bounds.size.height;
self.tableView.bounds = bounds;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *nameFilePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"nameContacts.dict"];
NSString *pictureFilePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"imageContacts.dict"];
self.names = (NSMutableDictionary *)[NSKeyedUnarchiver unarchiveObjectWithFile:nameFilePath];
self.pictures = (NSMutableDictionary *)[NSKeyedUnarchiver unarchiveObjectWithFile:pictureFilePath];
self.keys = [self.names allKeys];
sortedKeys = [self.keys sortedArrayUsingSelector:#selector(sortForIndex:)];
sortedAllValues = [[NSArray alloc] init];
for (NSString *sortedKey in sortedKeys)
{
NSArray *selectedValues = [self.names valueForKey:sortedKey];
for (NSString *selectedValue in selectedValues)
sortedAllValues = [sortedAllValues arrayByAddingObject:selectedValue];
}
// Do any additional setup after loading the view from its nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.tableView = nil;
self.searchBar = nil;
self.tvCell = nil;
self.fullName = nil;
self.names = nil;
self.pictures = nil;
self.keys = nil;
self.sortedKeys = nil;
self.sortedAllValues = nil;
}
- (void)dealloc
{
[tableView release];
[searchBar release];
[tvCell release];
[fullName release];
[names release];
[pictures release];
[keys release];
[sortedKeys release];
[sortedAllValues release];
[super dealloc];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table Data Source Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [sortedKeys count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *key = [sortedKeys objectAtIndex:section];
NSArray *nameSection = [names objectForKey:key];
return [nameSection count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CustomCellIdentifier = #"CustomCellIdentifier";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CustomCellIdentifier];
if ( cell == nil )
{
NSArray *nib = [[NSBundle mainBundle]
loadNibNamed:#"CustomPhonebookCell"
owner:self
options:nil];
if (nib.count > 0)
{
cell = self.tvCell;
} else
{
NSLog(#"Failed to load CustomPhonebookCell nib file!");
}
}
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
NSUInteger row = [indexPath row];
NSUInteger section = [indexPath section];
NSString *foundKey = [sortedKeys objectAtIndex:section];
NSArray *nameSection = [self.names objectForKey:foundKey];
UILabel *nameLabel = (UILabel *)[cell viewWithTag:kNameValueTag];
nameLabel.text = [nameSection objectAtIndex:row];
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSString *key = [sortedKeys objectAtIndex:section]; // EXC_BAD_ACCESS error at here
return key;
}
sortedKeys is not properly retained. When you set it use self.
self.sortedKeys = [self.keys sortedArrayUsingSelector:#selector(sortForIndex:)];
I think I'm not getting the handle on address book and UITableView, or maybe I'm just making it simpler than it is.
here is my .h file:
#interface Contacts : UITableViewController <ABPeoplePickerNavigationControllerDelegate> {
NSMutableArray *menuArray;
NSString *firstName;
NSString *lastName;
UIButton *addcontact;
}
#property (nonatomic, retain) NSMutableArray *menuArray;
#property (nonatomic, strong) UIButton *addcontact;
#property (nonatomic, strong) NSString *firstName;
#property (nonatomic, strong) NSString *lastName;
-(void)showPeoplePickerController;
#end
And my .m file:
-(IBAction)addcontact:(id)sender {
ABPeoplePickerNavigationController *peoplePicker=[[ABPeoplePickerNavigationController alloc] init];
[peoplePicker setPeoplePickerDelegate:self];
[self presentModalViewController:peoplePicker animated:YES]; }
- (void)viewDidLoad
{
menuArray = [[NSMutableArray alloc] init];
[super viewDidLoad];
}
- (BOOL)peoplePickerNavigationController:
(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person {
firstName = (__bridge NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
[menuArray addObject:firstName];
lastName = (__bridge NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
[menuArray addObject:lastName];
[self dismissModalViewControllerAnimated:YES];
return NO;}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [menuArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSString *cellValue = [menuArray objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
return cell;
}
I hope someone could help me with it, I'm fairley new to UITableViews and Addressbooks :)
For performance purposes (not to mention animation purposes), UITableView does not automatically update itself whenever the data source changes.
Try adding [myTableView reloadData]; after you add the first and last name to the arrays (or in viewWillAppear: