Recursos de Área de Trabalho macOS Objective-C - Exemplos

Exemplos de recursos de área de trabalho macOS Objective-C incluindo caixas de diálogo de arquivos, caixas de mensagem e bandeja do sistema

💻 Caixas de Mensagem objectivec

🟢 simple ⭐⭐

Exibir caixas de diálogo de alerta e confirmação usando NSAlert

⏱️ 20 min 🏷️ objectivec, macos, desktop, gui
Prerequisites: Objective-C basics, AppKit framework
// macOS Objective-C Message Boxes Examples
// Using AppKit framework

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>

// MARK: - 1. Basic Alert Dialogs

@interface MessageBoxHelper : NSObject

+ (void)showAlert:(NSString *)title
          message:(NSString *)message;

+ (void)showInformationalAlert:(NSString *)title
                        message:(NSString *)message;

+ (void)showWarningAlert:(NSString *)title
                  message:(NSString *)message;

+ (void)showErrorAlert:(NSString *)title
               message:(NSString *)message;

@end

@implementation MessageBoxHelper

+ (void)showAlert:(NSString *)title
          message:(NSString *)message {

    NSAlert *alert = [[NSAlert alloc] init];
    alert.messageText = title;
    alert.informativeText = message;
    alert.alertStyle = NSAlertStyleInformational;

    [alert runModal];
    NSLog(@"Alert shown: %@", title);
}

+ (void)showInformationalAlert:(NSString *)title
                        message:(NSString *)message {

    NSAlert *alert = [[NSAlert alloc] init];
    alert.messageText = title;
    alert.informativeText = message;
    alert.alertStyle = NSAlertStyleInformational;
    alert.icon = [NSImage imageNamed:NSImageNameInfo];

    [alert runModal];
    NSLog(@"Informational alert shown: %@", title);
}

+ (void)showWarningAlert:(NSString *)title
                  message:(NSString *)message {

    NSAlert *alert = [[NSAlert alloc] init];
    alert.messageText = title;
    alert.informativeText = message;
    alert.alertStyle = NSAlertStyleWarning;
    alert.icon = [NSImage imageNamed:NSImageNameCaution];

    [alert runModal];
    NSLog(@"Warning alert shown: %@", title);
}

+ (void)showErrorAlert:(NSString *)title
               message:(NSString *)message {

    NSAlert *alert = [[NSAlert alloc] init];
    alert.messageText = title;
    alert.informativeText = message;
    alert.alertStyle = NSAlertStyleCritical;
    alert.icon = [NSImage imageNamed:NSImageNameStopProgressTemplate];

    [alert runModal];
    NSLog(@"Error alert shown: %@", title);
}

@end

// MARK: - 2. Confirmation Dialogs

@interface ConfirmationDialogHelper : NSObject

+ (BOOL)showConfirmation:(NSString *)title
                  message:(NSString *)message;

+ (NSModalResponse)showYesNoDialog:(NSString *)title
                           message:(NSString *)message;

+ (BOOL)showYesNoCancelDialog:(NSString *)title
                       message:(NSString *)message;

@end

@implementation ConfirmationDialogHelper

+ (BOOL)showConfirmation:(NSString *)title
                  message:(NSString *)message {

    NSAlert *alert = [[NSAlert alloc] init];
    alert.messageText = title;
    alert.informativeText = message;
    alert.alertStyle = NSAlertStyleInformational;

    [alert addButtonWithTitle:@"OK"];
    [alert addButtonWithTitle:@"Cancel"];

    NSModalResponse response = [alert runModal];
    BOOL confirmed = (response == NSAlertFirstButtonReturn);

    NSLog(@"Confirmation dialog result: %@", confirmed ? @"YES" : @"NO");
    return confirmed;
}

+ (NSModalResponse)showYesNoDialog:(NSString *)title
                           message:(NSString *)message {

    NSAlert *alert = [[NSAlert alloc] init];
    alert.messageText = title;
    alert.informativeText = message;
    alert.alertStyle = NSAlertStyleWarning;

    [alert addButtonWithTitle:@"Yes"];
    [alert addButtonWithTitle:@"No"];

    NSModalResponse response = [alert runModal];

    if (response == NSAlertFirstButtonReturn) {
        NSLog(@"Yes/No dialog result: Yes");
    } else {
        NSLog(@"Yes/No dialog result: No");
    }

    return response;
}

+ (BOOL)showYesNoCancelDialog:(NSString *)title
                       message:(NSString *)message {

    NSAlert *alert = [[NSAlert alloc] init];
    alert.messageText = title;
    alert.informativeText = message;
    alert.alertStyle = NSAlertStyleInformational;

    [alert addButtonWithTitle:@"Yes"];
    [alert addButtonWithTitle:@"No"];
    [alert addButtonWithTitle:@"Cancel"];

    NSModalResponse response = [alert runModal];

    if (response == NSAlertFirstButtonReturn) {
        NSLog(@"Yes/No/Cancel dialog result: Yes");
        return YES;
    } else if (response == NSAlertSecondButtonReturn) {
        NSLog(@"Yes/No/Cancel dialog result: No");
        return NO;
    } else {
        NSLog(@"Yes/No/Cancel dialog result: Cancel");
        return NO; // Cancel returns NO
    }
}

@end

// MARK: - 3. Custom Button Dialogs

@interface CustomDialogHelper : NSObject

+ (NSInteger)showCustomButtonDialog:(NSString *)title
                            message:(NSString *)message
                           buttons:(NSArray<NSString *> *)buttons;

+ (NSString *)showCustomButtonDialogWithReturn:(NSString *)title
                                      message:(NSString *)message
                                     buttons:(NSArray<NSString *> *)buttons;

@end

@implementation CustomDialogHelper

