2014-06-14 12 views
28

मैं स्विफ्ट में एक नया दस्तावेज़ आधारित कोको परियोजना शुरू करने की कोशिश कर रहा हूं और NSWindowController (जैसा कि दस्तावेज़ आधारित ऐप्स पर ऐप्पल के मार्गदर्शिका में अनुशंसित है) का उप-वर्ग बनाना चाहता हूं। ओबीजेसी में आप NSWindowController सबक्लास को initWithWindowNibName: संदेश भेजकर एक उदाहरण देंगे, जिसे सुपरक्लास विधि को कॉल करने के अनुसार लागू किया गया था।स्विफ्ट और init (windowNibName) में NSWindowController उपclassing

स्विफ्ट init(windowNibName) में केवल सुविधा प्रारंभकर्ता के रूप में उपलब्ध है, NSWindowController का नामित प्रारंभकर्ता init(window) है जो स्पष्ट रूप से मुझे खिड़की में गुजरना चाहता है।

मैं अपने उपवर्ग से super.init(windowNibName) कॉल कर सकते हैं नहीं है, क्योंकि यह नामित प्रारंभकर्ता नहीं है, इसलिए मैं स्पष्ट रूप से convenience init(windowNibName), जो बारी में self.init(window) कॉल करने के लिए की जरूरत है लागू करने के लिए की है। लेकिन अगर मेरे पास मेरी निब फ़ाइल है, तो मैं उस प्रारंभकर्ता को भेजने के लिए निब फ़ाइल की विंडो कैसे एक्सेस करूं?

उत्तर

14

आप ओवरराइड करने के लिए की जरूरत है या तो NSWindowController (init(), init(window) और init(coder)), या उनमें से कोई भी तीनों नामित initializers, जिस स्थिति में अपने उपवर्ग स्वचालित रूप से init(windowNibName) और अन्य सभी सुविधा initializers वारिस होगा और आप इसे का निर्माण करने में सक्षम हो जाएगा सुपर क्लास का उपयोग सुविधा प्रारंभकर्ता:

// this overrides none of designated initializers 
class MyWindowController: NSWindowController { 
    override func windowDidLoad() { 
     super.windowDidLoad() 
    } 
} 

// this one overrides all of them 
// 
// Awkwardly enough, I see only two initializers 
// when viewing `NSWindowController` source from Xcode, 
// but I have to also override `init()` to make these rules apply. 
// Seems like a bug. 
class MyWindowController: NSWindowController 
{ 
    init() 
    { 
     super.init() 
    } 

    init(window: NSWindow!) 
    { 
     super.init(window: window) 
    } 

    init(coder: NSCoder!) 
    { 
     super.init(coder: coder) 
    } 

    override func windowDidLoad() { 
     super.windowDidLoad() 
    } 
} 

// this will work with either of the above 
let mwc: MyWindowController! = MyWindowController(windowNibName: "MyWindow") 

यह "प्रारंभ/स्वचालित प्रारंभकर्ता विरासत" द्वारा कवर किया जाता भाषा गाइड में:

हालांकि, कुछ शर्तों को पूरा होने पर सुपरक्लस प्रारंभकर्ता स्वचालित रूप से विरासत में प्राप्त होते हैं। व्यावहारिक रूप से, इसका मतलब है कि आपको कई सामान्य परिदृश्यों में प्रारंभकर्ता ओवरराइड लिखने की आवश्यकता नहीं है, और जब भी ऐसा करना सुरक्षित होता है तो न्यूनतम प्रयास के साथ अपने सुपरक्लास प्रारंभकर्ताओं को प्राप्त कर सकते हैं।

यह मानते हुए कि आप किसी भी नए गुणों आप एक उपवर्ग में परिचय के लिए डिफ़ॉल्ट मान प्रदान करते हैं निम्न दो नियम लागू होते हैं:

नियम 1 अपने उपवर्ग किसी भी नामित initializers परिभाषित नहीं करता है, तो यह स्वचालित रूप से सभी को विरासत में अपने superclass नामित प्रारंभिक के।

नियम 2 अपने उपवर्ग अपने सुपर क्लास नामित के सभी के एक कार्यान्वयन प्रदान करता है तो initializers-या तो उन्हें प्रति नियम 1 के रूप में विरासत में से, या उसके भाग के रूप में एक कस्टम कार्यान्वयन प्रदान करके परिभाषा-तो उसे अपने आप के सभी विरासत superclass सुविधा प्रारंभकर्ताओं।

+2

यह, पहचान निरीक्षक में कस्टम NSWindowController वर्ग का उपयोग करने के लिए खिड़की खिड़की आउटलेट खींचें और फिर एक वर्ग पर एक संपत्ति के रूप में कस्टम NSWindowController उदाहरण स्टोर करने के लिए निब के FileOwner स्थापित करने के लिए सुनिश्चित करें, अन्यथा कचरा इकट्ठा हो जाता है। –

4

मैं सुविधा प्रारंभकर्ता को कॉल करने वाले क्लास विधि के साथ काम करने में सक्षम था, कस्टम चर को संशोधित करता हूं, फिर नई वस्तु देता है।

तो एक उद्देश्य सी init विधि इस प्रकार दिखाई देगा:

class PPPluginInfoController: NSWindowController { 
    private var info: PPPlugInInfo! 
    class func windowControllerFromInfo(plugInfo: PPPlugInInfo) -> Self { 
     var toRet = self(windowNibName:"PPPlugInInfoController") 
     toRet.info = plugInfo 

     return toRet 
    } 
} 
+1

ग्रेट विचार, यह निश्चित रूप से सबसे अच्छा विकल्प की तरह लगता है। यद्यपि मुझे नफरत है कि गैर-वैकल्पिक गुण (var जानकारी) वैकल्पिक बनाते हैं, हालांकि – logancautrell

