Why Does This Compile: let v = UIView() - swift4.2

The documentation for UIView lists two initializers:
init(frame: CGRect)
init?(coder aDecoder: NSCoder)
According to my understanding, the compiler should force me to use one of those two. So, what gives? UIView is "special"?

Related

How to initialize NSTableRowView subclass?

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")
}
}

Custom init while creating view with storyboard or programmatically

I am trying to create a subclass of UIViewController and then through the storyboard or programmatically pass data to it. What I have tried so far is to have a subViewController swift file with a class subViewController that is a UIViewController
import UIKit
class subViewController: UIViewController {
var s1 = String()
init(myString: String) {
self.s1 = myString
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
#IBOutlet var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
print(self.s1)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
then in Identity Inspector I connect this to the view controller
and in AppDelegate.swift
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let SubVC = subViewController(myString: "Komic")
self.window?.rootViewController = SubVC
self.window?.makeKeyAndVisible()
return true
}
This loads a black screen but it logs out myString. As far as I understand it doesn't create the view but it just creates the instance of the class and that's why it's giving me the black screen. I also know that this part
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
runs when the storyboard gives you the view. But I can't pass data in there that's why I am trying to do this programmaticaly. Is it possible somehow to do that? I know I could instantiateWithIdentifier with the storyboard but I can't find a way to pass my data through that....any help?
An (ugly) way to solve this issue:
You can set your var s1 from an external buffer in your code (AppDelegate variable in this example)
required init?(coder aDecoder: NSCoder) {
self.s1 = UIApplication.shared().delegate.bufferForS1
super.init(coder: aDecoder)
}
And when you initiate your UIViewController through Storyboard:
UIApplication.shared().delegate.bufferForS1 = myS1Value
self.navigationController!.pushViewControllerFading(self.storyboard!.instantiateViewController(withIdentifier: "myViewControllerID") as UIViewController)
You are not loading the view controller from the storyboard when you call your custom initialiser, if you create a customer initialiser it is your responsibility to create the view hierarchy programatically - typically in loadView() although lots of people do it in viewDidLoad().
In Order to the load the view hierarchy you defined in the storyboard you can do this:
let storyBoard = UIStoryboard(name: "storyboardName", bundle: NSBundle.mainBundle())
let viewController = storyBoard.instantiateViewControllerWithIdentifier("storyboardId")
You define the storyboard Id of a view controller in the identity inspector

Problems debugging initializer?

I have a debugging error on the following code:
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
Here is all of my code:
class ViewController: UIViewController {
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
var button = UIButton.buttonWithType(.Custom) as UIButton
button.frame = CGRectMake(160, 100, 50, 50)
button.layer.cornerRadius = 0.5 * button.bounds.size.width
button.setImage(UIImage(named:"thumbsUp.png"), forState: .Normal)
button.addTarget(self, action: "thumbsUpButtonPressed", forControlEvents: .TouchUpInside)
view.addSubview(button)
}
func thumbsUpButtonPressed() {
println("thumbs up button pressed")
}
The error says:
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_1386_INVOP, subcode=0x0)
The debugger output says the following:
fatal error: init(coder:) has not been implemented: file...hi/ViewController.swift, line 14
I have had this error before and am unsure of how to fix it. The weird thing is, there was an error saying You don't have any initializers and had me put it in. It is giving me an error either way (with it or without it).
Any input and suggestions would be greatly appreciated.
Thanks in advance.
In your code, you trigger a "fatalError" instead of initializing. Replace
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
with
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}

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