+ (NSInteger)showCustomButtonDialog:(NSString *)title
                            message:(NSString *)message
                           buttons:(NSArray<NSString *> *)buttons {

    NSAlert *alert = [[NSAlert alloc] init];
    alert.messageText = title;
    alert.informativeText = message;
    alert.alertStyle = NSAlertStyleInformational;

    // Add custom buttons
    for (NSString *buttonTitle in buttons) {
        [alert addButtonWithTitle:buttonTitle];
    }

    NSModalResponse response = [alert runModal];
    NSInteger buttonIndex = response - NSAlertFirstButtonReturn;

    NSLog(@"Custom button dialog: Selected button index: %ld", (long)buttonIndex);
    return buttonIndex;
}

+ (NSString *)showCustomButtonDialogWithReturn:(NSString *)title
                                      message:(NSString *)message
                                     buttons:(NSArray<NSString *> *)buttons {

    NSInteger index = [self showCustomButtonDialog:title
                                           message:message
                                          buttons:buttons];

    if (index >= 0 && index < buttons.count) {
        NSString *selectedButton = buttons[index];
        NSLog(@"Selected button: %@", selectedButton);
        return selectedButton;
    }

    return nil;
}

@end

// MARK: - 4. Input Dialogs

@interface InputDialogHelper : NSObject

+ (NSString *)showTextInputDialog:(NSString *)title
                         message:(NSString *)message
                  defaultValue:(NSString *)defaultValue;

+ (NSString *)showPasswordDialog:(NSString *)title
                        message:(NSString *)message;

@end

@implementation InputDialogHelper

+ (NSString *)showTextInputDialog:(NSString *)title
                         message:(NSString *)message
                  defaultValue:(NSString *)defaultValue {

    NSAlert *alert = [[NSAlert alloc] init];
    alert.messageText = title;
    alert.informativeText = message;
    alert.alertStyle = NSAlertStyleInformational;

    // Create text field
    NSTextField *input = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 300, 24)];
    input.stringValue = defaultValue ?: @"";

    [alert setAccessoryView:input];

    [alert addButtonWithTitle:@"OK"];
    [alert addButtonWithTitle:@"Cancel"];

    [alert.window setInitialFirstResponder:input];

    NSModalResponse response = [alert runModal];

    if (response == NSAlertFirstButtonReturn) {
        NSString *text = input.stringValue;
        NSLog(@"Text input: %@", text);
        return text;
    }

    NSLog(@"Text input cancelled");
    return nil;
}

+ (NSString *)showPasswordDialog:(NSString *)title
                        message:(NSString *)message {

    NSAlert *alert = [[NSAlert alloc] init];
    alert.messageText = title;
    alert.informativeText = message;
    alert.alertStyle = NSAlertStyleInformational;

    // Create secure text field
    NSSecureTextField *passwordInput = [[NSSecureTextField alloc] initWithFrame:NSMakeRect(0, 0, 300, 24)];

    [alert setAccessoryView:passwordInput];

    [alert addButtonWithTitle:@"OK"];
    [alert addButtonWithTitle:@"Cancel"];

    [alert.window setInitialFirstResponder:passwordInput];

    NSModalResponse response = [alert runModal];

    if (response == NSAlertFirstButtonReturn) {
        NSString *password = passwordInput.stringValue;
        NSLog(@"Password entered (length: %lu)", (unsigned long)password.length);
        return password;
    }

    NSLog(@"Password input cancelled");
    return nil;
}

@end

// MARK: - 5. Detailed Dialogs with Suppression

@interface DetailedDialogHelper : NSObject

+ (void)showDetailedAlert:(NSString *)title
                  message:(NSString *)message
               detailText:(NSString *)detailText;

+ (BOOL)showSuppressibleAlert:(NSString *)title
                      message:(NSString *)message
                suppressionKey:(NSString *)key;

@end

@implementation DetailedDialogHelper

+ (void)showDetailedAlert:(NSString *)title
                  message:(NSString *)message
               detailText:(NSString *)detailText {

    NSAlert *alert = [[NSAlert alloc] init];
    alert.messageText = title;
    alert.informativeText = message;

    if (detailText) {
        // Add accessory view with detail text
        NSScrollView *scrollView = [[NSScrollView alloc] initWithFrame:NSMakeRect(0, 0, 400, 150)];
        scrollView.hasVerticalScroller = YES;
        scrollView.hasHorizontalScroller = NO;
        scrollView.borderType = NSBezelBorder;

        NSTextView *textView = [[NSTextView alloc] initWithFrame:scrollView.bounds];
        textView.string = detailText;
        textView.editable = NO;
        textView.font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];

        scrollView.documentView = textView;
        [alert setAccessoryView:scrollView];
    }

    [alert addButtonWithTitle:@"OK"];
    [alert runModal];

    NSLog(@"Detailed alert shown: %@", title);
}

+ (BOOL)showSuppressibleAlert:(NSString *)title
                      message:(NSString *)message
                suppressionKey:(NSString *)key {

    // Check if alert was previously suppressed
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    BOOL suppressed = [defaults boolForKey:key];

    if (suppressed) {
        NSLog(@"Alert was previously suppressed");
        return NO;
    }

    NSAlert *alert = [[NSAlert alloc] init];
    alert.messageText = title;
    alert.informativeText = message;
    alert.alertStyle = NSAlertStyleInformational;

    [alert setShowsSuppressionButton:YES];
    alert.suppressionButton.title = @"Don't show this again";

    [alert addButtonWithTitle:@"OK"];

    [alert runModal];

    // Save suppression state
    if (alert.suppressionButton.state == NSControlStateValueOn) {
        [defaults setBool:YES forKey:key];
        NSLog(@"Alert suppression enabled for key: %@", key);
    }

    return YES;
}

@end

// MARK: - 6. Sheet Dialogs (Attached to Windows)

@interface SheetDialogHelper : NSObject

+ (void)showSheetInWindow:(NSWindow *)window
                    title:(NSString *)title
                  message:(NSString *)message
               completion:(void (^)(NSModalResponse response))completion;

@end

@implementation SheetDialogHelper

