Mac开发基础26-NSOpenPanel和NSSavePanel

NSOpenPanelNSSavePanel 是 macOS 应用中的两个重要控件,分别用于文件和文件夹的选择(打开)以及文件的保存(保存)。

NSOpenPanel

NSOpenPanel 是用于展示系统的打开文件对话框的类,用户可以通过它来选择文件或文件夹。

基本使用

Objective-C

#import <Cocoa/Cocoa.h>

// 创建并配置 NSOpenPanel
NSOpenPanel *openPanel = [NSOpenPanel openPanel];

// 允许用户选择文件
[openPanel setCanChooseFiles:YES];

// 允许用户选择文件夹
[openPanel setCanChooseDirectories:YES];

// 允许多选
[openPanel setAllowsMultipleSelection:YES];

// 设置对话框标题
[openPanel setTitle:@"选择文件或文件夹"];

// 显示对话框,并异步处理用户选择
[openPanel beginWithCompletionHandler:^(NSModalResponse result) {
    if (result == NSModalResponseOK) {
        // 获取用户选择的 URL 列表
        NSArray<NSURL *> *urls = [openPanel URLs];
        for (NSURL *url in urls) {
            NSLog(@"选择的文件/文件夹: %@", url.path);
        }
    } else {
        NSLog(@"用户取消了选择");
    }
}];

Swift

import Cocoa

// 创建并配置 NSOpenPanel
let openPanel = NSOpenPanel()

// 允许用户选择文件
openPanel.canChooseFiles = true

// 允许用户选择文件夹
openPanel.canChooseDirectories = true

// 允许多选
openPanel.allowsMultipleSelection = true

// 设置对话框标题
openPanel.title = "选择文件或文件夹"

// 显示对话框,并异步处理用户选择
openPanel.begin { result in
    if result == .OK {
        // 获取用户选择的 URL 列表
        let urls = openPanel.urls
        for url in urls {
            print("选择的文件/文件夹: \(url.path)")
        }
    } else {
        print("用户取消了选择")
    }
}

配置文件类型过滤

Objective-C

// 只允许选择特定类型的文件(例如:只选择图片文件)
[openPanel setAllowedFileTypes:@[@"jpg", @"png", @"gif"]];

Swift

// 只允许选择特定类型的文件(例如:只选择图片文件)
openPanel.allowedFileTypes = ["jpg", "png", "gif"]

指定初始目录

Objective-C

// 设置初始目录
[openPanel setDirectoryURL:[NSURL fileURLWithPath:@"/Users/username/Documents"]];

Swift

// 设置初始目录
openPanel.directoryURL = URL(fileURLWithPath: "/Users/username/Documents")

处理用户取消操作

Objective-C

[openPanel beginWithCompletionHandler:^(NSModalResponse result) {
    if (result == NSModalResponseOK) {
        // 用户选择了文件或文件夹
    } else {
        // 用户取消了操作
        NSLog(@"用户取消了选择");
    }
}];

Swift

openPanel.begin { result in
    if result == .OK {
        // 用户选择了文件或文件夹
    } else {
        // 用户取消了操作
        print("用户取消了选择")
    }
}

NSSavePanel

NSSavePanel 是用于展示系统的保存文件对话框的类,用户可以通过它来选择保存文件的位置和名称。

基本使用

Objective-C

#import <Cocoa/Cocoa.h>

// 创建并配置 NSSavePanel
NSSavePanel *savePanel = [NSSavePanel savePanel];

// 设置对话框标题
[savePanel setTitle:@"保存文件"];

// 设置默认文件名
[savePanel setNameFieldStringValue:@"Untitled.txt"];

// 显示对话框,并异步处理用户选择
[savePanel beginWithCompletionHandler:^(NSModalResponse result) {
    if (result == NSModalResponseOK) {
        NSURL *saveURL = [savePanel URL];
        NSLog(@"保存路径: %@", saveURL.path);
        
        // 在这里可以进行文件保存操作,例如将数据写入到 saveURL 所指示的文件路径中
    } else {
        NSLog(@"用户取消了保存");
    }
}];

Swift

import Cocoa

// 创建并配置 NSSavePanel
let savePanel = NSSavePanel()

// 设置对话框标题
savePanel.title = "保存文件"

// 设置默认文件名
savePanel.nameFieldStringValue = "Untitled.txt"

// 显示对话框,并异步处理用户选择
savePanel.begin { result in
    if result == .OK {
        if let saveURL = savePanel.url {
            print("保存路径: \(saveURL.path)")
            
            // 在这里可以进行文件保存操作,例如将数据写入到 saveURL 所指示的文件路径中
        }
    } else {
        print("用户取消了保存")
    }
}

