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
この投稿へのコメント