+ (void)showSheetInWindow:(NSWindow *)window
                    title:(NSString *)title
                  message:(NSString *)message
               completion:(void (^)(NSModalResponse))completion {

    NSAlert *alert = [[NSAlert alloc] init];
    alert.messageText = title;
    alert.informativeText = message;
    alert.alertStyle = NSAlertStyleInformational;

    [alert beginSheetModalForWindow:window completionHandler:^(NSModalResponse response) {
        NSLog(@"Sheet dialog closed with response: %ld", (long)response);

        if (completion) {
            completion(response);
        }
    }];
}

@end

// MARK: - Main Demonstration

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"=== macOS Objective-C Message Boxes Examples ===\n");

        // Note: Message boxes require a running application with a window
        // These examples demonstrate the API usage patterns

        NSLog(@"--- Message Box API Examples ---\n");

        // 1. Basic alerts
        NSLog(@"1. Basic Alert");
        NSLog(@"   [MessageBoxHelper showAlert:@\"Title\" message:@\"Message\"]\n");

        NSLog(@"2. Informational Alert");
        NSLog(@"   [MessageBoxHelper showInformationalAlert:@\"Info\" message:@\"Details\"]\n");

        NSLog(@"3. Warning Alert");
        NSLog(@"   [MessageBoxHelper showWarningAlert:@\"Warning\" message:@\"Caution\"]\n");

        NSLog(@"4. Error Alert");
        NSLog(@"   [MessageBoxHelper showErrorAlert:@\"Error\" message:@\"Failure\"]\n");

        // 2. Confirmation dialogs
        NSLog(@"5. OK/Cancel Confirmation");
        NSLog(@"   BOOL confirmed = [ConfirmationDialogHelper showConfirmation:@\"Confirm\" message:@\"Are you sure?\"]\n");

        NSLog(@"6. Yes/No Dialog");
        NSLog(@"   NSModalResponse response = [ConfirmationDialogHelper showYesNoDialog:@\"Proceed\" message:@\"Continue?\"]\n");

        NSLog(@"7. Yes/No/Cancel Dialog");
        NSLog(@"   BOOL result = [ConfirmationDialogHelper showYesNoCancelDialog:@\"Save\" message:@\"Save changes?\"]\n");

        // 3. Custom buttons
        NSLog(@"8. Custom Button Dialog");
        NSLog(@"   NSArray *buttons = @[\"Retry\", \"Ignore\", \"Abort\"];");
        NSLog(@"   NSInteger index = [CustomDialogHelper showCustomButtonDialog:@\"Error\" message:@\"Action failed\" buttons:buttons]\n");

        // 4. Input dialogs
        NSLog(@"9. Text Input Dialog");
        NSLog(@"   NSString *text = [InputDialogHelper showTextInputDialog:@\"Input\" message:@\"Enter name:\" defaultValue:@\"John\"]\n");

        NSLog(@"10. Password Input Dialog");
        NSLog(@"   NSString *password = [InputDialogHelper showPasswordDialog:@\"Login\" message:@\"Enter password:\"]\n");

        // 5. Detailed dialogs
        NSLog(@"11. Detailed Alert");
        NSLog(@"   [DetailedDialogHelper showDetailedAlert:@\"Error\" message:@\"Operation failed\" detailText:@\"Stack trace...\"]\n");

        NSLog(@"12. Suppressible Alert");
        NSLog(@"   [DetailedDialogHelper showSuppressibleAlert:@\"Update Available\" message:@\"New version ready\" suppressionKey:@"updateAlert\"]\n");

        // 6. Sheet dialogs
        NSLog(@"13. Sheet Dialog");
        NSLog(@"   [SheetDialogHelper showSheetInWindow:window title:@\"Confirm\" message:@\"Delete?\"]\n");

        // Usage examples
        NSLog(@"--- Usage Examples ---\n");

        NSLog(@"// Confirm before destructive action:");
        NSLog(@"BOOL confirmed = [ConfirmationDialogHelper showConfirmation:@\"Delete File\"");
        NSLog(@"                                              message:@\"This cannot be undone.\"]");
        NSLog(@"if (confirmed) {");
        NSLog(@"    // Perform deletion");
        NSLog(@"}\n");

        NSLog(@"// Get user input:");
        NSLog(@"NSString *name = [InputDialogHelper showTextInputDialog:@\"User Name\"");
        NSLog(@"                                           message:@\"Enter your name:\"");
        NSLog(@"                                    defaultValue:@"\"A"");
        NSLog(@"if (name) {");
        NSLog(@"    NSLog(@\"Hello, %@\", name);");
        NSLog(@"}\n");

        NSLog(@"// Show detailed error:");
        NSLog(@"NSString *errorDetails = @\"Error code: 404\\nFile not found on server\\nPlease check connection\";");
        NSLog(@"[DetailedDialogHelper showDetailedAlert:@\"Download Failed\"");
        NSLog(@"                                message:@\"Could not download file\"");
        NSLog(@"                             detailText:errorDetails]\n");

        NSLog(@"=== Message Boxes Examples Completed ===");
        NSLog(@"\nNote: To see actual message boxes, run this code in a GUI application");
    }

    return 0;
}

💻 Caixas de Diálogo de Arquivos objectivec

🟡 intermediate ⭐⭐⭐

Abrir e salvar caixas de diálogo de arquivos usando NSOpenPanel e NSSavePanel

⏱️ 25 min 🏷️ objectivec, macos, desktop, gui
Prerequisites: Objective-C basics, AppKit framework
// macOS Objective-C File Dialogs Examples
// Using AppKit framework

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>

// MARK: - 1. Open File Dialog

@interface FileDialogHelper : NSObject

+ (NSURL *)showOpenFileDialog;
+ (NSURL *)showOpenFileDialogWithTypes:(NSArray<NSString *> *)fileTypes;
+ (NSArray<NSURL *> *)showOpenMultipleFilesDialog;
+ (NSURL *)showOpenDirectoryDialog;

@end

@implementation FileDialogHelper

