i will overload the init Method in Swift how i can implement that?
here my code that not work
code removed
Edit:
So it would be work fine
override init() {
super.init();
}
init(title:String?) {
super.init();
self.title = title
}
convenience init(title:String?, imageName:String?) {
self.init(title:title)
self.imageName = imageName
}
convenience init(title:String?, imageName:String?, contentKey:String?) {
self.init(title:title, imageName:imageName)
self.contentKey = contentKey
}
Updated Answer
class Y { }
class X : Y {
var title: String?
var imageName: String?
convenience override init() {
self.init(title: nil, imageName: nil)
}
convenience init(title:String?) {
self.init(title: title, imageName: nil)
}
init(title: String?, imageName: String?) {
self.title = title
self.imageName = imageName
super.init()
}
}
Use the most complete initializer as the designated initializer.
In this case init(title: String?, imageName: String?) is the only initializer that sets all its properties, so it should be the designated initializer.
Initialize your properties before calling super.init().
My old answer only worked because title and imageName were both var and optional.
In Two-Phase Initialization section of The Swift Programming Language: Initialization
Safety check 1
A designated initializer must ensure that all of the properties introduced by its class are initialized before it delegates up to a superclass initializer.
Old Answer
I plugged the sample into a playground, here is how I got it to work:
class Y { }
class X : Y {
var title: String?
var imageName: String?
override init() {
}
init(aTitle:String?) {
super.init()
self.title = aTitle
}
convenience init(aTitle:String?, aImageName:String?) {
self.init(aTitle: aTitle)
self.imageName = aImageName
}
}
init(aTitle:String?, aImageName:String?) cannot call init(aTitle:) and still be a designated initializer, it must be a convenience initializer.
self.init must be before anything else in init(aTitle:String?, aImageName:String?).
initializer must be passed the parameter name self.init(aTitle) must be self.init(aTitle: aTitle).
As a side note, I removed the unneeded semicolons and put super.init() first for style reasons.
Hope that helps.
UPDATE
To follow Apple's advice, there should only be one designated, the rest should be convenience initializers. For example, if you decide init(aTitle:String?) should be the designated initializer, then the code should look like:
convenience override init() {
self.init(aTitle: nil) // A convenience initializer calls the designated initializer.
}
init(aTitle:String?) {
super.init() // Only the designated initializer calls super.init.
self.title = aTitle
}
convenience init(aTitle:String?, aImageName:String?) {
self.init(aTitle: aTitle) // A convenience initializer calls the designated initializer.
self.imageName = aImageName
}
There are times when you might want more than once designated initializer, for example, UIView, but that should be an exception, not the rule.
UPDATE 2
Classes should have one designated initializer. Convenience initializer will (eventually) call the the designated initializer.
Initialization
A class may have multiple initializers. This occurs when the initialization data can take varied forms or where certain initializers, as a matter of convenience, supply default values. In this case, one of the initialization methods is called the designated initializer, which takes the full complement of initialization parameters.
Multiple initializers
The Designated Initializer
The initializer of a class that takes the full complement of initialization parameters is usually the designated initializer. The designated initializer of a subclass must invoke the designated initializer of its superclass by sending a message to super. The convenience (or secondary) initializers—which can include init—do not call super. Instead they call (through a message to self) the initializer in the series with the next most parameters, supplying a default value for the parameter not passed into it. The final initializer in this series is the designated initializer.
Related
I am converting an app from Objective-C to Swift 2.0 and while converting an NSView-subclass, I am getting an error while trying to store a weak back-reference from a CALayer to the ActionViewItemInternal which is needed so that the layer drawing code can access the item data. I want to use a weak reference in order to avoid a retain-cycle (item object retains layer so layer needs a weak reference back to the item object).
class WeakReference {
weak var reference: AnyObject?
init(reference: AnyObject) {
self.reference = reference
}
}
class ActionView: NSView {
// Used to store an item in ActionView.items
private class ActionViewItemInternal {
var actionViewItem: ActionViewItem
var layer: CALayer
...
init(withItem actionViewItem: ActionViewItem) {
self.actionViewItem = actionViewItem
let layer = CALayer()
// !!!!!!!!!!!!!!!!!!!!!!!!!!
// other init and error here:
// !!!!!!!!!!!!!!!!!!!!!!!!!!
layer.setValue(value: WeakReference(reference: self), forKey: "ActionViewItem")
self.layer = layer
}
}
var items: [ActionViewItem] = [ActionViewItem]()
...
}
Where ActionItemView is defined as:
#objc protocol ActionViewItem {
var name: String { get set }
var icon: NSImage { get set }
var enabled: Bool { get set }
}
I am getting the error:
ActionView.swift:73:19: Cannot invoke 'setValue' with an argument list of type '(value: WeakReference, forKey: String)'
Xcode version: Xcode 7.0 beta 1. Deployment targets tried: 10.9, 10.10 and 10.11.
EDIT: I have tried using NSValue, as per #rickster's suggestion, but the error remains:
layer.setValue(value: NSValue(nonretainedObject: self), forKey: "ActionViewItem")
ActionView.swift:72:19: Cannot invoke 'setValue' with an argument list of type '(value: NSValue, forKey: String)'
The setValue(_:forKey:) method requires an ObjC object for the value — you're passing an instance of a pure Swift class. If you make your WeakReference class either annotated with #objc or inherit from NSObject that call should succeed.
However, you don't need your own class for this purpose anyway... The NSValue method valueWithNonretainedObject does the same thing.
Oh, and on closer inspection: you're using an extra argument label in your call. It should be like setValue(myvalue, forKey: mykey).
I'd like to make an NSView subclass that handles drag and drop by redirecting it to its view controller. So I have to override NSDraggingDestination protocol methods in my NSView subclass. There I'd like to check if method is supported by view controller implementation and call it, or if not supported to call base class implementation. The first part seems easy by optional chaining, but how do I check if method implemented in super class? For example, this is what I came up for draggingEnded method. It gives a runtime crash inside if block, if the view controller does not implement draggingEnded method.
class ControllerChainedView: NSView {
#IBOutlet weak var chainedController: NSViewController!
override func draggingEnded(sender: NSDraggingInfo?) {
let destination = chainedController as! NSDraggingDestination
if !(destination.draggingEnded?(sender) != nil) {
super.draggingEnded(sender);
}
}
}
Changing the line inside if to super.draggingEnded?(sender); gives a compiler error. (Operand of postfix '?' should have optional type; type is '(NSDraggingInfo?) -> Void')
There is no problem with say similar draggingEntered method as it seems to be implemented in NSView.
So the question is how to detect if one can call method in super or not?
If your super is based on NSObject, you can still use respondsToSelector: in this way:
if super.respondsToSelector("draggingEnded:") {
super.draggingEnded(sender)
}
UPDATE - based on 1st Alex comment
Depends. Generally no, you can't do this with optional chaining without calling it.
But what you can do is to check if function was or wasn't called. But again, in specific cases only. Must be #objc protocol, must be based on NSObject and return value of optional function must not be Optional.
Check following examples.
#objc protocol Opt {
optional func implemented() -> Void
optional func notImplemented() -> Void
}
class Object: NSObject, Opt {
func implemented() {}
}
let o = Object() as Opt
let implementedCalled = o.implemented?() != nil // == true
let notImplementedCalled = o.notImplemented?() != nil // == false
In this particular case, implementedCalled is set to true. In other words, you can at least check if method was called or not. It's because of optional chaining and because o.implemented return type is Void, o.implemented?() returns Void?.
You can also do something like this ...
if o.implemented != nil {
// Function is implemented AND implemented WAS CALLED
} else {
// Function is not implemented
}
... but don't forget that it's not check if function is implemented, it's - if function is implemented, call it and return .Some(Void) or .None if it's not implemented.
In your particular case, you can do this:
override func draggingEnded(sender: NSDraggingInfo?) {
let destination = chainedController as! NSDraggingDestination
if destination.draggingEnded?(sender) == nil {
// .None returned - method not implemented in destination
// draggingEnded is called in super only if it's implemented
// ignore result of type Void?
super.draggingEnded?(sender)
}
}
If return type of optional function is not Void, but for example String, it behaves in the same way.
#objc protocol Opt {
optional func name() -> String
}
class Object: NSObject, Opt {
func name() -> String { return "Object" }
}
let o = Object() as Opt
let n: String? = o.name?() // n contains "Object"
If name is not implemented, n will contain None.
So far, so good. We can check if function was called for Void and for String (or any other type).
But what if return type is Optional? String? for example.
#objc protocol Opt {
optional func name() -> String?
}
class Object: NSObject, Opt {
func name() -> String? { return nil }
}
class Object2: NSObject, Opt {
}
let o = Object() as Opt
let n = o.name?()
let o2 = Object2() as Opt
let n2 = o2.name?()
Object implements name, but it returns nil and Object2 does not implement name at all. But both n and n2 contain nil. In other words, if return type is Optional, we can't check if function is or isn't implemented.
As you can see, it's tricky. Sometimes it suits your needs, sometimes not. If you are sure that your object is based on NSObject, stick with .respondsToSelector to be safe. You can then ignore all these conditions and cases.
If your goal is to just call function if it's implemented and you don't care if it is really implemented or not, if you're not interested in result, you can do it with ?.
Since the optional syntax ? is not working for super you'll have to check explicitly whether the superclass implements the method.
if NSView.instancesRespondToSelector("draggingEnded:") {
super.draggingEnded(sender)
}
I am subclassing NSObject in order to have an ordered collection that is accessible to Cocoa Bindings. My class looks more or less like this:
public class OrderedCollection<Tk: Hashable, Tv> : NSObject {
var keys: Array<Tk> = []
var values: Dictionary<Tk,Tv> = [:]
override init() {
super.init()
}
// Subscript methods go here
override public var description: String {
var result = "{\n"
for i in 0..<self.count {
result += "[\(i)]: \(self.keys[i]) => \(self[i]!)\n"
}
result += "}"
return result
}
}
It doesn't compile. The error says: '#objc' getter for non-'#objc' property.
Is there a way of making the getter non-'#objc' as it were? I don't need the property to be accessible from Objective-C...
It seems the answer was in the comments of an entirely different question. https://stackoverflow.com/a/26688572/4180258
Essentially, there is a bit of an ugly workaround:
class BaseNSObjectWithDescriptionFix: NSObject {
func makeDescription() -> String {
return super.description
}
override var description: String {
return makeDescription()
}
}
Now you just use BaseNSObjectWithDescriptionFix instead of NSObject and override makeDescription as you like.
In my case, I didn't need it because for my purposes I could use [String] and [String:AnyObject], but this may be of some use to someone in the future.
To override the description property of NSObject when subclassing in Swift, with two generic types like you have and keeping your class public, you just need this:
public class OrderedCollection<Tk: Hashable, Tv>: NSObject {
override public var description: String {
return "hello"
}
}
You could also, instead, conform to the CustomStringConvertible protocol (formerly, pre-Swift 2, known as Printable) and forget NSObject, like so:
public class OrderedCollection<Tk: Hashable, Tv>: CustomStringConvertible {
public var description: String {
return "hello"
}
}
In other words, generics don't really change anything for this case. (Not sure if things were different in an earlier version of Swift...)
The content of description I leave to you (e.g. you don't have a count property above, so I'm guessing you omitted more code than just subscript methods).
I have the following class that inherits from NSManagedObject:
import Foundation
import CoreData
class Note: NSManagedObject {
#NSManaged var text: String
#NSManaged var name: String
init(name: String, text:String, context: NSManagedObjectContext){
let entity = NSEntityDescription.entityForName("Note", inManagedObjectContext: context);
super.init(entity: entity!, insertIntoManagedObjectContext: context)
self.text = text
self.name = name;
}
}
When I create instances of it, everything works fine, but when I make a search for these entities, I get a very odd error:
fatal error: use of unimplemented initializer 'init(entity:insertIntoManagedObjectContext:)'
This is the code that causes the error:
func coreDatePlayground(){
var note = Note(name: "A new note", text: "blah", context: self.managedObjectContext!)
println("\(note.name) \(note.text)")
var noote2 = Note(name: "Another note", text: "blah blah", context: self.managedObjectContext!)
managedObjectContext?.save(nil)
var fetch = NSFetchRequest(entityName: "Note")
// This line causes the crash.
var results = self.managedObjectContext?.executeFetchRequest(fetch, error: nil)
if let objects = results{
println(objects.count)
}
}
I found out that changing the initialiser by making it a convenience one and calling on self instead of on super gets rid of the issue, but I have no idea why.
convenience init(name: String, text:String, context: NSManagedObjectContext){
let entity = NSEntityDescription.entityForName("Note", inManagedObjectContext: context);
self.init(entity: entity!, insertIntoManagedObjectContext: context)
self.text = text
self.name = name;
}
The code above works, but I have no idea why. Anybody knows what's going on? Is it a bug or is my fault?
This is documented behavior.
Swift subclasses do not inherit their superclass initializers by default
For example, following code does not even compile, because Child does not inherit init(id:String) automatically. This mechanism make sure name in Child class properly initialized.
class Parent {
var id:String
init(id:String) {
self.id = id
}
}
class Child:Parent {
var name:String
init(id:String, name:String) {
self.name = name
super.init(id: id)
}
}
var child1 = Child(id:"child1")
If you define only convenience initializers in subclass, then it automatically inherits all of its superclass designated initializers as documented in "Automatic Initializer Inheritance" section
You must implement the following in your NSManagedObject subclass (this is the Swift 3.0 version):
#objc
private override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?) {
super.init(entity: entity, insertInto: context)
}
The answer is kind of answering it, but not really directly.
The reasoning for this is that Swift does not inherit their supercalls designated initializers by default AND it seems as CoreData by uses this initializer when doing fetches (insert a breakpoint in the method to see). So here we "bring up" the designated initializer for CoreData to use.
If you have NSManagedObject base classes, you must also implement this method in those.
Credits to JSQCoreDataKit for the idea.
I am trying to start a new document based Cocoa project in Swift and want to create a subclass of NSWindowController (as recommended in Apple's guides on document based apps). In ObjC you would make an instance of an NSWindowController subclass sending the initWithWindowNibName: message, which was implemented accordingly, calling the superclasses method.
In Swift init(windowNibName) is only available as an convenience initializer, the designated initializer of NSWindowController is init(window) which obviously wants me to pass in a window.
I cannot call super.init(windowNibName) from my subclass, because it is not the designated initializer, so I obviously have to implement convenience init(windowNibName), which in turn needs to call self.init(window). But if all I have is my nib file, how do I access the nib file's window to send to that initializer?
Instead of overriding any of the init methods you can simply override the windowNibName property and return a hardcoded string. This allows you to call the basic vanilla init method to create the window controller.
class WindowController: NSWindowController {
override var windowNibName: String! {
return "NameOfNib"
}
}
let windowController = WindowController()
I prefer this over calling let windowController = WindowController(windowNibName: "NameOfNib") as the name of the nib is an implementation detail that should be fully encapsulated within the window controller class and never exposed outside (and it's just plain easier to call WindowController()).
If you want to add additional parameters to the init method do the following:
In your custom init method call super.init(window: nil). This will get NSWindowController to init with the windowNibName property.
Override the required init(coder: NSCoder) method to either configure your object or simply call fatalError() to prohibit its use (albiet at runtime).
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)
You need to override either all three designated initializers of NSWindowController (init(), init(window) and init(coder)), or none of them, in which case your subclass will automatically inherit init(windowNibName) and all others convenience initializers and you will be able to construct it using superclass's convenience initializer:
// 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")
This is covered by "Initialization / Automatic Initializer Inheritance" in the language guide:
However, superclass initializers are automatically inherited if certain conditions are met. In practice, this means that you do not need to write initializer overrides in many common scenarios, and can inherit your superclass initializers with minimal effort whenever it is safe to do so.
Assuming that you provide default values for any new properties you introduce in a subclass, the following two rules apply:
Rule 1
If your subclass doesn’t define any designated initializers, it automatically inherits all of its superclass designated initializers.
Rule 2
If your subclass provides an implementation of all of its superclass designated initializers—either by inheriting them as per rule 1, or by providing a custom implementation as part of its definition—then it automatically inherits all of the superclass convenience initializers.
I was able to work around this by just having a class method that calls the convenience initializer, modifies the custom variables, then returns the new object.
So an Objective C init method would look like this:
//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
This is how I did the Swift version:
class PPPluginInfoController: NSWindowController {
private var info: PPPlugInInfo!
class func windowControllerFromInfo(plugInfo: PPPlugInInfo) -> Self {
var toRet = self(windowNibName:"PPPlugInInfoController")
toRet.info = plugInfo
return toRet
}
}
The stroke of genius in #hamstergene's answer is to override init() as well, which is inherited from NSResponder. Now one can introduce a new initialiser and delegate to self.init(windowNibName: NoteWindowName), which is in turn inherited once all three designated initialisers are overridden:
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")
}
}
Now it is no longer necessary to tell the custom window controller what nib file to load from. Instead, it can be specialised for whatever motivated the subclass in the first place (like taking part in some document hierarchy, for example)...
An update to hamstergene answer.
This works fine on Xcode Version 6.1 (6A1052d)
//
// 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__)
}
}
Console output:
(…/MainWindowController.swift, init(coder:))
(…/MainWindowController.swift, windowDidLoad())