配置文件类型限制

Objective-C

// 只允许保存特定类型的文件(例如:只保存为文本文件)
[savePanel setAllowedFileTypes:@[@"txt"]];

Swift

// 只允许保存特定类型的文件(例如:只保存为文本文件)
savePanel.allowedFileTypes = ["txt"]

指定初始目录和文件名

Objective-C

// 设置初始目录
[savePanel setDirectoryURL:[NSURL fileURLWithPath:@"/Users/username/Documents"]];

// 设置默认文件名
[savePanel setNameFieldStringValue:@"MyDocument.txt"];

Swift

// 设置初始目录
savePanel.directoryURL = URL(fileURLWithPath: "/Users/username/Documents")

// 设置默认文件名
savePanel.nameFieldStringValue = "MyDocument.txt"

强制文件扩展名

Objective-C

// 强制附加的文件扩展名
[savePanel setExtensionHidden:NO];

Swift

// 强制附加的文件扩展名
savePanel.isExtensionHidden = false

封装工具类

为了更方便地使用 NSOpenPanelNSSavePanel,可以封装一个工具类,提供常见功能的高层接口。

Objective-C

#import <Cocoa/Cocoa.h>

@interface FileDialogHelper : NSObject

+ (void)showOpenPanelWithTitle:(NSString *)title
               canChooseFiles:(BOOL)canChooseFiles
          canChooseDirectories:(BOOL)canChooseDirectories
        allowsMultipleSelection:(BOOL)allowsMultipleSelection
               allowedFileTypes:(NSArray<NSString *> *)allowedFileTypes
              completionHandler:(void (^)(NSArray<NSURL *> *urls))completionHandler;

+ (void)showSavePanelWithTitle:(NSString *)title
               defaultFileName:(NSString *)defaultFileName
               allowedFileTypes:(NSArray<NSString *> *)allowedFileTypes
              completionHandler:(void (^)(NSURL *url))completionHandler;

@end

@implementation FileDialogHelper

+ (void)showOpenPanelWithTitle:(NSString *)title
               canChooseFiles:(BOOL)canChooseFiles
          canChooseDirectories:(BOOL)canChooseDirectories
        allowsMultipleSelection:(BOOL)allowsMultipleSelection
               allowedFileTypes:(NSArray<NSString *> *)allowedFileTypes
              completionHandler:(void (^)(NSArray<NSURL *> *urls))completionHandler {
    NSOpenPanel *openPanel = [NSOpenPanel openPanel];
    [openPanel setTitle:title];
    [openPanel setCanChooseFiles:canChooseFiles];
    [openPanel setCanChooseDirectories:canChooseDirectories];
    [openPanel setAllowsMultipleSelection:allowsMultipleSelection];
    [openPanel setAllowedFileTypes:allowedFileTypes];
    
    [openPanel beginWithCompletionHandler:^(NSModalResponse result) {
        if (result == NSModalResponseOK) {
            completionHandler([openPanel URLs]);
        } else {
            completionHandler(nil);
        }
    }];
}

+ (void)showSavePanelWithTitle:(NSString *)title
               defaultFileName:(NSString *)defaultFileName
               allowedFileTypes:(NSArray<NSString *> *)allowedFileTypes
              completionHandler:(void (^)(NSURL *url))completionHandler {
    NSSavePanel *savePanel = [NSSavePanel savePanel];
    [savePanel setTitle:title];
    [savePanel setNameFieldStringValue:defaultFileName];
    [savePanel setAllowedFileTypes:allowedFileTypes];
    
    [savePanel beginWithCompletionHandler:^(NSModalResponse result) {
        if (result == NSModalResponseOK) {
            completionHandler([savePanel URL]);
        } else {
            completionHandler(nil);
        }
    }];
}

@end

Swift

import Cocoa

class FileDialogHelper {
    
    // 显示打开对话框
    static func showOpenPanel(title: String,
                              canChooseFiles: Bool,
                              canChooseDirectories: Bool,
                              allowsMultipleSelection: Bool,
                              allowedFileTypes: [String]?,
                              completionHandler: @escaping ([URL]?) -> Void) {
        let openPanel = NSOpenPanel()
        openPanel.title = title
        openPanel.canChooseFiles = canChooseFiles
        openPanel.canChooseDirectories = canChooseDirectories
        openPanel.allowsMultipleSelection = allowsMultipleSelection
        openPanel.allowedFileTypes = allowedFileTypes
        
        openPanel.begin { result in
            if result == .OK {
                completionHandler(openPanel.urls)
            } else {
                completionHandler(nil)
            }
        }
    }
    