+ (NSURL *)showOpenFileDialog {
    NSOpenPanel *panel = [NSOpenPanel openPanel];
    panel.title = @"Select a file";
    panel.prompt = @"Open";
    panel.canChooseFiles = YES;
    panel.canChooseDirectories = NO;
    panel.allowsMultipleSelection = NO;

    if ([panel runModal] == NSModalResponseOK) {
        NSURL *selectedURL = panel.URLs.firstObject;
        NSLog(@"Selected file: %@", selectedURL.path);
        return selectedURL;
    }

    NSLog(@"File selection cancelled");
    return nil;
}

+ (NSURL *)showOpenFileDialogWithTypes:(NSArray<NSString *> *)fileTypes {
    NSOpenPanel *panel = [NSOpenPanel openPanel];
    panel.title = @"Select a file";
    panel.prompt = @"Open";
    panel.canChooseFiles = YES;
    panel.canChooseDirectories = NO;
    panel.allowsMultipleSelection = NO;

    // Set allowed file types
    if (fileTypes) {
        panel.allowedFileTypes = fileTypes;
        NSLog(@"Allowed file types: %@", fileTypes);
    }

    if ([panel runModal] == NSModalResponseOK) {
        NSURL *selectedURL = panel.URLs.firstObject;
        NSLog(@"Selected file: %@", selectedURL.path);
        return selectedURL;
    }

    NSLog(@"File selection cancelled");
    return nil;
}

+ (NSArray<NSURL *> *)showOpenMultipleFilesDialog {
    NSOpenPanel *panel = [NSOpenPanel openPanel];
    panel.title = @"Select one or more files";
    panel.prompt = @"Open";
    panel.canChooseFiles = YES;
    panel.canChooseDirectories = NO;
    panel.allowsMultipleSelection = YES;

    if ([panel runModal] == NSModalResponseOK) {
        NSArray<NSURL *> *selectedURLs = panel.URLs;
        NSLog(@"Selected %lu files", (unsigned long)selectedURLs.count);
        for (NSURL *url in selectedURLs) {
            NSLog(@"  - %@", url.path);
        }
        return selectedURLs;
    }

    NSLog(@"Multiple file selection cancelled");
    return nil;
}

+ (NSURL *)showOpenDirectoryDialog {
    NSOpenPanel *panel = [NSOpenPanel openPanel];
    panel.title = @"Select a folder";
    panel.prompt = @"Open";
    panel.canChooseFiles = NO;
    panel.canChooseDirectories = YES;
    panel.allowsMultipleSelection = NO;

    if ([panel runModal] == NSModalResponseOK) {
        NSURL *selectedURL = panel.URLs.firstObject;
        NSLog(@"Selected directory: %@", selectedURL.path);
        return selectedURL;
    }

    NSLog(@"Directory selection cancelled");
    return nil;
}

@end

// MARK: - 2. Save File Dialog

@interface SaveFileDialogHelper : NSObject

+ (NSURL *)showSaveFileDialog;
+ (NSURL *)showSaveFileDialogWithName:(NSString *)defaultName;
+ (NSURL *)showSaveFileDialogWithName:(NSString *)defaultName
                            fileType:(NSString *)fileType;

@end

@implementation SaveFileDialogHelper

+ (NSURL *)showSaveFileDialog {
    NSSavePanel *panel = [NSSavePanel savePanel];
    panel.title = @"Save file";
    panel.prompt = @"Save";
    panel.canCreateDirectories = YES;
    panel.nameFieldStringValue = @"Untitled";

    if ([panel runModal] == NSModalResponseOK) {
        NSURL *saveURL = panel.URL;
        NSLog(@"Save to: %@", saveURL.path);
        return saveURL;
    }

    NSLog(@"Save file dialog cancelled");
    return nil;
}

+ (NSURL *)showSaveFileDialogWithName:(NSString *)defaultName {
    NSSavePanel *panel = [NSSavePanel savePanel];
    panel.title = @"Save file";
    panel.prompt = @"Save";
    panel.canCreateDirectories = YES;
    panel.nameFieldStringValue = defaultName ?: @"Untitled";

    if ([panel runModal] == NSModalResponseOK) {
        NSURL *saveURL = panel.URL;
        NSLog(@"Save to: %@", saveURL.path);
        return saveURL;
    }

    NSLog(@"Save file dialog cancelled");
    return nil;
}

+ (NSURL *)showSaveFileDialogWithName:(NSString *)defaultName
                            fileType:(NSString *)fileType {

    NSSavePanel *panel = [NSSavePanel savePanel];
    panel.title = @"Save file";
    panel.prompt = @"Save";
    panel.canCreateDirectories = YES;
    panel.nameFieldStringValue = defaultName ?: @"Untitled";

    // Set allowed file type
    if (fileType) {
        panel.allowedFileTypes = @[fileType];
        NSLog(@"File type: %@", fileType);
    }

    if ([panel runModal] == NSModalResponseOK) {
        NSURL *saveURL = panel.URL;
        NSLog(@"Save to: %@", saveURL.path);
        return saveURL;
    }

    NSLog(@"Save file dialog cancelled");
    return nil;
}

@end

// MARK: - 3. Advanced File Dialog Options

@interface AdvancedFileDialogHelper : NSObject

+ (NSURL *)showOpenDialogWithDirectory:(NSString *)directoryPath
                           allowedTypes:(NSArray<NSString *> *)types;

+ (NSURL *)showSaveDialogInDirectory:(NSString *)directoryPath
                         defaultName:(NSString *)defaultName
                            fileType:(NSString *)fileType;

+ (NSURL *)showSaveDialogWithAccessory:(NSString *)defaultName;

@end

@implementation AdvancedFileDialogHelper

+ (NSURL *)showOpenDialogWithDirectory:(NSString *)directoryPath
                           allowedTypes:(NSArray<NSString *> *)types {

    NSOpenPanel *panel = [NSOpenPanel openPanel];
    panel.title = @"Select a file";
    panel.prompt = @"Open";
    panel.canChooseFiles = YES;
    panel.canChooseDirectories = NO;
    panel.allowsMultipleSelection = NO;

    // Set starting directory
    if (directoryPath) {
        NSURL *directoryURL = [NSURL fileURLWithPath:directoryPath];
        panel.directoryURL = directoryURL;
        NSLog(@"Starting directory: %@", directoryPath);
    }

    // Set allowed file types
    if (types) {
        panel.allowedFileTypes = types;
    }

    if ([panel runModal] == NSModalResponseOK) {
        NSURL *selectedURL = panel.URLs.firstObject;
        NSLog(@"Selected file: %@", selectedURL.path);
        return selectedURL;
    }

    return nil;
}

