17

In my application, I want to create a dialog box with one text field, and a button, through which I can prompt user and get back user entered value.

How do I do this in Cocoa, Objective-C ?

I didn't find any predefined method for that.

Kyle Browning
  • 5,374
  • 1
  • 19
  • 30
udr1990
  • 265
  • 1
  • 3
  • 11

4 Answers4

42

You can call an NSAlert and put the NSTextField as it's accessoryView like this"

- (NSString *)input: (NSString *)prompt defaultValue: (NSString *)defaultValue {
    NSAlert *alert = [NSAlert alertWithMessageText: prompt
                                     defaultButton:@"OK"
                                   alternateButton:@"Cancel"
                                       otherButton:nil
                         informativeTextWithFormat:@""];

    NSTextField *input = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 24)];
    [input setStringValue:defaultValue];
    [input autorelease];
    [alert setAccessoryView:input];
    NSInteger button = [alert runModal];
    if (button == NSAlertDefaultReturn) {
        [input validateEditing];
        return [input stringValue];
    } else if (button == NSAlertAlternateReturn) {
        return nil;
    } else {
        NSAssert1(NO, @"Invalid input dialog button %d", button);
        return nil;
    }
}
Aamir
  • 5,324
  • 2
  • 30
  • 47
0xSina
  • 20,973
  • 34
  • 136
  • 253
  • Don't forget to release the NSTextField if you are creating it by alloc-init. – Sebastian Hojas Apr 19 '12 at 10:50
  • @SebastianHojas do they still need to do that if their using ARC for memory management? – rd108 May 14 '13 at 00:48
  • @rd108 No release is needed/allowed when you are using ARC. – Sebastian Hojas May 30 '13 at 10:12
  • Yes, no releases are needed with ARC. But don't forget to use @autoreleasepool when appropriate. Without that, each allocation is maintained by to the main pool. Therefore, all instances will be released from memory only when the main pool will be drained. Swift or Objective-C. – Chrstpsln Sep 27 '17 at 10:34
  • 1
    This answer is using a deprecated API and is generally showing its age. ("[NSAlert alertWithMessageText ...] etc.). These days just make an NSAlert with [[NSAlert alloc] init] and fill in the properties as described in other answers here. – w0mbat Jun 17 '20 at 04:22
18

IN OS X 10.10:

    NSAlert *alert = [[NSAlert alloc] init];
    [alert setMessageText:@"Permission denied, sudo password?"];
    [alert addButtonWithTitle:@"Ok"];
    [alert addButtonWithTitle:@"Cancel"];

    NSTextField *input = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 24)];
    [input setStringValue:@""];

    [alert setAccessoryView:input];
    NSInteger button = [alert runModal];
    if (button == NSAlertFirstButtonReturn) {
        password = [input stringValue];
    } else if (button == NSAlertSecondButtonReturn) {

    }
Kyle Browning
  • 5,374
  • 1
  • 19
  • 30
8

An example in Swift as of Xcode 7.2.1 and OS X 10.11:

let a = NSAlert()
a.messageText = "Please enter a value"
a.addButtonWithTitle("Save")
a.addButtonWithTitle("Cancel")

let inputTextField = NSTextField(frame: NSRect(x: 0, y: 0, width: 300, height: 24))
inputTextField.placeholderString = "Enter string"
a.accessoryView = inputTextField

a.beginSheetModalForWindow(self.window!, completionHandler: { (modalResponse) -> Void in
    if modalResponse == NSAlertFirstButtonReturn {
        let enteredString = inputTextField.stringValue
        print("Entered string = \"\(enteredString)\"")
    }
})
Klaas
  • 22,394
  • 11
  • 96
  • 107
8

I believe what you are looking for is a sheet. Have a look at the Sheet Programming Topics documentation

I've just updated a Github Sample project on this. You can enter text in a field on the sheet and pass that back to the main window.

This example shows how to create a view in a nib and use a custom sheet controller class which uses a block as the callback, rather than having to create and pass in a selector.

Abizern
  • 146,289
  • 39
  • 203
  • 257