How to initialize NSTableRowView subclass? - cocoa

The compiler crashses on line 3 and I cant find information on NSTableRowView initializers anywhere
class ItemRowView: NSTableRowView {
convenience override init(frame: NSRect) {
self.init(frame: frame) // EXC BAD ACCESS
self.draggingDestinationFeedbackStyle = NSTableViewDraggingDestinationFeedbackStyle.None
}

First, init( frame: NSRect )is the designated initializer, so the keyword convenience is wrong in this place.
Then you probably meant to call the super initializer than your own method recursively.
At last you'll need to implement another required initializer init?(coder: NSCoder)
The following code should get you going:
class ItemRowView: NSTableRowView {
override init(frame: NSRect) {
super.init(frame: frame) // super - not self
self.draggingDestinationFeedbackStyle = NSTableViewDraggingDestinationFeedbackStyle.None
}
required init?(coder: NSCoder) {
// Write something useful here, or leave the default implementation
fatalError("init(coder:) has not been implemented")
}
}

Related

Custom UILabel-Subclass does not appear in dropdown selection of IB

I wrote a tiny class that inherits from UILabel
import UIKit
class ConnectionStateLabel: UILabel, BTConnectionStateChangedDelegate {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(frame: CGRect) {
super.init(frame: frame)
}
func didConnect() {
self.text = "Connected"
}
func didDisconnect() {
self.text = "Disconnected"
}
}
As far as I know, in Xcode that class should now be selectable from the dropdown menu (section "Custom Class") for any UILabel that I drag into my story board, but it does not show up. What is wrong with that class? What did I miss?

providing a designated initializer for a custom NSView in Swift

I have a custom NSView Class that looks like:
class MyClass: NSView
{
var myClassVar: NSColor
}
Naturally, Xcode is complaining that my class has no initializers, so I need to override the designated initializer so I can initialize myClassVar.
How can I do this?
Try this;
class MyClass: NSView
{
var myClassVar: NSColor! // the optional mark ! to be noticed.
override init(frame frameRect: NSRect) {
super.init(frame:frameRect);
}
required init(coder: NSCoder) {
super.init(coder: coder)
}
//or customized constructor/ init
init(frame frameRect: NSRect, otherInfo:Int) {
super.init(frame:frameRect);
// other code
}
}
If you give your color a default value, the initializers from NSView should still work.
Here are several ways to do this:
var myClassVar: NSColor?
var myClassVar: NSColor! // make sure to set this before you actually access it
var myClassVar: NSColor = NSColor.clearColor()
The second example (implicitly unwrapped optional) is what Apple does with IBOutlets. Otherwise you would need to have an initializer that sets each of your variables to a non-null value in your init methods.
For more information about this, see Swift Initialization and the Pain of Optionals, which discusses these solutions:
Instantiating it before the call to super.init.
Optional variable (NSColor?), instantiating it after super.init
Implicitly unwrapped optional variable (NSColor!)
Using a lazy property
Using a lazy property with a closure

Is it possible to make #IBDesignable override Interface Builder values?

For example, I want to subclass UIButton and set it's font to 20.0f by default. I can write something like this:
#IBDesignable
class HCButton: UIButton {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.customInit()
}
func customInit () {
titleLabel?.font = UIFont.systemFontOfSize(20)
}
}
But this does not affect preview in Interface Builder, all custom buttons appear with 15.0f font size by default. Any thoughts?
I have created new IBInspectable as testFonts :
import UIKit
#IBDesignable
class CustomButton: UIButton {
override init(frame: CGRect) {
super.init(frame: frame)
self.customInit()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.customInit()
}
func customInit () {
titleLabel?.font = UIFont.systemFontOfSize(20)
}
convenience init() {
self.init(frame:CGRectZero)
self.customInit()
}
override func awakeFromNib() {
super.awakeFromNib()
self.customInit()
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
self.customInit()
}
}
Hope it helps you :)
This is working for me.
I think you must override the init with frame initializer as well to affect that
override init(frame: CGRect) {
super.init(frame: frame)
self.customInit()
}
EASIER: The following solution usually works or me
import UIKit
#IBDesignable
class CustomButton: UIButton {
open override func layoutSubviews() {
super.layoutSubviews()
customInit()
}
func customInit () {
titleLabel?.font = UIFont.systemFontOfSize(20)
}
}
I hope that's what you're looking for.

Failable och non-failable initializers prevents me to extend NSView and implement NSCoding

I'm having problems implementing a subclass to NSView that implements NSCoding.
It seems like the declarations of init(coder: NSCoder) are conflicting in NSView and NSCoding.
NSView nowadays says it's failable, but NSCoding still says it's non-failable.
When I try to override init(coder: NSCoder) and do my custom initialisation, Xcode 6.1 gives me an error message:
A non-failable initializer cannot chain to failable initializer
'init(coder:)' written with 'init?'
How am I supposed to do my custom init of my class?
Here's a silly example where I extend a view and I want to persist an additional click counter for my view.
import Cocoa
import Foundation
class MyView: NSView, NSCoding {
var clickCounter:Int = 0
required init(coder: NSCoder) {
super.init(coder: coder)
coder.encodeObject(self.clickCounter,
forKey: "clickCounter")
}
override func encodeWithCoder(coder: NSCoder) {
super.encodeWithCoder(coder)
coder.encodeObject(self.clickCounter, forKey: "clickCounter")
}
override func mouseDown(theEvent: NSEvent) {
clickCounter++
}
}
You don't have to explicitly conform to NSCoding, because NSResponder (superclass of NSView) already conforms to it.
required init?(coder: NSCoder) {
super.init(coder: coder)
self.clickCounter = coder.decodeObjectForKey("clickCounter") as Int
}

Designated Initializer of UITextView

When I create a new subclass of UITextView in the Xcode 6 Beta, the following code is automatically provided.
import UIKit
class TerminalView: UITextView {
init(frame: CGRect) {
super.init(frame: frame)
// Initialization code
}
}
The previous code (completely provided by Xcode with nothing removed) gives the following error.
Must call a designated initializer of the superclass 'UITextView'
As far as I know, the designated for all subclasses of UIView is -initWithFrame: (or in Swift, init(frame:). If this is the case, why does the code provided by Xcode result in an error? I have added no new instance variables to the class, so nothing else has to be initialized yet.
It seems as though the only initializer that works for now is:
super.init(frame: CGRect, textContainer: NSTextContainer?)
which can be called with
super.init(frame: CGRect.zero, textContainer: nil)
This is most likely a bug in the initial beta release and will be fixed in upcoming beta releases.
For 2020:
class SpecialText: UITextView {
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
common()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
common()
}
private func common() {
backgroundColor = .yellow
font = .systemFont(ofSize: 26)
textColor = .green
}
}

Resources