+ (NSURL *)showSaveDialogInDirectory:(NSString *)directoryPath
                         defaultName:(NSString *)defaultName
                            fileType:(NSString *)fileType {

    NSSavePanel *panel = [NSSavePanel savePanel];
    panel.title = @"Save file";
    panel.prompt = @"Save";
    panel.canCreateDirectories = YES;
    panel.nameFieldStringValue = defaultName ?: @"Untitled";

    // Set starting directory
    if (directoryPath) {
        NSURL *directoryURL = [NSURL fileURLWithPath:directoryPath];
        panel.directoryURL = directoryURL;
    }

    // Set file type
    if (fileType) {
        panel.allowedFileTypes = @[fileType];
    }

    if ([panel runModal] == NSModalResponseOK) {
        NSURL *saveURL = panel.URL;
        NSLog(@"Save to: %@", saveURL.path);
        return saveURL;
    }

    return nil;
}

+ (NSURL *)showSaveDialogWithAccessory:(NSString *)defaultName {
    NSSavePanel *panel = [NSSavePanel savePanel];
    panel.title = @"Save file";
    panel.prompt = @"Save";
    panel.canCreateDirectories = YES;
    panel.nameFieldStringValue = defaultName ?: @"Untitled";

    // Add accessory view
    NSView *accessoryView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 300, 60)];

    NSButton *checkbox = [[NSButton alloc] initWithFrame:NSMakeRect(10, 35, 280, 20)];
    checkbox.buttonType = NSSwitchButton;
    checkbox.title = @"Add file extension";
    checkbox.state = NSControlStateValueOn;
    [accessoryView addSubview:checkbox];

    NSTextField *infoLabel = [[NSTextField alloc] initWithFrame:NSMakeRect(10, 10, 280, 20)];
    infoLabel.stringValue = @"Choose save location and name";
    infoLabel.editable = NO;
    infoLabel.drawsBackground = NO;
    infoLabel.bordered = NO;
    [accessoryView addSubview:infoLabel];

    panel.accessoryView = accessoryView;

    if ([panel runModal] == NSModalResponseOK) {
        NSURL *saveURL = panel.URL;
        NSLog(@"Extension checkbox state: %ld", (long)checkbox.state);
        NSLog(@"Save to: %@", saveURL.path);
        return saveURL;
    }

    return nil;
}

@end

// MARK: - 4. File Dialog Completion Handlers

@interface ModernFileDialogHelper : NSObject

+ (void)showOpenFileDialogWithCompletion:(void (^)(NSURL *selectedURL))completion;
+ (void)showSaveFileDialogWithCompletion:(void (^)(NSURL *saveURL))completion;

@end

@implementation ModernFileDialogHelper

+ (void)showOpenFileDialogWithCompletion:(void (^)(NSURL *selectedURL))completion {
    NSOpenPanel *panel = [NSOpenPanel openPanel];
    panel.title = @"Select a file";
    panel.prompt = @"Open";
    panel.canChooseFiles = YES;
    panel.canChooseDirectories = NO;
    panel.allowsMultipleSelection = NO;

    [panel beginSheetModalForWindow:nil completionHandler:^(NSModalResponse result) {
        if (result == NSModalResponseOK) {
            NSURL *selectedURL = panel.URLs.firstObject;
            NSLog(@"Selected file: %@", selectedURL.path);
            if (completion) {
                completion(selectedURL);
            }
        } else {
            NSLog(@"File selection cancelled");
            if (completion) {
                completion(nil);
            }
        }
    }];
}

+ (void)showSaveFileDialogWithCompletion:(void (^)(NSURL *saveURL))completion {
    NSSavePanel *panel = [NSSavePanel savePanel];
    panel.title = @"Save file";
    panel.prompt = @"Save";
    panel.canCreateDirectories = YES;
    panel.nameFieldStringValue = @"Untitled";

    [panel beginSheetModalForWindow:nil completionHandler:^(NSModalResponse result) {
        if (result == NSModalResponseOK) {
            NSURL *saveURL = panel.URL;
            NSLog(@"Save to: %@", saveURL.path);
            if (completion) {
                completion(saveURL);
            }
        } else {
            NSLog(@"Save dialog cancelled");
            if (completion) {
                completion(nil);
            }
        }
    }];
}

@end

// MARK: - 5. Common File Type Filters

@interface FileTypeFilter : NSObject

+ (NSArray<NSString *> *)imageTypes;
+ (NSArray<NSString *> *)textTypes;
+ (NSArray<NSString *> *)documentTypes;
+ (NSArray<NSString *> *)audioTypes;
+ (NSArray<NSString *> *)videoTypes;

@end

@implementation FileTypeFilter

+ (NSArray<NSString *> *)imageTypes {
    return @[@"png", @"jpg", @"jpeg", @"gif", @"bmp", @"tiff", @"webp", @"ico"];
}

+ (NSArray<NSString *> *)textTypes {
    return @[@"txt", @"md", @"rtf", @"csv", @"json", @"xml", @"html", @"css", @"js"];
}

+ (NSArray<NSString *> *)documentTypes {
    return @[@"pdf", @"doc", @"docx", @"xls", @"xlsx", @"ppt", @"pptx", @"pages", @"numbers", @"key"];
}

