Variable scope?

Discussion in 'iOS Programming' started by ataylor2009, Jun 16, 2009.

  1. ataylor2009 macrumors member

    Joined:
    Jan 27, 2009
    #1
    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.
     
  2. BlackWolf macrumors regular

    Joined:
    Apr 9, 2009
    #2
    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?
     
  3. ataylor2009 thread starter macrumors member

    Joined:
    Jan 27, 2009
    #3
    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.
     
  4. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #4
    Can we see the code(s) where you define and assign a value to rule?
     
  5. ataylor2009 thread starter macrumors member

    Joined:
    Jan 27, 2009
    #5
    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).
     
  6. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #6
    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.
     
  7. BlackWolf macrumors regular

    Joined:
    Apr 9, 2009
    #7
    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.
     
  8. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #8
    yeah, what BlackWolf said.
     
  9. ataylor2009 thread starter macrumors member

    Joined:
    Jan 27, 2009
    #9
    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?
     
  10. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #10
    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.
     
  11. PhoneyDeveloper macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #11
    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.
     

Share This Page