views:

36

answers:

1

I want to store the FTP Password in a Keychain rather than in the NSUserDefaults. So I used a wrapper called EMKeyChain to store the problem. The problem being is that it won't load the password when the Preference Window is loaded:

Note: FTPPassword is a IBOutlet for NSTextField in PreferenceController.h

-(void)windowDidLoad
{
//Check Login Keychain
    [self loadlogin];
//Set FTP Password Delegate to PreferenceController
    [FTPPassword setDelegate:self];
//Load Password
EMGenericKeychainItem *keychainItem = [EMGenericKeychainItem genericKeychainItemForService:@"MelScrobbleX" withUsername: @"ftp"];
if (keychainItem.password != nil) {
    [FTPPassword setValue:keychainItem.password];
}

Resulting in this big nasty error:

2010-09-05 19:31:51.360 MelScrobbleX[83291:a0f] -[NSSecureTextField setValue:]: unrecognized selector sent to instance 0x10c4be0
2010-09-05 19:31:51.363 MelScrobbleX[83291:a0f] HIToolbox: ignoring exception '-[NSSecureTextField setValue:]: unrecognized selector sent to instance 0x10c4be0' that raised inside Carbon event dispatch
(
    0   CoreFoundation                      0x977d6bba __raiseError + 410
    1   libobjc.A.dylib                     0x9022f509 objc_exception_throw + 56
    2   CoreFoundation                      0x978238db -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
    3   CoreFoundation                      0x9777d7e6 ___forwarding___ + 950
    4   CoreFoundation                      0x9777d3b2 _CF_forwarding_prep_0 + 50
    5   MelScrobbleX                        0x000193f2 -[PreferenceController windowDidLoad] + 157
    6   AppKit                              0x96d7941f -[NSWindowController _windowDidLoad] + 525
    7   AppKit                              0x96d072b0 -[NSWindowController window] + 123
    8   AppKit                              0x96f6c0f8 -[NSWindowController showWindow:] + 36
    9   AppKit                              0x96d61f1e -[NSApplication sendAction:to:from:] + 112
    10  AppKit                              0x96d61dd1 -[NSMenuItem _corePerformAction] + 435
    11  AppKit                              0x96d61ac2 -[NSCarbonMenuImpl performActionWithHighlightingForItemAtIndex:] + 174
    12  AppKit                              0x96d619ae -[NSMenu performActionForItemAtIndex:] + 65
    13  AppKit                              0x96d61961 -[NSMenu _internalPerformActionForItemAtIndex:] + 50
    14  AppKit                              0x96d618c7 -[NSMenuItem _internalPerformActionThroughMenuIfPossible] + 97
    15  AppKit                              0x96d6180b -[NSCarbonMenuImpl _carbonCommandProcessEvent:handlerCallRef:] + 336
    16  AppKit                              0x96d55f49 NSSLMMenuEventHandler + 404
    17  HIToolbox                           0x9370df2f _ZL23DispatchEventToHandlersP14EventTargetRecP14OpaqueEventRefP14HandlerCallRec + 1567
    18  HIToolbox                           0x9370d1f6 _ZL30SendEventToEventTargetInternalP14OpaqueEventRefP20OpaqueEventTargetRefP14HandlerCallRec + 411
    19  HIToolbox                           0x9372f9bb SendEventToEventTarget + 52
    20  HIToolbox                           0x9375bfa7 _ZL18SendHICommandEventmPK9HICommandmmhPKvP20OpaqueEventTargetRefS5_PP14OpaqueEventRef + 448
    21  HIToolbox                           0x93780d1c SendMenuCommandWithContextAndModifiers + 66
    22  HIToolbox                           0x93780cd1 SendMenuItemSelectedEvent + 121
    23  HIToolbox                           0x93780bda _ZL19FinishMenuSelectionP13SelectionDataP10MenuResultS2_ + 152
    24  HIToolbox                           0x93902342 _ZL19PopUpMenuSelectCoreP8MenuData5PointdS1_tjPK4RecttmS4_S4_PK10__CFStringPP13OpaqueMenuRefPt + 1851
    25  HIToolbox                           0x93902699 _HandlePopUpMenuSelection7 + 678
    26  AppKit                              0x96febe97 _NSSLMPopUpCarbonMenu3 + 3938
    27  AppKit                              0x97275bdb +[NSStatusBarButtonCell popupStatusBarMenu:inRect:ofView:withEvent:] + 962
    28  AppKit                              0x97275241 -[NSStatusBarButtonCell trackMouse:inRect:ofView:untilMouseUp:] + 151
    29  AppKit                              0x96e3ae93 -[NSControl mouseDown:] + 812
    30  AppKit                              0x96e38e9c -[NSWindow sendEvent:] + 5549
    31  AppKit                              0x972761f8 -[NSStatusBarWindow sendEvent:] + 82
    32  AppKit                              0x96d51aff -[NSApplication sendEvent:] + 6431
    33  AppKit                              0x96ce55bb -[NSApplication run] + 917
    34  AppKit                              0x96cdd5ed NSApplicationMain + 574
    35  MelScrobbleX                        0x00002eda start + 54
)

The program creates a new keychain item every time the password changes even though the keychain item exists already. (This selector is for FTPPassword)

- (void)controlTextDidEndEditing:(NSNotification *)aNotification {
    EMGenericKeychainItem *keychainItem = [EMGenericKeychainItem genericKeychainItemForService:@"MelScrobbleX" withUsername: @"ftp"];
    if (keychainItem.password == nil) {
        //Create Keychain
        NSLog(@"Creating Keychain");
        [EMGenericKeychainItem addGenericKeychainItemForService:@"MelScrobbleX" withUsername:@"ftp" password:[FTPPassword stringValue]];
    }
    else if (keychainItem.password != [FTPPassword stringValue]){
        //Save Password
        NSLog(@"Saving Password");
        keychainItem.password = [FTPPassword stringValue];
    }
    else if ([[FTPPassword stringValue] length] == 0){
        //Blank Password. Remove Keychain Item
        NSLog(@"Deleting Password");
        [keychainItem removeFromKeychain];
    }
}

Notes: The required frameworks are already linked (Security.framework and Carbon.framework) and this error happens with GC on and off. Also, I'm using the Mac OS X 10.5 SDK.

+2  A: 

Your error says

-[NSSecureTextField setValue:]: unrecognized selector sent to instance 0x10c4be0

You should look up the reference, see NSSecureTextField. By traversing the class hierarchy, you eventually find there's no such method as setValue:.

I guess you wanted to do

[FTPPassword setStringValue:keychainItem.password];

instead of

[FTPPassword setValue:keychainItem.password];

I would've thought that the compiler should have warned against using setValue: because there's no such method in NSControl, but I found this informal protocol defining setValue: as a category method of NSObject. Alas...

Yuji
That was a silly mistake... but oddly enough, the compiler did not show an error when I used the setValue method.
chikorita157
I explained in the answer why the compiler didn't complain: Apple added a category method to `NSObject`, without implementing it, to define an informal protocol. Google "informal protocol" to learn more about it.
Yuji