+ (NSArray<NSString *> *)audioTypes {
    return @[@"mp3", @"wav",aac", @"m4a", @"flac", @"ogg", @"wma"];
}

+ (NSArray<NSString *> *)videoTypes {
    return @[@"mp4", @"mov", @"avi", @"mkv", @"m4v", @"flv", @"wmv"];
}

@end

// MARK: - Main Demonstration

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"=== macOS Objective-C File Dialogs Examples ===\n");

        // Note: File dialogs require a running application with a window
        // These examples demonstrate the API usage patterns

        NSLog(@"--- File Dialog API Examples ---\n");

        // 1. Open file dialog
        NSLog(@"1. Open File Dialog");
        NSLog(@"   - [FileDialogHelper showOpenFileDialog]");
        NSLog(@"   Usage: Selects a single file\n");

        // 2. Open file with type filter
        NSLog(@"2. Open File with Type Filter");
        NSLog(@"   - [FileDialogHelper showOpenFileDialogWithTypes:[FileTypeFilter imageTypes]]");
        NSLog(@"   Usage: Selects only image files\n");

        // 3. Open multiple files
        NSLog(@"3. Open Multiple Files");
        NSLog(@"   - [FileDialogHelper showOpenMultipleFilesDialog]");
        NSLog(@"   Usage: Selects multiple files\n");

        // 4. Open directory
        NSLog(@"4. Open Directory");
        NSLog(@"   - [FileDialogHelper showOpenDirectoryDialog]");
        NSLog(@"   Usage: Selects a folder\n");

        // 5. Save file dialog
        NSLog(@"5. Save File Dialog");
        NSLog(@"   - [SaveFileDialogHelper showSaveFileDialog]");
        NSLog(@"   Usage: Prompts for save location\n");

        // 6. Save file with name
        NSLog(@"6. Save File with Name");
        NSLog(@"   - [SaveFileDialogHelper showSaveFileDialogWithName:@\"document.txt\"]");
        NSLog(@"   Usage: Sets default filename\n");

        // 7. Save with file type
        NSLog(@"7. Save with File Type");
        NSLog(@"   - [SaveFileDialogHelper showSaveFileDialogWithName:@\"image\" fileType:@\"png\"]");
        NSLog(@"   Usage: Restricts to specific file type\n");

        // 8. Advanced options
        NSLog(@"8. Advanced Options");
        NSLog(@"   - [AdvancedFileDialogHelper showOpenDialogWithDirectory:@\"/Users\" allowedTypes:types]");
        NSLog(@"   Usage: Sets starting directory and file types\n");

        // 9. Modern async handlers
        NSLog(@"9. Modern Completion Handlers");
        NSLog(@"   - [ModernFileDialogHelper showOpenFileDialogWithCompletion:^(NSURL *url) { ... }]");
        NSLog(@"   Usage: Asynchronous dialog with completion block\n");

        // 10. Common file type filters
        NSLog(@"10. Common File Type Filters");
        NSLog(@"   - [FileTypeFilter imageTypes]: %@\n", [FileTypeFilter imageTypes]);
        NSLog(@"   - [FileTypeFilter textTypes]: %@\n", [FileTypeFilter textTypes]);
        NSLog(@"   - [FileTypeFilter documentTypes]: %@\n", [FileTypeFilter documentTypes]);

        // Example code snippets
        NSLog(@"--- Example Code Snippets ---\n");

        NSLog(@"// Open and read a text file:");
        NSLog(@"NSURL *fileURL = [FileDialogHelper showOpenFileDialogWithTypes:[FileTypeFilter textTypes]];");
        NSLog(@"if (fileURL) {");
        NSLog(@"    NSString *content = [NSString stringWithContentsOfURL:fileURL");
        NSLog(@"                                                  encoding:NSUTF8StringEncoding");
        NSLog(@"                                                     error:nil];");
        NSLog(@"    NSLog(@\"Content: %@\", content);");
        NSLog(@"}\n");

        NSLog(@"// Save content to file:");
        NSLog(@"NSURL *saveURL = [SaveFileDialogHelper showSaveFileDialogWithName:@\"output\"]");
        NSLog(@"if (saveURL) {");
        NSLog(@"    NSString *content = @\"Hello, World!\";");
        NSLog(@"    [content writeToURL:saveURL");
        NSLog(@"               atomically:YES");
        NSLog(@"                 encoding:NSUTF8StringEncoding");
        NSLog(@"                    error:nil];");
        NSLog(@"}\n");

        NSLog(@"=== File Dialogs Examples Completed ===");
        NSLog(@"\nNote: To see actual dialogs, run this code in a GUI application");
    }

    return 0;
}

💻 Bandeja do Sistema / Barra de Status objectivec

🟡 intermediate ⭐⭐⭐

Criar e gerenciar itens da barra de status, menus e notificações

⏱️ 30 min 🏷️ objectivec, macos, desktop, status bar
Prerequisites: Objective-C basics, AppKit framework
// macOS Objective-C System Tray / Status Bar Examples
// Using AppKit framework

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>

// MARK: - 1. Basic Status Bar Item

@interface StatusBarItemController : NSObject

@property (nonatomic, strong) NSStatusItem *statusItem;

- (instancetype)initWithTitle:(NSString *)title;
- (void)showMenu;
- (void)hide;
- (void)setTooltip:(NSString *)tooltip;
- (void)setTitle:(NSString *)title;
- (void)setImage:(NSImage *)image;

@end

@implementation StatusBarItemController

- (instancetype)initWithTitle:(NSString *)title {
    self = [super init];

    if (self) {
        // Create status item in system status bar
        _statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
        _statusItem.button.title = title;

        NSLog(@"Status bar item created with title: %@", title);
    }

    return self;
}

- (void)showMenu:(NSMenu *)menu {
    self.statusItem.menu = menu;
    NSLog(@"Menu attached to status bar item");
}

- (void)hide {
    [[NSStatusBar systemStatusBar] removeStatusItem:self.statusItem];
    NSLog(@"Status bar item removed");
}

- (void)setTooltip:(NSString *)tooltip {
    self.statusItem.button.toolTip = tooltip;
    NSLog(@"Tooltip set: %@", tooltip);
}

- (void)setTitle:(NSString *)title {
    self.statusItem.button.title = title;
    NSLog(@"Title set: %@", title);
}

