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
}
}
Related
I constantly find "leaks" using Xcode instruments (8.2) where free is the last call on the object/memory. If free is being called successfully then why would instruments be reporting this as a leak? Is this really a leak or a bug in instruments?
Here is one example
For example, this small segment of code seems to cause instruments to report leaks like these.
class RDTranslateComponentView: RDMessageCellComponentView {
let textView: RDTextMessageCellComponentView
let button: UIButton
convenience init() {
self.init(frame: CGRect.zero)
}
override init(frame: CGRect) {
self.textView = RDTextMessageCellComponentView()
self.button = UIButton(type: .custom)
super.init(frame: frame)
self.setupView()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupView() {
self.textView.label.font = UIFont.proximaSemiBold(withSize: 14)
self.textView.label.textColor = UIColor.remindBrand()
self.textView.bubble.backgroundColor = UIColor.white
self.addSubviews([ self.textView, self.button ])
self.button.addTarget(self, action: #selector(pressedButton(_:)), for: .touchUpInside)
}
#objc private func pressedButton(_ sender: UIButton?) {
/// Code that calls into a delegate
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
return self.textView.sizeThatFits(size)
}
override func layoutSubviews() {
super.layoutSubviews()
self.textView.frame = self.bounds
self.button.frame = self.bounds
}
}
class RDMessageCellComponentView: UIView {
/// The inside of this is just a bag of constants. Doesn't even touch anything View related so I'm omitting.
}
Here's a stack trace from my code in association to a leak. Keep in mind this isn't the only place this happens. This case props up often though and seems to be exclusive to code that has UILabel instantiated inside the init method of a subview that is added as a subview to another view.
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")
}
}
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?
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
}
changing corner radius of NSView should be pretty straight forward however i am getting error message "fatal error: Can't unwrap Optional.None". is there a chance i am doing this with 10.9 not 10.10 and this is happening due framework differences? or the code is wrong.
class aRoundView: NSView {
let cornerRad = 5.0
init(frame: NSRect) {
super.init(frame: frame)
self.layer.cornerRadius = cornerRad
}
override func drawRect(dirtyRect: NSRect)
{
super.drawRect(dirtyRect)
NSColor.redColor().setFill()
NSRectFill(dirtyRect)
}
}
EDIT
calling it in
func applicationDidFinishLaunching(aNotification: NSNotification?) {
let aView = mainViewTest(frame: NSMakeRect(0, 0, 100, 100))
self.window.contentView.addSubview(aView)
}
actually it is not just that. any iteration with self.layer gives same result, backgroundcolor etc.
That is because self.layer is an optional value, which is currently not set. Add self.wantsLayer = true before self.layer.cornerRadius, to make sure a proper layer exists.
init(frame: NSRect) {
super.init(frame: frame)
self.wantsLayer = true
self.layer.cornerRadius = cornerRad
}