Objective-CからSwiftへの変換メモ その6

Xcodeに任せてできたコードが落ちたのでメモして置く。

Objective-C、Swift共に、AppDelegateに「gameWindowController(NSWindowController)」を定義して置く。またStoryBoard上にWindowControllerを追加し、そのStoryBoard IDを「GameWindow」として置く。それにボタンね!

Objective-Cだと問題ないコード

- (IBAction)ok:(id)sender {
    
    AppDelegate *delegate = [[NSApplication sharedApplication] delegate];
    
    // Open Game Window
    if (![[delegate.gameWindowController window] isVisible]) {
        
        NSString * storyboardName = @"Main";
        NSStoryboard *storyboard = [NSStoryboard storyboardWithName:storyboardName bundle: nil];
        delegate.gameWindowController = [storyboard instantiateControllerWithIdentifier:@"GameWindow"];
        [delegate.gameWindowController showWindow:self];
    }
}

上記コードをobjc2swiftで変換し、さらにXcodeの修正要求を反映したものが以下。

@IBAction func ok(_ sender: Any) {
        
        let delegate = NSApplication.shared.delegate as! AppDelegate

        if (!(delegate.gameWindowController?.window?.isVisible)!) {

            let storyboardName = "Main"
            let storyboard = NSStoryboard(name: NSStoryboard.Name(rawValue: storyboardName), bundle: nil)
            delegate.gameWindowController = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "GameWindow")) as? NSWindowController
            delegate.gameWindowController?.showWindow(self)
        }
}

動作させ見たら、lldbが起動してアプリが落ちた。
エラーコードは「Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)」
と言われても良く分からない。エラーで止まるのは「if (!(delegate.gameWindowController?.window?.isVisible)!)」の部分。

これ、実は、nilが大嫌いなSwift(?)的に考えてみると、Objective-Cのコードの方が何もなく動くことがおかしい気がしてくる。「delegate.gameWindowController?.window」はnilの場合があるからだ。

そう気が付けば簡単で、if letを使ったnilチェックを追加した以下のコードで正常に動作した。

@IBAction func Game(_ sender: Any) {
        
        let delegate = NSApplication.shared.delegate as! AppDelegate
        
        var gameWinBool: Bool
        
        // Swift requires nil check
        if let gameWindow = delegate.gameWindowController?.window {
            
            // Here, we check game window visibility if the window is not nil
            gameWinBool = gameWindow.isVisible
            
        } else {
            
            gameWinBool = false
        }
        
        // Open Game Window, if it isn't already exsists
        if !(gameWinBool) {
            
            let storyboardName = "Main"
            let storyboard = NSStoryboard(name: NSStoryboard.Name(rawValue: storyboardName), bundle: nil)
            delegate.gameWindowController = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "GameWindow")) as? NSWindowController
            delegate.gameWindowController?.showWindow(self)
        }
}

このコードは、ボタンを押したら新しいウインドウを表示するが、既に同じウインドウがある場合は開かないという動作をするものである。

この投稿へのコメント

コメントはありません。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

この投稿へのトラックバック

トラックバックはありません。

トラックバック URL