- (void)setImage:(NSImage *)image {
    self.statusItem.button.image = image;
    NSLog(@"Image set");
}

@end

// MARK: - 2. Status Bar with Menu

@interface MenuStatusBarController : StatusBarItemController

- (void)setupDefaultMenu;

@end

@implementation MenuStatusBarController

- (void)setupDefaultMenu {
    // Create menu
    NSMenu *menu = [[NSMenu alloc] init];

    // Add menu items
    [menu addItem:[self createMenuItem:@"About"
                              action:@selector(showAbout:)
                           keyEquivalent:@""]];

    [menu addItem:[NSMenuItem separatorItem]];

    [menu addItem:[self createMenuItem:@"Preferences"
                              action:@selector(showPreferences:)
                           keyEquivalent:@","]];

    [menu addItem:[self createMenuItem:@"Check for Updates"
                              action:@selector(checkForUpdates:)
                           keyEquivalent:@""]];

    [menu addItem:[NSMenuItem separatorItem]];

    [menu addItem:[self createMenuItem:@"Hide"
                              action:@selector(hide:)
                           keyEquivalent:@"h"]];

    [menu addItem:[self createMenuItem:@"Quit"
                              action:@selector(quit:)
                           keyEquivalent:@"q"]];

    [self showMenu:menu];
    NSLog(@"Default menu setup completed");
}

- (NSMenuItem *)createMenuItem:(NSString *)title
                       action:(SEL)action
                keyEquivalent:(NSString *)keyEquivalent {

    NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:title
                                                  action:action
                                           keyEquivalent:keyEquivalent];
    item.target = self;
    return item;
}

- (void)showAbout:(id)sender {
    NSLog(@"Menu action: Show About");
    [self showAlert:@"About"
            message:@"Status Bar Application\nVersion 1.0"];
}

- (void)showPreferences:(id)sender {
    NSLog(@"Menu action: Show Preferences");
    [self showAlert:@"Preferences"
            message:@"Preferences panel would open here"];
}

- (void)checkForUpdates:(id)sender {
    NSLog(@"Menu action: Check for Updates");
    [self showAlert:@"Updates"
            message:@"No updates available"];
}

- (void)hide:(id)sender {
    NSLog(@"Menu action: Hide");
    [NSApp hide:nil];
}

- (void)quit:(id)sender {
    NSLog(@"Menu action: Quit");
    [NSApp terminate:nil];
}

- (void)showAlert:(NSString *)title
          message:(NSString *)message {

    NSAlert *alert = [[NSAlert alloc] init];
    alert.messageText = title;
    alert.informativeText = message;
    [alert runModal];
}

@end

// MARK: - 3. Status Bar with Custom View

@interface CustomViewStatusBarController : StatusBarItemController

- (void)setupCustomView;

@end

@implementation CustomViewStatusBarController

- (void)setupCustomView {
    // Create custom view
    NSView *customView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 100, 20)];

    // Create progress indicator
    NSProgressIndicator *progress = [[NSProgressIndicator alloc]
        initWithFrame:NSMakeRect(0, 2, 20, 16)];
    progress.style = NSProgressIndicatorSpinningStyle;
    [customView addSubview:progress];
    [progress startAnimation:nil];

    // Create text label
    NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(25, 2, 75, 16)];
    label.stringValue = @"Active";
    label.editable = NO;
    label.drawsBackground = NO;
    label.bordered = NO;
    [customView addSubview:label];

    // Set custom view
    self.statusItem.button.view = customView;

    NSLog(@"Custom view setup completed");
}

@end

// MARK: - 4. Status Bar with Click Action

@interface ClickableStatusBarController : StatusBarItemController

- (void)setupClickAction;

@end

@implementation ClickableStatusBarController

- (void)setupClickAction {
    // Create action for click
    self.statusItem.button.action = @selector(statusBarButtonClicked:);
    self.statusItem.button.target = self;

    // Create menu for right-click
    NSMenu *menu = [[NSMenu alloc] init];
    [menu addItem:[self createMenuItem:@"Open"
                              action:@selector(openApp:)
                           keyEquivalent:@"o"]];
    [menu addItem:[self createMenuItem:@"Quit"
                              action:@selector(quit:)
                           keyEquivalent:@"q"]];
    [self showMenu:menu];

    NSLog(@"Click action setup completed");
}

- (NSMenuItem *)createMenuItem:(NSString *)title
                       action:(SEL)action
                keyEquivalent:(NSString *)keyEquivalent {

    NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:title
                                                  action:action
                                           keyEquivalent:keyEquivalent];
    item.target = self;
    return item;
}

- (void)statusBarButtonClicked:(id)sender {
    NSLog(@"Status bar button clicked");

    // Show alert or perform action
    NSAlert *alert = [[NSAlert alloc] init];
    alert.messageText = @"Status Bar Clicked";
    alert.informativeText = @"You clicked the status bar icon";
    [alert runModal];
}

- (void)openApp:(id)sender {
    NSLog(@"Menu action: Open");
}

- (void)quit:(id)sender {
    NSLog(@"Menu action: Quit");
    [NSApp terminate:nil];
}

@end

// MARK: - 5. Dynamic Menu Updates

@interface DynamicMenuStatusBarController : MenuStatusBarController

@property (nonatomic, strong) NSMenuItem *toggleItem;
@property (nonatomic, assign) BOOL isEnabled;

- (void)setupDynamicMenu;

@end

@implementation DynamicMenuStatusBarController

- (void)setupDynamicMenu {
    [super setupDefaultMenu];

    // Add dynamic items
    NSMenu *menu = self.statusItem.menu;

    [menu insertItem:[NSMenuItem separatorItem] atIndex:2];

    // Toggle item
    self.toggleItem = [[NSMenuItem alloc] initWithTitle:@"Enable Feature"
                                                action:@selector(toggleFeature:)
                                         keyEquivalent:@"f"];
    self.toggleItem.target = self;
    self.toggleItem.state = NSControlStateValueOff;
    [menu insertItem:self.toggleItem atIndex:3];

    // Status item
    NSMenuItem *statusItem = [[NSMenuItem alloc] initWithTitle:@"Status: Active"
                                                       action:nil
                                                keyEquivalent:@""];
    statusItem.enabled = NO;
    [menu insertItem:statusItem atIndex:4];

    NSLog(@"Dynamic menu setup completed");
}

