본문 바로가기
macOS

NSOpenPanel, NSSavePanel 예제

by 고고 2021. 11. 25.

안녕하세요 ◠‿◠ 고고입니다.

NSOpenPanel과 NSSavePanel로 png, jpeg 등 이미지를 열고 저장하는 것과 pdf, hwp 등의 파일을 열고 저장하는 코드를 올려봤습니다. 편하게 사용해주세요~

1. NSOpenPanel

1.1 Open images

extension NSOpenPanel {
    // Image 가져오기 실패 시 사용
    enum ImageError: Error {
        case selectionFailed
    }
    
    static func openImage(completion: @escaping (_ result: Result<NSImage, Error>) -> Void) {
        let panel = NSOpenPanel()
        // 다중 선택가능
        panel.allowsMultipleSelection = false
        // 파일 선택가능
        panel.canChooseFiles = true
        // 폴더 선택가능
        panel.canChooseDirectories = false
        // 가져올 수 있는 파일형식
        panel.allowedFileTypes = ["jpg", "jpeg", "png"]
        // 열기 눌렀을 때
        panel.begin { result in
            guard
                result == .OK,
                let url = panel.urls.first,
                let image = NSImage(contentsOf: url) // 가져온 url을 NSImage로 변환
            else {
                completion(.failure(ImageError.selectionFailed))
                return
            }
            completion(.success(image))
        }
    }
}

 

1-2. Open files

extension String {
    var lastPathComponent: String {
        get {
            return (self as NSString).lastPathComponent
        }
    }
}
static func openFile(completion: @escaping (_ result: Result<(String, Data), Error>) -> Void) {
        let panel = NSOpenPanel()
        // 다중 선택가능?
        panel.allowsMultipleSelection = false
        // 파일 선택가능?
        panel.canChooseFiles = true
        // 폴더 선택가능?
        panel.canChooseDirectories = false
        // 열기 눌렀을 때
        panel.begin { result in
            guard
                result == .OK,
                let url = panel.urls.first
            else {
                completion(.failure(ImageError.selectionFailed))
                return
            }
            do {
                let data = try Data(contentsOf: url)
                completion(.success((url.path.lastPathComponent, data))) // 파일 이름, 데이터
            } catch {
                completion(.failure(error))
            }
        }
    }

 

 

2. NSSavePanel

2-1. Save images

extension NSSavePanel {
    
    // 저장 실패 시 사용
    enum SaveError: Error {
        case saveFailed
    }
	
    static func saveImage(fileName: String, targetPath: String = "Downloads", image: NSImage, completion: @escaping (_ result: Result<Void, Error>) -> Void) {
        
        let targetPath = NSHomeDirectory()
        let savePanel = NSSavePanel()
        
        savePanel.directoryURL = URL(fileURLWithPath: targetPath.appending(targetPath))
        savePanel.canCreateDirectories = true
        savePanel.nameFieldStringValue = fileName
        savePanel.allowedFileTypes = ["png", "jpg", "jpeg"]
        savePanel.begin { result in
            if result.rawValue == NSApplication.ModalResponse.OK.rawValue {
                if let url = savePanel.url {
                    let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil)!
                    let bitmapRep = NSBitmapImageRep(cgImage: cgImage)
                    let jpegData = bitmapRep.representation(using: NSBitmapImageRep.FileType.png, properties: [:])!
                    do {
                        try jpegData.write(to: url)
                        completion(.success(()))
                    } catch {
                        completion(.failure(error))
                    }
                }
            } else {
                completion(.failure(SaveError.saveFailed))
            }
        }
    }
}

 

2-2. Save files

class Downloader {
    
    // 저장 실패 시 사용
    enum WriteError: Error {
        case writeFailed
    }
    
    class func load(url: URL, to localUrl: URL, completion: @escaping (_ result: Result<Void, Error>) -> Void) {
        let sessionConfig = URLSessionConfiguration.default
        let session = URLSession(configuration: sessionConfig)
        let request = try! URLRequest(url: url, method: .get)
        
        let task = session.downloadTask(with: request) { (tempLocalUrl, response, error) in
            if let tempLocalUrl = tempLocalUrl, error == nil {
                do {
                    try FileManager.default.copyItem(at: tempLocalUrl, to: localUrl)
                    completion(.success(()))
                } catch (let writeError) {
                    completion(.failure(writeError))
                }
                
            } else {
                completion(.failure(WriteError.writeFailed))
            }
        }
        task.resume()
    }
}
extension NSSavePanel {
    
    // 저장 실패 시 사용
    enum SaveError: Error {
        case saveFailed
    }
    
    static func saveFile(fileName: String, targetPath: String = "Downloads", fileUrl: String, completion: @escaping (_ result: Result<Void, Error>) -> Void) {
        
        let targetPath = NSHomeDirectory()
        let savePanel = NSSavePanel()
        
        savePanel.directoryURL = URL(fileURLWithPath: targetPath.appending(targetPath))
        savePanel.canCreateDirectories = true
        savePanel.nameFieldStringValue = fileName
        savePanel.level = NSWindow.Level(rawValue: Int(CGWindowLevelForKey(.modalPanelWindow)))
        savePanel.begin { result in
            if result.rawValue == NSApplication.ModalResponse.OK.rawValue {
                if let url = URL(string: fileUrl) {
                    Downloader.load(url: url, to: savePanel.url!, completion: { result in
                        switch result {
                        case .success(_):
                            completion(.success(()))
                        case .failure(let error):
                            completion(.failure(error))
                        }
                    })
                }
            } else {
                completion(.failure(SaveError.saveFailed))
            }
        }
    }
}

댓글