PDA

View Full Version : Accessing unknown getter




ArtOfWarfare
Nov 28, 2009, 01:47 AM
Properties continue to confuse me to no end...

I have a view controller which contains the properties username and password (both NSStrings.)

@interface UserTableController : UITableViewController <ComposeViewControllerDelegate>
{
NSArray *users;
NSOperationQueue *infoQueue;
NSMutableArray *userInfoArray;
NSMutableArray *spinnerArray;
NSString *username;
NSString *password;
}

- (void) loadInfo:(NSString *)i;
- (void) compose;

@property (readwrite, assign) NSString *username;
@property (readwrite, assign) NSString *password;

@end

These are both synthesized in the main...

@synthesize username;
@synthesize password;

and then set in the initWithStyle

self.username = @"ArtOfWarfare";
self.password = @"***";

Later on, a module view controller is added to the initial view controller.

ComposeViewController *composeViewController = [[ComposeViewController alloc] init];
composeViewController.delegate = self;
[self presentModalViewController:composeViewController animated: YES];
[composeViewController release];

I would like this modual view controller to display the username and password, but it wasn't working. So I commented out the lines telling it to do that and instead have a simple NSLog to make sure it gets the username and password. Here's that code:

NSLog (@"I say the username is %@ and the password is %@.", self.delegate.username, self.delegate.password);

This gets me the error: accessing unknown 'password' getter method

I don't understand. The delegate of composeViewController is userTableController, shouldn't self.delegate.password just grab the password then? I'm either using delegates or properties (or both) incorrectly... I still don't understand either of them particularly well and I tend to just copy and paste example code for them without understanding why.

*** The actual code has the actual password in it... I'm not copying it down for obvious security reasons.



robbieduncan
Nov 28, 2009, 02:52 AM
Your design is not really the correct way to do this: you should not be holding your model in your controller layer.

firewood
Nov 28, 2009, 12:49 PM
Your design is not really the correct way to do this: you should not be holding your model in your controller layer.

Religious nonsense. This has nothing to do with the OP's problem. You can hold state information anywhere, M, V, C, or global, if you don't care about reuse (which wasn't part of the OP's problem).

To debug, try switching from dot to bracket notation for your messaging, and breaking the access into multiple statements using temporary variables you can watch in the debugger.

North Bronson
Nov 28, 2009, 02:38 PM
Think of a protocol as an agreement. My delegate promises to hold up that agreement, but anything else is out the window.

There's no real reason that your ComposeViewController should "know" that your UserTableController has the "username" and "password" properties without explicitly making those part of the protocol. In fact, to code your ComposeViewController with the assumption that your delegate will always be a UserTableController is starting to run counter of one of the principles of delegation; the code becomes reusable because different objects can assume the delegation role -- "locking in" the delegate to be a UserTableController loses this benefit.

I would add these following lines to your ComposeViewController protocol:

- (NSString *)passwordForComposeViewController:(ComposeViewController *)controller;
- (NSString *)usernameForComposeViewController:(ComposeViewController *)controller;

Then, in your UserTableController (along with the other methods of the ComposeViewController protocol):

- (NSString *)passwordForComposeViewController:(ComposeViewController *)controller
{
NSString *string = [self password];

return string;
}

- (NSString *)usernameForComposeViewController:(ComposeViewController *)controller
{
NSString *string = [self username];

return string;
}

Then, in your ComposeViewController, you should be able to:

NSString *username = [[self delegate] usernameForComposeViewController: self];

NSString *password = [[self delegate] passwordForComposeViewController: self];

NSLog(@"Username: %@, username);

NSLog(@"Password: %@, password);

This might seem like more work, but I think this runs more in line with the spirit of delegation. Also, take a good look at the delegation section in "Cocoa Design Patterns" in your documentation.