- (void)toggleFeature:(id)sender {
    self.isEnabled = !self.isEnabled;

    if (self.isEnabled) {
        self.toggleItem.state = NSControlStateValueOn;
        self.toggleItem.title = @"Disable Feature";
        NSLog(@"Feature enabled");
    } else {
        self.toggleItem.state = NSControlStateValueOff;
        self.toggleItem.title = @"Enable Feature";
        NSLog(@"Feature disabled");
    }
}

@end

// MARK: - 6. Status Bar with Notification

@interface NotificationStatusBarController : StatusBarItemController

- (void)showNotification:(NSString *)title
              message:(NSString *)message;

- (void)showNotificationWithSound:(NSString *)title
                         message:(NSString *)message;

@end

@implementation NotificationStatusBarController

- (void)showNotification:(NSString *)title
              message:(NSString *)message {

    NSUserNotification *notification = [[NSUserNotification alloc] init];
    notification.title = title;
    notification.informativeText = message;
    notification.soundName = NSUserNotificationDefaultSoundName;

    [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];

    NSLog(@"Notification shown: %@", title);
}

- (void)showNotificationWithSound:(NSString *)title
                         message:(NSString *)message {

    NSUserNotification *notification = [[NSUserNotification alloc] init];
    notification.title = title;
    notification.informativeText = message;
    notification.soundName = NSUserNotificationDefaultSoundName;

    [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];

    // Also update status bar
    [self setTitle:@"🔔"];

    // Reset after delay
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)),
                   dispatch_get_main_queue(), ^{
        [self setTitle:@"App"];
    });

    NSLog(@"Notification with sound shown: %@", title);
}

@end

// MARK: - Main Demonstration

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"=== macOS Objective-C System Tray / Status Bar Examples ===\n");

        // Note: Status bar items require a running application
        // These examples demonstrate the API usage patterns

        NSLog(@"--- Status Bar API Examples ---\n");

        // 1. Basic status bar item
        NSLog(@"1. Basic Status Bar Item");
        NSLog(@"   StatusBarItemController *controller = [[StatusBarItemController alloc] initWithTitle:@\"App\"]");
        NSLog(@"   // Creates a status bar item with title\n");

        // 2. Status bar with menu
        NSLog(@"2. Status Bar with Menu");
        NSLog(@"   MenuStatusBarController *menuController = [[MenuStatusBarController alloc] initWithTitle:@\"App\"]");
        NSLog(@"   [menuController setupDefaultMenu];");
        NSLog(@"   // Creates menu with About, Preferences, Quit, etc.\n");

        // 3. Status bar with custom view
        NSLog(@"3. Status Bar with Custom View");
        NSLog(@"   CustomViewStatusBarController *customController = [[CustomViewStatusBarController alloc] initWithTitle:@"\"\"]");
        NSLog(@"   [customController setupCustomView];");
        NSLog(@"   // Adds custom view with progress indicator\n");

        // 4. Status bar with click action
        NSLog(@"4. Status Bar with Click Action");
        NSLog(@"   ClickableStatusBarController *clickController = [[ClickableStatusBarController alloc] initWithTitle:@\"App\"]");
        NSLog(@"   [clickController setupClickAction];");
        NSLog(@"   // Shows alert on left-click, menu on right-click\n");

        // 5. Dynamic menu updates
        NSLog(@"5. Dynamic Menu Updates");
        NSLog(@"   DynamicMenuStatusBarController *dynamicController = [[DynamicMenuStatusBarController alloc] initWithTitle:@\"App\"]");
        NSLog(@"   [dynamicController setupDynamicMenu];");
        NSLog(@"   // Menu items can change state dynamically\n");

        // 6. Status bar with notifications
        NSLog(@"6. Status Bar with Notifications");
        NSLog(@"   NotificationStatusBarController *notifController = [[NotificationStatusBarController alloc] initWithTitle:@\"App\"]");
        NSLog(@"   [notifController showNotification:@\"Update Available\" message:@\"Version 2.0 is ready\"]");
        NSLog(@"   // Shows system notification\n");

        // Usage examples
        NSLog(@"--- Usage Examples ---\n");

        NSLog(@"// Create a simple status bar app:");
        NSLog(@"StatusBarItemController *controller = [[StatusBarItemController alloc] initWithTitle:@\"MyApp\"]");
        NSLog(@"[controller setTooltip:@\"My Status Bar App\"]\n");

        NSLog(@"// Setup menu:");
        NSLog(@"NSMenu *menu = [[NSMenu alloc] init];");
        NSLog(@"[menu addItemWithTitle:@\"Open\" action:@selector(open:) keyEquivalent:@\"o\"]");
        NSLog(@"[menu addItem:[NSMenuItem separatorItem]];");
        NSLog(@"[menu addItemWithTitle:@\"Quit\" action:@selector(quit:) keyEquivalent:@\"q\"]");
        NSLog(@"[controller showMenu:menu]\n");

        NSLog(@"// Handle menu actions:");
        NSLog(@"- (void)open:(id)sender {");
        NSLog(@"    NSLog(@\"Open menu item clicked\");");
        NSLog(@"    // Open main window");
        NSLog(@"}\n");

        NSLog(@"- (void)quit:(id)sender {");
        NSLog(@"    [NSApp terminate:nil];");
        NSLog(@"}\n");

        NSLog(@"// Show notification:");
        NSLog(@"[controller showNotification:@\"Download Complete\"");
        NSLog(@"                         message:@\"Your file is ready\"]\n");

        NSLog(@"=== System Tray / Status Bar Examples Completed ===");
        NSLog(@"\nNote: To see actual status bar items, run this code in a GUI application");
    }

    return 0;
}