    // 显示保存对话框
    static func showSavePanel(title: String,
                              defaultFileName: String,
                              allowedFileTypes: [String]?,
                              completionHandler: @escaping (URL?) -> Void) {
        let savePanel = NSSavePanel()
        savePanel.title = title
        savePanel.nameFieldStringValue = defaultFileName
        savePanel.allowedFileTypes = allowedFileTypes
        
        savePanel.begin { result in
            if result == .OK {
                completionHandler(savePanel.url)
            } else {
                completionHandler(nil)
            }
        }
    }
}

使用示例

Objective-C

// 使用示例:显示打开对话框
[FileDialogHelper showOpenPanelWithTitle:@"选择文件或文件夹"
                          canChooseFiles:YES
                     canChooseDirectories:YES
                   allowsMultipleSelection:YES
                          allowedFileTypes:@[@"jpg", @"png"]
                         completionHandler:^(NSArray<NSURL *> *urls) {
    if (urls) {
        for (NSURL *url in urls) {
            NSLog(@"选择的文件/文件夹: %@", url.path);
        }
    } else {
        NSLog(@"用户取消了选择");
    }
}];

// 使用示例:显示保存对话框
[FileDialogHelper showSavePanelWithTitle:@"保存文件"
                          defaultFileName:@"Untitled.txt"
                          allowedFileTypes:@[@"txt"]
                         completionHandler:^(NSURL *url) {
    if (url) {
        NSLog(@"保存路径: %@", url.path);
    } else {
        NSLog(@"用户取消了保存");
    }
}];

Swift

// 使用示例:显示打开对话框
FileDialogHelper.showOpenPanel(title: "选择文件或文件夹",
                               canChooseFiles: true,
                               canChooseDirectories: true,
                               allowsMultipleSelection: true,
                               allowedFileTypes: ["jpg", "png"]) { urls in
    if let urls = urls {
        for url in urls {
            print("选择的文件/文件夹: \(url.path)")
        }
    } else {
        print("用户取消了选择")
    }
}

// 使用示例:显示保存对话框
FileDialogHelper.showSavePanel(title: "保存文件",
                               defaultFileName: "Untitled.txt",
                               allowedFileTypes: ["txt"]) { url in
    if let url = url {
        print("保存路径: \(url.path)")
    } else {
        print("用户取消了保存")
    }
}

深入探讨

自定义面板行为

有时候,你可能希望自定义 NSOpenPanelNSSavePanel 的行为,例如在用户选择某个文件或目录时执行特定的检查。

Objective-C

// Example of custom delegate for NSOpenPanel
@interface CustomOpenPanelDelegate : NSObject <NSOpenPanelDelegate>
@end

@implementation CustomOpenPanelDelegate

- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url {
    // 只允许选择特定的文件或目录
    if ([url.pathExtension isEqualToString:@"txt"]) {
        return YES;
    }
    return NO;
}

@end

// 使用自定义代理
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
CustomOpenPanelDelegate *delegate = [[CustomOpenPanelDelegate alloc] init];
[openPanel setDelegate:delegate];

Swift

// Example of custom delegate for NSOpenPanel
class CustomOpenPanelDelegate: NSObject, NSOpenPanelDelegate {
    func panel(_ sender: Any, shouldEnable url: URL) -> Bool {
        // 只允许选择特定的文件或目录
        if url.pathExtension == "txt" {
            return true
        }
        return false
    }
}

// 使用自定义代理
let openPanel = NSOpenPanel()
let delegate = CustomOpenPanelDelegate()
openPanel.delegate = delegate

面板定制界面

你可以在 NSOpenPanelNSSavePanel 中添加额外的用户界面元素,例如文本字段或复选框。

Objective-C

NSOpenPanel *openPanel = [NSOpenPanel openPanel];

// 创建自定义视图,例如一个 NSTextField
NSTextField *textField = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 24)];
[textField setStringValue:@"请输入额外信息"];

// 添加自定义视图到面板
[openPanel setAccessoryView:textField];

Swift

let openPanel = NSOpenPanel()

// 创建自定义视图,例如一个 NSTextField
let textField = NSTextField(frame: NSRect(x: 0, y: 0, width: 200, height: 24))
textField.stringValue = "请输入额外信息"

// 添加自定义视图到面板
openPanel.accessoryView = textField

总结

通过了解 NSOpenPanelNSSavePanel 的基本使用、配置文件类型和初始目录、处理用户操作、自定义面板行为以及添加自定义界面等技巧,并封装工具类,将能够更高效地使用这两个类创建和管理文件选择和保存对话框。

posted @ 2024-08-06 18:21  Mr.陳  阅读(51)  评论(0编辑  收藏  举报