I'm retrieving Contact name and phone no. from the Address book in my application. I'm printing them in log and it is working fine. But when I try to show them on the table view, I'm getting the exception NSInvalidArgumentException. I have a button on the view controller, pressing which the table view should get populated with the contact names and their no.s:
- (IBAction)syncContacts:(id)sender
{
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
for (int i = 0; i < ABAddressBookGetPersonCount(addressBook); i++) {
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i);
NSString *contact = (NSString *)CFBridgingRelease(ABRecordCopyCompositeName(ref));
// NSString* phone = nil;
ABMultiValueRef phoneNumbers = ABRecordCopyValue(ref,kABPersonPhoneProperty);
// if (ABMultiValueGetCount(phoneNumbers) > 0) {
NSString *phone = (__bridge_transfer NSString*)
ABMultiValueCopyValueAtIndex(phoneNumbers, 0);
// }
NSDictionary *curContact=[NSDictionary dictionaryWithObjectsAndKeys:(NSString *)contact,#"Name",phone,#"phone",nil];
[self.phoneContacts addObject:curContact];
}
tableView.delegate = self;
tableView.dataSource = self;
[tableView reloadData];
NSLog(#"%#",self.phoneContacts);
NSLog(#"%i",[self.phoneContacts count]);
}
And the table view methods are:
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.phoneContacts count];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
// cell.textLabel.text = [self.phoneContacts objectAtIndex:indexPath.row];
cell = [self.phoneContacts objectAtIndex:indexPath.row];
return cell;
}
What's wrong with the table view? When the phoneContacts had only the name, it was working fine.([phoneContacts addObject:contact]). But now when I'm adding the dictionary object, it is throwing this exception.
I've made a change.
cell = [[self.phoneContacts objectAtIndex:indexPath.row] objectForKey:#"AddressBook"];
The exception doesn't come now. But nothing is getting shown on screen.
Here's the edited method:
- (IBAction)syncContacts:(id)sender
{
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
for (int i = 0; i < ABAddressBookGetPersonCount(addressBook); i++) {
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i);
// NSNumber *contact = (NSNumber *)ABRecordCopyComposite();// (ref));
NSString *contact = (NSString *)CFBridgingRelease(ABRecordCopyCompositeName(ref));
// NSString* phone = nil;
ABMultiValueRef phoneNumbers = ABRecordCopyValue(ref,kABPersonPhoneProperty);
// if (ABMultiValueGetCount(phoneNumbers) > 0) {
NSString *phone = (__bridge_transfer NSString*)
ABMultiValueCopyValueAtIndex(phoneNumbers, 0);
// }
// NSDictionary *curContact=[NSDictionary dictionaryWithObjectsAndKeys:(NSString *)contact,#"Name",phone,#"phone",nil];
contact = [contact stringByAppendingString:#" "];
contact = [contact stringByAppendingString:phone];
[self.phoneContacts addObject:contact];
}
tableView.delegate = self;
tableView.dataSource = self;
[tableView reloadData];
}
The table view remains unchanged as given in the original post. It is now working.
The commented line cell.textLabel.text = [self.phoneContacts objectAtIndex:indexPath.row]; doesn't work? Can you set breakpoint and check if the cell's textlabel have the text assigned?
Assigning the cell using
cell = [[self.phoneContacts objectAtIndex:indexPath.row] objectForKey:#"AddressBook"]
wouldn't work, unless you defined phoneContacts to be subclass of UITableViewCell.
Related
Below is what I am using to retrieve the contacts list from the device. I want it to be displayed alphabetically but using other examples seen on stack overflow I have been unable to get it to work.
The code below is from a tutorial, what do I need to do to it to sort according to alphabetical order?
- (void)getPersonOutOfAddressBook
{
//1
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
if (addressBook != nil) {
NSLog(#"Succesful.");
//2
NSArray *allContacts = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
//3
NSUInteger i = 0; for (i = 0; i < [allContacts count]; i++)
{
Person *person = [[Person alloc] init];
ABRecordRef contactPerson = (__bridge ABRecordRef)allContacts[i];
//4
NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson,
kABPersonFirstNameProperty);
NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonLastNameProperty);
NSString *fullName = [NSString stringWithFormat:#"%# %#", firstName, lastName];
person.firstName = firstName; person.lastName = lastName;
person.fullName = fullName;
//email
//5
ABMultiValueRef emails = ABRecordCopyValue(contactPerson, kABPersonEmailProperty);
//6
NSUInteger j = 0;
for (j = 0; j < ABMultiValueGetCount(emails); j++) {
NSString *email = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(emails, j);
if (j == 0) {
person.homeEmail = email;
NSLog(#"person.homeEmail = %# ", person.homeEmail);
}
else if (j==1) person.workEmail = email;
}
//7
[self.tableData addObject:person];
}
//8
CFRelease(addressBook);
} else {
//9
NSLog(#"Error reading Address Book");
}
}
This is my UITableView code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"Identifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
Person *person = [self.tableData objectAtIndex:indexPath.row];
cell.textLabel.text = person.fullName;
return cell;
}
I have tried below
[self.tableData sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
I have also tried NSSortDescriptor but I don't have a Key to sort by.
You'll need to sort the array of Person objects. Once you have finished adding them all to the array you can sort on the fullName using the following code:
[self.tableData sortUsingComparator:^NSComparisonResult(Person *p1, Person *p2) {
return [p1.fullName compare:p2.fullName];
}];
Alternative
You may want to implement a compare: method on the Person object and perform the comparison there, this will keep sorting logic nicely encapsulated and ensure that anything else that uses Person objects can easily perform sorts without duplicating the code shown above.
#implementation Person
// Mostly likely this implementation will contain more code, not shown for brevity
- (NSComparisonResult)compareByFullName:(Person *)otherPerson {
return [self.fullName compare:otherPerson.fullName];
}
#end
Then you can sort the array with:
[self.tableData sortUsingSelector:#selector(compareByFullName:)];
You need to implement and provide a method to sort a Person record as a selector for the sortUsingSelector method invocation.
I managed to solve it like this.
//keys with fetching properties NSArray *keys = #[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactEmailAddressesKey]; CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:keys];
//Order contacts by Surname. request.sortOrder = CNContactSortOrderFamilyName;
--OR YOU CAN--
//Order contacts by Name. request.sortOrder = CNContactSortOrderGivenName;
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I created an ABAddressBook on a UITableView. Now, I need to pass the firstname, last name, etc. to next viewcontroller.
I have to pass data using nsobject class ... in this project i have made Person class which has string properties of name,lastname,number,email.
The code for address book is:
ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook);
allPeople = (__bridge NSMutableArray *)(ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonFirstNameProperty));
NSInteger numberOfPeople = [allPeople count];
for (NSUInteger i = 0; i < numberOfPeople; i++) {
personContact = [[Person alloc]init];
person = (__bridge ABRecordRef)allPeople[i];
NSString *firstName = (__bridge NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty);
NSString *lastName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty));
if (firstName == nil ) {
firstName = #"";
}
if (lastName == nil)
{
lastName = #"";
}
NSString *fullName = [NSString stringWithFormat:#"%# %#",firstName,lastName];
personContact.firstName = firstName;
personContact.lastName = lastName;
personContact.fullName = fullName;
//For adding multiple contacts:
ABMultiValueRef phoneNumbers = ABRecordCopyValue((person), kABPersonPhoneProperty);
CFIndex numberOfPhoneNumbers = ABMultiValueGetCount(phoneNumbers);
for (CFIndex i = 0; i < numberOfPhoneNumbers; i++) {
NSString *phoneNumber = CFBridgingRelease(ABMultiValueCopyValueAtIndex(phoneNumbers, i));
if ([phoneNumber isEqualToString:#""])
{
phoneNumber = #"Not Available";
}
NSCharacterSet *trim = [NSCharacterSet characterSetWithCharactersInString:#"#();$&-+"];
phoneNumber = [[phoneNumber componentsSeparatedByCharactersInSet: trim] componentsJoinedByString: #""];
phoneNumber= [phoneNumber stringByReplacingOccurrencesOfString:#"\"" withString:#""];
phoneNumber=[phoneNumber stringByReplacingOccurrencesOfString:#"" withString:#""];
personContact.phoneNumber = phoneNumber;
//Emails
ABMutableMultiValueRef eMail = ABRecordCopyValue(person, kABPersonEmailProperty);
if(ABMultiValueGetCount(eMail) > 0)
{
email =CFBridgingRelease(ABMultiValueCopyValueAtIndex(eMail, 0));
}
else
{
email = #"";
}
personContact.email = email;
}
//Photos
CFDataRef imgData = ABPersonCopyImageData(person);
NSData *imageData = (__bridge NSData *)(imgData);
phoneImage = [UIImage imageWithData:imageData];
if (phoneImage == nil) {
phoneImage = [UIImage imageNamed:#"userEdit"];
}
CGSize destinationSize = CGSizeMake(70, 70);
UIGraphicsBeginImageContext(destinationSize);
[phoneImage drawInRect:CGRectMake(0, 0, destinationSize.width, destinationSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if (imgData != NULL)
{
CFRelease(imgData);
}
personContact.photos = (NSString *)newImage;
[contactsData addObject:personContact];
[contactstableView reloadData];
}
}
And the code for cellforrowatIndex path is as follows:-
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier=#"CellID";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell==nil)
{
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
cell.backgroundColor=[UIColor colorWithRed:238.0/255.0 green:238.0/255.0 blue:239.0/255.0 alpha:1.0];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
personContact = [searchResults objectAtIndex:indexPath.row];
}
else {
personContact = [contactsData objectAtIndex:indexPath.row];
}
if (contactsData.count > 0)
{
cell.textLabel.text = personContact.fullName;
cell.imageView.image = personContact.photos;
cell.imageView.layer.cornerRadius = 35;
cell.imageView.layer.masksToBounds = YES;
cell.imageView.contentMode = UIViewContentModeScaleAspectFit;
}
On didselect row, I want to pass all the contact details to next controller. Please help?
If you have to pass it from ABAddressBook to ViewController use delegate methods
If you have to pass it to ABAddressBook you can Pass ABPerson or Associative properties
objc_setAssociatedObject(actionSheet, #"selectedUserJidStr", selectedUserJidStr, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
I guess you will display view on cell select, which you can do using following delegate method.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"segueName" sender:indexPath];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"segueName"])
{
NSIndexPath *indexPath = sender;
ViewControllerName *objectOfViewControllerName = segue.destinationViewController;
objectOfViewControllerName.personContact = [contactsData objectAtIndex:indexPath.row];
}
}
I am doing this in cellforrowAtIndexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
AddGuestVC *add = [[AddGuestVC alloc]initWithNibName:#"AddGuestVC" bundle:nil];
add.personContact = [contactsData objectAtIndex:indexpath.row];
add.delegate = self;
add.personContact = personContact;
[self.navigationController pushViewController:add animated:YES];
}
}
and for populating textfield i use :
firstname.text = self.personContact.firstName;
I want to create program that will import contacts from adressbook and show them in tableview. I already did code to download contacts from adressbook but when I'm adding them into Array and then trying to show in TableView they don't appear when I'm starting app. Here's code:
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[self getPersonOutOfAddressBook];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.tableData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"Identifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
Person *person = [self.tableData objectAtIndex:indexPath.row];
cell.textLabel.text = person.fullName;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
}
- (void)getPersonOutOfAddressBook
{
//1
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
__block BOOL accessGranted = NO;
if (ABAddressBookRequestAccessWithCompletion != NULL) { // We are on iOS 6
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
accessGranted = granted;
dispatch_semaphore_signal(semaphore);
});
}
if (addressBook != nil) {
NSLog(#"Succesful.");
//2
NSArray *allContacts = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
//3
NSUInteger i = 0; for (i = 0; i < [allContacts count]; i++)
{
Person *person = [[Person alloc] init];
ABRecordRef contactPerson = (__bridge ABRecordRef)allContacts[i];
//4
NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson,
kABPersonFirstNameProperty);
NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonLastNameProperty);
NSString *fullName = [NSString stringWithFormat:#"%# %#", firstName, lastName];
person.firstName = firstName; person.lastName = lastName;
person.fullName = fullName;
[self.tableData addObject:person];
}
//8
CFRelease(addressBook);
} else {
//9
NSLog(#"Error reading Address Book");
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
When I'm using debugger it shows that variables firstname, lastname and then fullname have access to adressbook because I can see name or last name of person. But I think there is problem with adding to array because I can't see anything in this array. Could someone help me? I'm beginner with Objective - C so please forbearance :)
To use an array you need to both declare it and create it. You do this by allocating and initializing the array.
self.tableData = [[NSMutableArray alloc] init];
I am trying to load Contacts that contain addresses to my TableView. I attempted to debug it and the NSLogs are showing that the data is there. However when I try to load it to my UITableView, it hangs on a black screen and nothing happens. The debugger shows the data is printed to console.
I am using an iOS 7 simulator for testing my project.
#implementation ViewController
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
_contactsArray = [[NSMutableArray alloc] init];
[self getArrayOfPeople];
NSLog(#"array: %#", self.contactsArray);
}
return self;
}
- (void)getArrayOfPeople {
//ABAddressBookRef addressBook = ABAddressBookCreate();
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
__block BOOL accessGranted = NO;
if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
accessGranted = granted;
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
else { // we're on iOS 5 or older
accessGranted = YES;
}
if (accessGranted) {
for( CFIndex emailIndex = 0; emailIndex < nPeople; emailIndex++ ) {
ABRecordRef person = CFArrayGetValueAtIndex( allPeople, emailIndex );
//ABMutableMultiValueRef emailRef= ABRecordCopyValue(person, kABPersonEmailProperty);
ABMutableMultiValueRef addressRef= ABRecordCopyValue(person, kABPersonAddressProperty);
int addressCount = (int)ABMultiValueGetCount(addressRef);
if(!addressCount) {
CFErrorRef error = nil;
ABAddressBookRemoveRecord(addressBook, person, &error);
if (error) NSLog(#"Error: %#", error);
} else {
ABMultiValueRef address = ABRecordCopyValue(person, kABPersonAddressProperty);
NSString *contactAddress = (__bridge NSString *)ABMultiValueCopyValueAtIndex(address, 0);
NSString *name = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
if (name) {
NSMutableDictionary *contactDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
name, #"name",
contactAddress, #"address",
nil];
[self.contactsArray addObject:contactDict];
NSLog(#"%#", self.contactsArray);
}
}
}
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_contactsArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [_contactsArray objectAtIndex:indexPath.row];
return cell;
}
#end
I hope my pasted code above will help find the "bug" thats causing my code to malfunction.
try calling reloadData on your table view after you populate your array
[myTableView reloadData];
You are adding NSDictionary items to the array, but assigning them to cell.textLabel.text in your cellForRowAtIndexPath:. Try
cell.textLabel.text = [[_contactsArray objectAtIndex:indexPath.row] valueForKey:#"name"];
You do this:
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
before requesting access to the address book, so you get -1 and you're stuck in a very consuming loop in getArrayOfPeople. Move the following lines:
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
into the if (accessGranted) block.
Did you modify its launch in the appDidFinishLaunching or something else that you think may have had something to do with its normal launch
Check and try following things to debug the problem.
If its your 1st view ,just check if you have connect view to root of Navigation controller
Try to remove the class from the view and check if view is loading.
Try to add a new view Controller without linking class and add it to your navigation controller and check if its displaying white or black screen.
I have a UITableView which is populated with some parsed JSON twitter data. The intent is to have the user select the a row, and have the data passed to a modalViewController, which in this case is a map displaying coordinate and annotation information.
In the debug console I can see the data loaded into each visible UITableViewCell, plus the first one off screen (last loaded). When I run the app, and attempt to select a row, no matter which row I select, the data from the last loaded cell is always the data passed to the modalViewController.
I have logged to ensure the correct row is selected (it is) but no matter which row is selected, the last data loaded is always the data that is pushed.
First the Data Source Methods
#pragma mark -
#pragma mark UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSUInteger count = [self.results count];
return count > 0 ? count : 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ResultCellIdentifier = #"ResultCell";
static NSString *LoadCellIdentifier = #"LoadingCell";
NSUInteger count = [self.results count];
if ((count == 0) && (indexPath.row == 0)) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:LoadCellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:LoadCellIdentifier];
cell.textLabel.textAlignment = UITextAlignmentCenter;
}
if (self.connection) {
cell.textLabel.text = #"Loading...";
} else {
cell.textLabel.text = #"Not available";
}
return cell;
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ResultCellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:ResultCellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.numberOfLines = 0;
cell.textLabel.font = [UIFont systemFontOfSize:14.0];;
}
UIImage *image = [UIImage imageNamed:#"medicaltag.png"];
cell.imageView.image = image;
// Begin UITableCell Data Formatting
NSDictionary *tweet = [self.results objectAtIndex:indexPath.row];
NSString* tweetText = [tweet objectForKey:#"text"];
if ([tweetText rangeOfString:#" *** "].location !=NSNotFound) {
NSArray *textItems = [tweetText componentsSeparatedByString:#" *** "];
NSLog(#"%#", textItems);
callAddress = [textItems objectAtIndex:0];
callAddress = [callAddress stringByReplacingOccurrencesOfString:#" , " withString:#", "];
callType = [textItems objectAtIndex:1];
NSLog(#"%#", callType);
NSLog(#"%#", callAddress);
NSString *latitude = [textItems objectAtIndex:2];
NSString *latStringPt1 = [[NSString alloc] init];
NSString *latStringPt2 = [[NSString alloc] init];
NSString *longitude = [textItems objectAtIndex:3];
longitude = [longitude stringByReplacingOccurrencesOfString:#"- " withString:#"-"];
NSString *lonStringPt1 = [[NSString alloc] init];
NSString *lonStringPt2 = [[NSString alloc] init];
int latStringLen = [latitude length];
int lonStringLen = [longitude length];
NSLog(#"The value of integer num is %i", latStringLen);
latStringPt1 = [latitude substringWithRange:NSMakeRange(0,latStringLen-6)];
latStringPt2 = [latitude substringFromIndex:latStringLen-6];
combinedLatString = [latStringPt1 stringByAppendingString:#"."];
combinedLatString = [combinedLatString stringByAppendingString:latStringPt2];
lonStringPt1 = [longitude substringWithRange:NSMakeRange(0,lonStringLen-6)];
lonStringPt2 = [longitude substringFromIndex:lonStringLen-6];
combinedLonString = [lonStringPt1 stringByAppendingString:#"."];
combinedLonString = [combinedLonString stringByAppendingString:lonStringPt2];
NSLog(#"%#", combinedLatString);
NSLog(#"%#", combinedLonString);
}
cell.textLabel.text = [NSString stringWithFormat:#"%#", callAddress];
cell.textLabel.font = [UIFont boldSystemFontOfSize:16];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#", callType];
cell.detailTextLabel.font = [UIFont systemFontOfSize:14];
return cell;
}
Now the Delegate Method
#pragma mark -
#pragma mark Table View Delegate Methods*
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = [indexPath row];
NSLog(#"%i", row);
CallMapViewController *mapVC = [[CallMapViewController alloc] initWithNibName:#"CallMapViewController" bundle:[NSBundle mainBundle]];
mapVC.annotCallType = callType;
mapVC.annotCallAddress = callAddress;
NSLog(#"%#", mapVC.annotCallType);
NSLog(#"%#", mapVC.annotCallAddress);
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber *lat = [f numberFromString:combinedLatString];
NSNumber *lon = [f numberFromString:combinedLonString];
mapVC.annotLatCoord = lat;
mapVC.annotLonCoord = lon;
NSLog(#"%#", lat);
NSLog(#"%#", lon);
NSLog(#"%#", callType);
NSLog(#"%#", callAddress);
[self presentModalViewController:mapVC animated:YES];
}
You already have your tweet data stored in your viewController's property results, so you just need to grab the data from there and parse it again (as Daryl Teo mentions) in didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString* tweetText = [[self.results objectAtIndex:indexPath.row] objectForKey:#"text"];
if ([tweetText rangeOfString:#" *** "].location != NSNotFound) {
NSArray *textItems = [tweetText componentsSeparatedByString:#" *** "];
CallMapViewController *mapVC = [[CallMapViewController alloc] initWithNibName:#"CallMapViewController" bundle:[NSBundle mainBundle]];
mapVC.callAddress = [[textItems objectAtIndex:0] stringByReplacingOccurrencesOfString:#" , " withString:#", "];
mapVC.callType = [textItems objectAtIndex:1];
[self presentModalViewController:mapVC animated:YES];
}
}
You get [indexPath row] but you don't use it.
And you've got "callType" and "callAddress" which aren't within the scope of the delegate method. They exist as instance variables of the viewController, and you set their values as you're creating the cells. That's why their values are always the values of the last cell.
You need to store the data in memory, so that you can reference it when you get the row from indexPath.
NSInteger row = [indexPath row];
NSString *tweetText = [tweetsStorageArray objectAtIndex: row];
/* Parse Tweet Text again */
You can either store tweets as text, or create a storage class and store that.
From what I can see in the method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
You take the [indexPath row]; but you don't chose your data base on that.
I see that in your delegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath () you are only accessing the selected row variable for NSLog messages.
You would probably need to access the cell using UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath] and its contents using callType = cell.detailTextLabel.text;and callAddress = cell.textLabel.text;