How to retrieve kABPhoneNumber from Address Book in Cocoa with multiValues? - objective-c

I'm trying to extract phone numbers from an ABRecord and put it into a NSTableView. It logs the number, but the app crashes when the tableView is scrolled and tries to get more data. Is the way I'm retrieving the number the right way to do so? Its not clear to me why it sometimes fails to load it into the cell.
-(NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row
{
contactCell *cellView = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self];
if( [tableColumn.identifier isEqualToString:#"cell"] )
{
ABPerson *indexedPerson = contactsArr[row];
ABRecord *record = contactsArr[row];
NSString *numberString = #"";
NSString *nameInfo = [NSString stringWithFormat:#"%# %#",
[indexedPerson valueForKey:kABFirstNameProperty],
[indexedPerson valueForKey:kABLastNameProperty]];
//get the number
ABMutableMultiValue *multiValue = [record valueForProperty:kABPhoneProperty];
NSLog(#"currentPerson: %#",indexedPerson);
//see if there is data in the multi value
if ([multiValue valueAtIndex:1]) {
numberString = [multiValue valueAtIndex:1];
} else {
numberString = #"";
}
NSLog(#"%# test", numberString);
//set the strings
[cellView.nameField setTitle:nameInfo];
//set field in cell
[cellView.numberField setTitle:numberString];
return cellView;
}
return cellView;
}

Instead of checking index 0, I was checking index 1. Changing to index 0 in the if statement checking for data in the multivalue resolved the issue.

Related

How do I get a UITableView' cell's data?

I need to get part of the selected row's data (cell.textLabel.text). The problem is this is what is in the cell (according to the debugger) and I can't figure out how to get to it. This is the line of code in -didSelectRowAtIndexPath
NSString *cellText = selectedCell.textLabel.text;
and this is what's in selectedCell.textLabel.text:
For the life of me, I can't figure out how to get the 1st of the 3 parts.
Any ideas/comments/answers would be greatly appreciated!
Have you tried something like this?
NSString *cellText = selectedCell.textLabel.text;
NSArray *components = [cellText componentsSeparatedByString:#" "];
if (components.count > 0) {
NSString *firstPart = components[0];
NSLog(#"%#", firstPart);
}
I got it to work; this is the code:
- (void) tableView:(UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath {
if(isFiltered) {
Books *su = filteredTableData[indexPath.row];
passedSKU = su.sku;
}
else {
// get the key from the cell that was selected from the list
Books *selectedBook = [booksArray objectAtIndex:indexPath.row];
passedSKU = selectedBook.sku;
}
// programmatically set the tabBar index
[self.tabBarController setSelectedIndex: 1];
}

function to check if there is any empty cell in a multicolumn nstableview not working

Hi i have written a function to check if there is any empty cell in a multicolumn nstableview like below.However this function is not working and always checks for the columns in the first row only.. any suggestions.and what is the right way to check for it
-(BOOL)isTableRowsContainingEmptyCells
{
for(int row=0;row< [[self.myarray arrangedObjects] count];row++)
{
NSTableColumn *column1 = [self.formFieldValues
tableColumnWithIdentifier:#"A"];
NSTableColumn *column2 = [self.formFieldValues
tableColumnWithIdentifier:#"B"];
NSCell *cell1 = [column1 dataCellForRow:row];
NSCell *cell2 = [column2 dataCellForRow:row];
NSLog(#"cell1 %# cell2 %#",cell1,cell2);
if([[cell1 stringValue] isEqualToString:#""]||[cell1 stringValue]==nil||[[cell2 stringValue] isEqualToString:#""]||[cell2 stringValue]==nil)
{
return YES;
}
}
return NO;
}
Try like this
NSCell *cll=[tableView preparedCellAtColumn:0 row:0];
NSString *str=[cll stringValue];
NSInteger len=[str length];
if (len ==0)
{
NSLog(#"NO data")
}

Trying to identify selected table view cells

I'm trying to find selected people in an array. I'm correctly getting where no one is selected, however, if one person in a group is selected, all people in the group are selected.
After a long head-scratching session, I could use some help to see if there is something obvious.
This action is going on in cellForRowAtIndexPath like this:
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"%s", __FUNCTION__);
static NSString *pCell = #"Cell";
PeopleCell *cell = (PeopleCell *)[aTableView dequeueReusableCellWithIdentifier:pCell];
if (cell == nil) {
cell = [[PeopleCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:pCell];
}
people = [peopleArray objectAtIndex:[indexPath row]];
NSString *text = [people objectForKey:#"name"];
cell.textLabel.text = text;
if (selectedPeopleinGroup.count == 0) {
//no people selected in this group
NSLog(#"none");
cell.isSelected = [selectedPeopleinGroup containsObject:text] == NO;
} else {
//there are some people in this group - find out who they are
NSLog(#"some");
NSString *key1 = [selectedPeopleinGroup valueForKey:#"personKey"];
NSString *key2 = [people valueForKey:#"personKey"];
NSLog (#"key1 %#", key1 );
NSLog (#"key2 %#", key2 );
if (key1 == key2) {
cell.isSelected = [selectedPeople containsObject:text] == YES;
} else {
cell.isSelected = [selectedPeople containsObject:text] == NO;
}
}
return cell;
}
The cell is a subclassed UITableViewCell that has a checkmark image on the left side of the cell if selected and a different image if not selected. Many thanks.
This looks odd:
NSString *key1 = [selectedPeopleinGroup valueForKey:#"personKey"];
if selectedPeopleInGroup is an array, then valueForKey: returns an array of the results of calling valueForKey on each object in the array. So you are assigning an array to a string.
I'm surprised that the compiler is not issuing a warning about this. I'm also surprised that the log statements don't show odd values.

Checking/Unchecking a tableviewcell with sections

Previously, I had a large-ish dataset (~530 records) being displayed in a tableview. The data was held in an array of dictionaries with two keys, ID and name. Previously, I tapped a cell, it added a check mark, and it sent the cell row number to a 'selectedArray'. As I had already alphabetically sorted them (still in one section), the indexPath.row which was stored in the selectedArray corresponded to the dictionaries' array index, so I could pull data (the ID) from the record.
I decided that I would split this into headers by alphabetical order (which was an absolute pain, I don't see why it's such a complex process to insert headers into a list of records). But now, as I only used indexPath.row, when I tick the first one, it ticks the first record of each section, and only returns the number 0, so I only get the first record in the whole dataset. Is there a simple way to correct this? Really appreciate any help.
cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"inviteCell"];
// cell.accessoryType = UITableViewCellAccessoryCheckmark;
if ([checkedCells objectForKey:[NSNumber numberWithInt:indexPath.row]] != nil) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
// NSDictionary *friend = [sortedFriendsArray objectAtIndex:indexPath.row];
//---get the letter in the current section---
NSString *alphabet = [nameIndex objectAtIndex:[indexPath section]];
//---get all states beginning with the letter---
NSPredicate *predicate =
[NSPredicate predicateWithFormat:#"SELF.name beginswith[c] %#", alphabet];
NSArray *states = [sortedFriendsArray filteredArrayUsingPredicate:predicate];
if ([states count]>0) {
//---extract the relevant state from the states object---
NSDictionary *friend = [states objectAtIndex:indexPath.row];
long long fbid = [[friend objectForKey:#"id"]longLongValue];
NSString *name = [friend objectForKey:#"name"];
NSString *urlString = [NSString stringWithFormat:#"https://graph.facebook.com/%qi/picture?type=square",fbid];
NSURL *url = [NSURL URLWithString:urlString];
UILabel *eventNameLabel = (UILabel *) [cell viewWithTag:1];
eventNameLabel.text = name;
UIImageView *eventLogo = (UIImageView*) [cell viewWithTag:2];
eventLogo.image = [UIImage imageNamed:#"112-group.png"];
// eventLogo.image = [UIImage imageWithData: [NSData dataWithContentsOfURL:url]];;
}
return cell;
}
CURRENT didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSNumber *indexNumber = [NSNumber numberWithInt:indexPath.row];
NSDictionary *friend = [sortedFriendsArray objectAtIndex:indexPath.row];
long long fbid = [[friend objectForKey:#"id"]longLongValue];
NSNumber *fbidNum = [NSNumber numberWithLongLong:fbid];
if ([checkedCells objectForKey:indexNumber] != nil) {
[checkedCells removeObjectForKey:indexNumber];
cell.accessoryType = UITableViewCellAccessoryNone;
}
else
{
[checkedCells setObject:fbidNum forKey:indexNumber];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
NSLog(#"Cell Pressed: %#",indexNumber);
NSLog(#"FBID: %lld",fbid);
NSLog(#"Array: %#",checkedCells);
}
It looks like you're only saving the checked cells by row, not by section and row. At minimum, don't you need to be testing the section as well as the row in this block of code?
if ([checkedCells objectForKey:[NSNumber numberWithInt:indexPath.row]] != nil) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
It's late, and I don't have my Mac handy to try this code, so maybe I'm missing something obvious. I'm not sure what you're talking about only returning zero ... is that indexPath.row?
EDIT:
To account for the section in your data array, I'd suggest storing the data as a dictionary of arrays, one dictionary entry keyed by each letter, with the inner array holding all of the entries starting with that letter. It's a little more complicated to retrieve the data, but it correctly accounts for the section.
I supposed you could create some kind of an offset to account for the number of entries in each section and then use that to index into a flat array, but that would be a lot harder to maintain, in my view. I think the dictionary of arrays is the way to go.

Read plist data into a NSArray but get null

I got same warning here “local declaration hides instance variable” warning
but I got more problems...
Here is my code
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.someaddress.php"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
// create the connection with the request
// and start loading the data
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
NSLog(#"\n\nCONNECTION: %#", theConnection);
NSData *returnData = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:nil error:nil];
NSString *listFile = [[NSString alloc] initWithData:returnData encoding:NSASCIIStringEncoding];
NSMutableArray *plist = [[NSMutableArray alloc] init];
plist = [listFile propertyList];
NSLog( #"\n 1111 plist is \n%#", plist );
//I can get a plist format data here,But nothing in 2222
NSLog(#"Now you see me tableView Row Count");
NSLog(#"TOTAL PLIST ROW COUNT IS = %i", [plist count]);
// Return the number of rows in the section.
return [plist count];
}
and I got Warning here"Local declaration of 'plist' hides instance variable"
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"LightCell";
LightCell0 *cell =(LightCell0 *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[LightCell0 alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell…
NSLog(#"Now you see me Load Data %i", indexPath.row);
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
//I try to get list data here But RETURN NULL
NSLog( #"\n 2222 plist is \n %#", plist);
switch (indexPath.row) {
case 0:
if ([plist valueForKey:#"nodeStatus"] == 0){
cell.lightImageView.image = [UIImage imageNamed:#"lightOff.png"];
NSLog(#"value for key Node Status : %#" ,[self.plists Valuefokey:#"nodeStatus"]);
//also return NULL !!
}
else if([self valueForKey:#"nodeStatus"] == 1){
cell.lightImageView.image = [UIImage imageNamed:#"lightOn.png"];
}
break;
case 1:
cell.lightLocation.text =[plist valueForKey:#"nodeName"] ;
if ([plist valueForKey:#"nodeStatus"] == 0){
cell.lightImageView.image = [UIImage imageNamed:#"lightOff.png"];
}
else if([plist valueForKey:#"nodeStatus"] == 1){
cell.lightImageView.image = [UIImage imageNamed:#"lightOn.png"];
};
break;
default:
break;
}
return cell;
}
This is the tow items I create in a plist
{
category = Light;
nodeID = 1;
nodeName = "Living Room";
nodeStatus = 0;
nodeTrigger = 0;
nodeType = "light_sw";
},
{
category = Light;
nodeID = 2;
nodeName = Kitchen;
nodeStatus = 0;
nodeTrigger = 0;
nodeType = "light_sw";
}
So that's my question ,Why can't I pass "plist" from
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
...
}
to
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
...
}
and I use NSMutableArray *plist = [[NSMutableArray alloc] init];
But still appear "Local declaration of 'plist' hides instance variable"
???
hope someone can figure out this problem
Best Regards !
and I got Warning here"Local declaration of 'plist' hides instance variable"
Well, then, you should fix that.
The warning is telling you that you've declared two variables named plist: One local to this instance method, and the other an instance variable. The local variable, having a narrower scope, hides the instance variable, so that when you refer to plist in the method, you are referring to the local variable. This means that you cannot access anything stored in the instance variable by another method, nor store anything in it for another method to retrieve.
The solution is either to kill off or to rename the local variable. If the latter is what you want, use Xcode's “Edit All in Scope” feature.
Also:
NSMutableArray *plist = [[NSMutableArray alloc] init];
plist = [listFile propertyList];
Creating the array on the first of those lines is redundant, because you immediately replace your pointer to that array with the pointer to another array, returned by propertyList. Thus, you never use and you leak the first array. You should at least cut out the creation of the first array, and you should probably cut out the entire first line (thereby cutting out both the first array and the local variable).
Here is the code I fix the warning ,the program can build without any warning
it also can display the result after reading the plist in tableview
1.Load the plist:
- (void)viewDidLoad {
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www. someaddress.php"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
NSData *returnData = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:nil error:nil];
NSString *listFile = [[NSString alloc] initWithData:returnData encoding:NSASCIIStringEncoding];
plist = [listFile propertyList];
}
2.return the number to rows
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [plist count];
}
3.read the plist data to show result in cells
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"LightCell0";
LightCell0 *cell =(LightCell0 *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[LightCell0 alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell…
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
int i;
for (i=0; i<[plist count]; i++) {
//Get nodeName
if(indexPath.row == i)
{
cell.lightLocation.text = [[[plist objectAtIndex:i] valueForKey: #"nodeName"]description];
//Get Light Status to show the image
if ([[[plist objectAtIndex:i] valueForKey: #"nodeStatus"] intValue] == 0){
cell.lightImageView.image = [UIImage imageNamed:#"lightOff.png"];
}
else if([[[plist objectAtIndex:i] valueForKey: #"nodeStatus"] intValue] == 1){
cell.lightImageView.image = [UIImage imageNamed:#"lightOn.png"];
cell.lightSwitch.on=YES;
}
}
}
return cell;
}
It can get the right data ,and display the correct result in the tableview cells
BUTTTTTTT
If you scroll up the tableview,it's ok,when you on the top it will scroll down Automatically
When you "scroll down" the tableview,program crash ???
WHY ??? did I write anything wrong ???
plist = [listFile propertyList];=====>self.plist = [listFile propertyList];
THAT IS CORRECT