+0

मुझे यह पोस्ट मिला, और (कम से कम इस मामले में) विंडो ओवरब्राइड करना NNName इस समस्या को संबोधित करता है। http://dev.eltima.com/post/91454912064/nswindowcontroller-subclass-in-swift-project – logancautrell

-1

एक अद्यतन जवाब hamstergene रहे हैं:

//Class.h 
@class PPPlugInInfo; 

@interface PPPlugInInfoController : NSWindowController 
//... 
- (id)initWithPlugInInfo:(PPPlugInInfo *)plugInfo; 
//... 
@end 

//Class.m 
#include "Class.h" 

@interface PPPlugInInfoController() 
@property (strong) PPPlugInInfo *info; 
@end 

@implementation PPPlugInInfoController 

- (id)initWithPlugInInfo:(PPPlugInInfo *)plugInfo; 
{ 
    if (self = [self initWithWindowNibName:@"PPPlugInInfoController"]) { 
     self.info = plugInfo; 
    } 
    return self; 
} 

@end 

यह मैं कैसे स्विफ्ट संस्करण ने किया।

यह एक्सकोड संस्करण 6 पर ठीक काम करता है।1 (6A1052d)

Add your custom class to window controller

// 
// MainWindowController.swift 
// VHDA Editor 
// 
// Created by Holyfield on 20/11/14. 
// Copyright (c) 2014 Holyfield. All rights reserved. 
// 

import Cocoa 

class MainWindowController: NSWindowController { 

    //override func windowDidLoad() { 
    // super.windowDidLoad() 

     // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. 
    // } 

    override init() 
    { 
     super.init() 
     println(__FILE__, __FUNCTION__) 
    } 

    override init(window: NSWindow!) 
    { 
     super.init(window: window) 
     println(__FILE__, __FUNCTION__) 
    } 

    required init?(coder: (NSCoder!)) 
    { 
     super.init(coder: coder) 
     println(__FILE__, __FUNCTION__) 
    } 

    override func windowDidLoad() { 
     super.windowDidLoad() 
     println(__FILE__, __FUNCTION__) 
    } 

} 

कंसोल आउटपुट:

(…/MainWindowController.swift, init(coder:)) 
(…/MainWindowController.swift, windowDidLoad()) 
1

@ hamstergene के जवाब में प्रतिभा की स्ट्रोक के साथ-साथ init() ओवरराइड करने के लिए है, जो NSResponder से विरासत में मिली है।

class WindowController: NSWindowController { 

    var note: Document! // must be optional because self is not available before delegating to designated init 

    convenience init(note: Document) { 
     self.init(windowNibName: NoteWindowName) 
     self.document = document 
    } 

    override init(window: NSWindow?) { 
     super.init(window: window) 
    } 

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

    override init() { 
     fatalError("init() has not been implemented") 
    } 
} 

अब यह अब कस्टम खिड़की नियंत्रक क्या निब फाइल करने के लिए बताने के लिए आवश्यक है: अब एक self.init(windowNibName: NoteWindowName) के लिए एक नया initialiser और प्रतिनिधि है, जो बारी में एक बार विरासत में मिला तीनों नामित initialisers अधिरोहित कर रहे हैं लागू कर सकते हैं से लोड इसके बजाए, यह पहले स्थान पर उप-वर्ग को प्रेरित करने के लिए विशेष हो सकता है (उदाहरण के लिए, कुछ दस्तावेज़ पदानुक्रम में भाग लेना) ...

+0

इसके लिए धन्यवाद। तेजी से प्रारंभिकता एक गड़बड़ है। –

8

किसी भी इनिट विधियों को ओवरराइड करने के बजाय आप windowNibName संपत्ति को आसानी से ओवरराइड कर सकते हैं और एक हार्डकोडेड स्ट्रिंग वापस करें। यह आपको विंडो नियंत्रक बनाने के लिए मूल वेनिला इनिट विधि को कॉल करने की अनुमति देता है।

class WindowController: NSWindowController { 

    override var windowNibName: String! { 
     return "NameOfNib" 
    } 
} 

let windowController = WindowController() 

मैं let windowController = WindowController(windowNibName: "NameOfNib") बुला निब के नाम के रूप में एक कार्यान्वयन विस्तार है कि पूरी तरह से खिड़की नियंत्रक वर्ग के भीतर समझाया जाना चाहिए और कभी नहीं बाहर उजागर (और यह सिर्फ सादा आसान WindowController() कॉल करने के लिए है) है पर इस पसंद करते हैं।

आप init विधि में अतिरिक्त पैरामीटर जोड़ना चाहते हैं निम्नलिखित है:

  • अपने कस्टम init विधि कॉल super.init(window: nil) में। यह windowNibName संपत्ति के साथ NSWindowController प्राप्त करने के लिए मिलेगा।
  • अपने ऑब्जेक्ट को कॉन्फ़िगर करने के लिए आवश्यक init(coder: NSCoder) विधि को ओवरराइड करें या इसके उपयोग को प्रतिबंधित करने के लिए बस fatalError() पर कॉल करें (रनटाइम पर अल्बियेट)।
class WindowController: NSWindowController { 

    var test: Bool 

    override var windowNibName: String! { 
     return "NameOfNib" 
    } 

    init(test: Bool) { 
     self.test = test 
     super.init(window: nil) // Call this to get NSWindowController to init with the windowNibName property 
    } 

    // Override this as required per the class spec 
    required init?(coder: NSCoder) { 
     fatalError("init(coder:) has not been implemented. Use init()") 

     // OR 

     self.test = false 
     super.init(coder: coder) 
    } 
} 

let windowController = WindowController(test: true) 
संबंधित मुद्दे