2016-10-12 4 views
8

Я пытаюсь создать приложение macOS без раскадровки в Xcode 8 (стабильный) на macOS Sierra. Однако мой AppDelegate не инициируется. Вот код, у меня есть:NSApplicationDelegate не работает без раскадровки

import Cocoa 

@NSApplicationMain 
class AppDelegate: NSObject, NSApplicationDelegate { 
    var window: NSWindow! 

    override init() { 
     super.init() 
     print("Init") 
    } 

    func applicationDidFinishLaunching(_ aNotification: Notification) { 
     print("Finished launching") 

     // Create a window 
     window = NSWindow() 

     // Add the view controller 
     let viewController = ViewController() 
     window.contentView?.addSubview(viewController.view) 

     // Show the window 
     window.makeKeyAndOrderFront(nil) 
    } 
} 

Ни init или applicationDidFinishLaunching(_ aNotification: Notification) вызывается. Любая помощь приветствуется.

+0

Код выглядит совершенно нормально для меня ... нет причин, по которым он не должен попасть в init или applicationDidFinishLaunching ... –

+0

Почему бы вам просто не использовать Use Storiesboards при создании нового проекта? –

+0

@LeoDabus Потому что он все еще дает мне XIB-файл. Что странно, что если я удалю файл XIB/Storyboard в качестве «основного интерфейса», но сохранил его в проекте, AppDelegate все еще вызывается. Однако, как только я удалю его, он не будет вызван. – Zoyt

ответ

10

Вам нужно сделать несколько вещей здесь

  1. Удалить NSMainStoryboardFile ключ/значение из списка свойств
  2. Создать NSApplication подкласс и назначить его на ключ Principal Class (NSPrincipalClass).

assign custom class to principal class

Имя должно быть полностью квалифицированным с именем модуля.

  1. Вручную создайте ваш делегат в подклассе NSApplication и назначьте его свойству delegate.

Убедитесь, что вы держите ссылку на свой объект-делегат. Здесь я использовал здесь let.

class GrookApplication: NSApplication { 

    let strongDelegate = AppDelegate() 

    override init() { 
     super.init() 
     self.delegate = strongDelegate 
    } 

    required init?(coder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 

} 

например, простой делегат.

@NSApplicationMain 
class AppDelegate: NSObject, NSApplicationDelegate { 

    override init() { 
     super.init() 
     print("wassup") 
    } 

    func applicationDidFinishLaunching(_ aNotification: Notification) { 
     print("yo! I'm alive") 
    } 

} 
+0

как вы держите ссылку? Я пробовал это, и все работало нормально - окно было показано, но когда я попытался установить 'styleMask' окна в' .title', он дал мне исключение, говорящее «Ошибка утверждения» в [X.XApplication init],/Библиотека/Кэши/com.apple.xbs/Источники/AppKit/AppKit-1504.82.104/AppKit.subproj/NSApplication.m: 1778 2017-04-08 13: 25: 35.761585 + 0100 X [9073: 1059806] [Общие сведения ] Неподготовленное исключение было поднято 2017-04-08 13: 25: 35.761601 + 0100 X [9073: 1059806] [Общие] Создание нескольких приложений. –

+0

@TylerDurden сильная ссылка делается с помощью 'var' или' let'. Если вы этого не сделали, то слабая ссылка делегата высвободит экземпляр. i.e это 'self.delegate = AppDelegate()' не работает. Что касается вашего другого вопроса, не видя ваш код, я не знаю. Я подозреваю, что вы пытались сделать это '[NSApplication sharedApplication] .window' и не работали по причинам. –

0

В случае, если кто-то ищет версию Swift (на основе ответа @WarrenBurtons).

AppDelegate

@NSApplicationMain 
class AppDelegate: NSObject, NSApplicationDelegate { 
    var window: NSWindow? 

    func applicationDidFinishLaunching(_ aNotification: Notification) { 
     // Insert code here to initialize your application 
     window = NSWindow(contentViewController: RootViewController()) 
     window?.makeKeyAndOrderFront(self) 
    } 
} 

class RootViewController: NSViewController { 
    override func loadView() { 
     self.view = NSView() 
     self.view.frame = NSRect(x: 0, y: 0, width: 600, height: 400) 
    } 
} 

NSApplication подкласс

import Cocoa 

class Application: NSApplication { 
    let strongDelegate = AppDelegate() 

    override init() { 
     super.init() 
     self.delegate = strongDelegate 
    } 

    required init?(coder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 
} 

Info.plist запись

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 
<plist version="1.0"> 
<dict> 
    ... 
    <key>NSPrincipalClass</key> 
    <string>$(PRODUCT_MODULE_NAME).Application</string> 
    ... 
</dict> 
</plist> 

Я также создал суть для этого, что я буду держать до e для новых версий Xcode/Swift. https://gist.github.com/florieger/7ac5e7155f6faf18666f92f7d82f6cbc

Edit: Убедитесь удалить Main.storyboard/MainMenu.xib, в противном случае вы могли бы в конечном итоге с двумя окнами в UI Debugger.

Смежные вопросы