Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

ataylor2009

macrumors member
Original poster
Jan 27, 2009
78
0
I am apparently a little light on "variable scope" knowledge. I'm sure I've just got something out of place somewhere, but I can't quite pin it down. This is the only remaining error (currently) preventing me from building and testing my app.

Here's the method implementation where I'm getting the error:

Code:
-(BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier {
	NSString* tempName = (NSString*)ABRecordCopyCompositeName(person);
	ABMultiValueRef thisPhones = ABRecordCopyValue(person, kABPersonPhoneProperty);
	NSString* tempLabel = (NSString*)ABMultiValueCopyLabelAtIndex(thisPhones,0);
	NSString* tempNumber = (NSString*)ABMultiValueCopyValueAtIndex(thisPhones,0);
	[rule setName:tempName];
	[rule setNumber:tempNumber];
	[rule setLabel:tempLabel];
	return NO;}

The three "temp..." variables are declared in the RootViewController.h file (this method is from RootViewController.m). The "rule" variable is where I'm getting the following error: "rule undeclared: first use in this function."

"Rule" is actually a Core Data managed object that is created within the RootViewController; i.e., when a user clicks "Add", a new "rule" object is created and inserted into the managed object context, then the peoplePicker is called to allow the user to select a contact.

My question is, how do I actually get the selected contact's name and selected property back into my "rule" entity? I suspect I just have one or two things out of place, but I can't figure out what they are.

Thanks in advance for any advice you can offer.
 

BlackWolf

macrumors regular
Apr 9, 2009
244
0
you should post your rootviewcontrollers .h file.

but if a "Rule" get's created every time someone clicks add, shouldn't you have an array that manages all the rules created or something?
 

ataylor2009

macrumors member
Original poster
Jan 27, 2009
78
0
RootViewController.h:

Code:
#import <UIKit/UIKit.h>
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>

@interface RootViewController: UITableViewController <ABPeoplePickerNavigationControllerDelegate>
{
	NSMutableArray*			rulesArray;
	NSManagedObjectContext*	managedObjectContext;
	UIBarButtonItem*		addButton;
	NSString*				tempName;
	NSString*				tempNumber;
	NSString*				tempLabel;
}

-(IBAction)addRule:(id)sender;

@property (nonatomic, retain) NSMutableArray*			rulesArray;
@property (nonatomic, retain) NSManagedObjectContext*	managedObjectContext;
@property (nonatomic, retain) UIBarButtonItem*			addButton;
@property (nonatomic, retain) NSString*					tempName;
@property (nonatomic, retain) NSString*					tempNumber;
@property (nonatomic, retain) NSString*					tempLabel;

@end

There is an array (sort of) that holds the rules; since they're managed objects, they're actually handled by the Core Data framework (my understanding), although there is an array of "rule objects" that acts as a data source to the tableview where the rules are actually displayed. Hope that makes sense.

The basic control flow is: user presses "Add," RootViewController instantiates new Rule object and inserts into managed object context, RootViewController passes control to ABPeoplePickerNavigationController, user selects contact, user selects property within contact...this is where I lose control. How do I get the selected name/property label/value back from the the method? It only returns a BOOL, which I assume means I have to set the values in question before the method returns - which is what I've tried to do, but apparently in the wrong way.
 

ataylor2009

macrumors member
Original poster
Jan 27, 2009
78
0
Sure thing:

Code:
-(IBAction)addRule:(id)sender
{
	// Create and configure a new instance of the Rule entity
	Rule* rule = (Rule*)[NSEntityDescription insertNewObjectForEntityForName:@"Rule" inManagedObjectContext:managedObjectContext];
	
	// Present PeoplePicker
	ABPeoplePickerNavigationController* picker = [[ABPeoplePickerNavigationController alloc] init];
	picker.peoplePickerDelegate = self;
	[self presentModalViewController:picker animated:YES];
	[picker release];
	
	NSError* error;
	if (![managedObjectContext save:&error])
	{/* Handle errors */}
	[rulesArray addObject:rule];
	NSIndexPath* indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
	[self.tableView insertRowsAtIndexPath:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
	[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

That what you're looking for? I can also post the "Rule.h" and "Rule.m" files, but, honestly, since they're Core Data entities, there's not much to them (like 3 lines each).
 

dejo

Moderator emeritus
Sep 2, 2004
15,982
452
The Centennial State
Your rule's scope is limited to the addRule: method because you declare it as a local variable. Therefore, no other methods will be able to access it. If you want other methods to be able to use it, you should define it as an instance variable (or something along those lines) of RootViewController.
 

BlackWolf

macrumors regular
Apr 9, 2009
244
0
Your rule's scope is limited to the addRule: method because you declare it as a local variable. Therefore, no other methods will be able to access it. If you want other methods to be able to use it, you should define it as an instance variable (or something along those lines) of RootViewController.

or, since I guess that's what it's for, add the Rule to your rulesArray and then get it from there

Right now you're not defining rule in your .h file (class-wide scope), but rather in your method (method-wide scope). therefor rule isn't available outside of the method you defined it in.

edit: I just saw you already add your rule to your array. than, obviously, that's where you need to get it from before you can use it.
 

ataylor2009

macrumors member
Original poster
Jan 27, 2009
78
0
Okay - thanks for the tips. When I get in this evening, I'll spend some time re-jiggering things and see what I can come up with.

I appreciate you taking the time to give me a shove in the right direction.

Actually - I just thought of another question: Since I AM declaring tempName, tempNumber, and tempLabel in the *.h file (class-wide scope), what if I just move the three "[rule set...]" lines out of the peoplePicker:shouldContinueAfterSelectingPerson:property:identifier: method and back into the addRule: method? Wouldn't that work, since the three temp... variables are declared in the *.h file?
 

dejo

Moderator emeritus
Sep 2, 2004
15,982
452
The Centennial State
Actually - I just thought of another question: Since I AM declaring tempName, tempNumber, and tempLabel in the *.h file (class-wide scope), what if I just move the three "[rule set...]" lines out of the peoplePicker:shouldContinueAfterSelectingPerson:property:identifier: method and back into the addRule: method? Wouldn't that work, since the three temp... variables are declared in the *.h file?
Won't work because the values that you need to assign to them are not determinable until you are in shouldContinueAfterSelectingPerson, and not yet known when you are in addRule.
 

PhoneyDeveloper

macrumors 68040
Sep 2, 2008
3,114
93
In this code there appears to be the concept of the current rule. You have a rules array that contains all the rule objects. Arrays allow you to get values based on their index. You can get the third object, the tenth object etc. So if you have a table then you have the concept of the current selected row. Your current selected row will correspond to a rule in the rule array. Get your currentRule and you're all set.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.