Issues subclassing UIVisualEffect - ios

I am trying to subclass UIVisualEffect but I am having issues implementing the correct init methods. So far I have this:
import UIKit
class BlurView: UIVisualEffect {
init(effect: UIVisualEffect?) {
super.init(effect)
print("Init 1 called")
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
print("Init 2 called")
}
}
I am getting the error: "Missing the argument coder in the call". I have also tried:
import UIKit
class BlurView: UIVisualEffect {
init(effect: UIVisualEffect?) {
super.init()
print("Init 1 called")
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
print("Init 2 called")
}
}
This complains that I haven't implemented the init method. I tried doing this but still couldn't get it working. Any ideas how to go about implementing these methods? Thanks!

There is a typo, you want to subclass UIVisualEffectView, not UIVisualEffect.
They are different UIVisualEffectView inherits from UIView and apply the UIVisualEffect that you pass in. UIVisualEffect is just the effect.
class BlurView: UIVisualEffectView {
override init(effect: UIVisualEffect?) {
super.init(effect: effect)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}

Related

Strange issue with initializing custom view in Swift [duplicate]

This is my class of a UIView:
class overlap: UIView{
init() {
super.init(frame: UIScreen.main.bounds)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
fatalError("init(coder:) has not been implemented")
}
}
It should just fill up the screen. When I add the view in Storyboard with constraints pinned to the edges of the screen, it crashes when I launch the app. The error comes up as stated in the code above.
Creating and adding the subclass programmatically works with this init function:
override init(frame: CGRect) {
super.init(frame: frame)
}
But I want it reusable through Storyboard, without adding code. What is wrong with my code, and is it even possible what I want?
Thanks!
it crashes when I launch the app
Because that is what your code told it to do.
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
fatalError("init(coder:) has not been implemented")
}
fatalError means "crash me".

Adding subclass to Storyboard crashes

This is my class of a UIView:
class overlap: UIView{
init() {
super.init(frame: UIScreen.main.bounds)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
fatalError("init(coder:) has not been implemented")
}
}
It should just fill up the screen. When I add the view in Storyboard with constraints pinned to the edges of the screen, it crashes when I launch the app. The error comes up as stated in the code above.
Creating and adding the subclass programmatically works with this init function:
override init(frame: CGRect) {
super.init(frame: frame)
}
But I want it reusable through Storyboard, without adding code. What is wrong with my code, and is it even possible what I want?
Thanks!
it crashes when I launch the app
Because that is what your code told it to do.
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
fatalError("init(coder:) has not been implemented")
}
fatalError means "crash me".

Force user to use custom init method for the initialization

I am creating a UIView subclass with the intention to force users to my required init method than the default one.
So for that, I have created a convenience method for this.
#available(*, unavailable, message: "init is unavailable.")
public override init(frame: CGRect) {
super.init(frame: frame)
}
required
convenience public init(withSomeParameters myParam:Type) {
self.init(frame: CGRect.zero)
//Doing something nice!
}
This works! However, when I try to init it's showing me two ways to initialize it. How to force the user to make use of custom init method?
You can make it private , so user must need to init Test class with withSomeParameters
class Test:UIView {
private override init(frame: CGRect) {
super.init(frame: frame)
}
convenience public init(withSomeParameters myParam:Type) {
self.init(frame: CGRect.zero)
//Doing something nice!
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Maybe you need to mark the coder initialiser as unavailable as well:
#available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
Plus: remove the convenience from your initialiser, and call supers init(frame:)
public init(withSomeParameters myParam:Type) {
super.init(frame: .zero)
//Doing something nice!
}
As another example, here is some base UIView subclass I use in a lot of my projects that don't utilise storyboards:
class MXView: UIView {
init() {
super.init(frame: .zero)
}
// Storyboards are incompatible with truth and beauty.
#available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
Subclass:
class CustomView: MXView {
init(someParameters params: Type) {
// Phase 1: store ivars.
super.init()
// Phase 2: Do something nice.
}
If you do it like that, users of CustomView will be forced to use init(someParamters:). init(frame:) is shadowed because init(someParameters:) is a non-convenience init.

Inherit properties of a UITextfield

I am new to Swift programming and I have a few textfields with similar properties. Can I create one textfield with defined properties and then extend them to other textfields. num inherits properties like borderColor and borderWidth from textfield1.
class TextElement: UITextField {
var textfiedl1: UITextField = UITextField(frame:CGRectMake(38,383,299,44))
textfield1.layer.borderColor = UIColor.grayColor().CGColor
textfield1.layer.borderWidth = 1.0
}
class TextElement2 : UITextField {
var num: TextElement = TextElement(frame: CGRectMake(38,416,299,44))
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
num.backgroundColor = UIColor.redColor()
self.addSubview(num)
}
This does not give any output. The simulator screen is blank. Any solution for this.
This is completely off the top of my head (not tested) but I think you want something along the lines of the following:
Base Class:
class BaseTextField: UITextField {
init() {
super.init(frame: CGRectZero)
self.layer.borderColor = UIColor.grayColor().CGColor
self.layer.borderWidth = 1.0
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Sub Class:
class YourTextField: BaseTextField {
init(frame: CGRect, backgroundColor: UIColor) {
super.init()
self.frame = frame
self.backgroundColor = backgroundColor
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Usage in Viewcontroller:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let textField = YourTextField(frame: CGRectMake(38, 416, 299, 44), backgroundColor: UIColor.redColor())
self.view.addSubview(textField)
}
}
Note:
You probably want to actually do something in required init?(coder aDecoder: NSCoder) but for here I left the default implementation.
What you need here is a helper object. Lightweight structs are perfect for this. Create a struct embodying the configuration features. Give the struct a method that you can call, passing self as a parameter, allowing the struct to configure your text field (warning: this is Swift 3):
struct TFConfig {
let borderColor = UIColor.gray().cgColor
let borderWidth:CGFloat = 1.0
func configure(_ tf:UITextField) {
tf.layer.borderColor = borderColor
tf.layer.borderWidth = borderWidth
}
}
class MyTextField : UITextField {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
TFConfig().configure(self)
}
}
// ... similarly for other text fields

Swift required init NSCoder constructor

I have the following class representing a button in my iOS 8 custom keyboard:
internal class KeyButton: UIButton {
required init(char: Character) {
super.init()
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Since KeyButton is not initialised via storyboard the constructor (coder: NSCoder) would never be called.
The problem is that I am required to implement (coder: NSCoder) constructor, when I run the app I receive the exception plugin interrupted when instantiating KeyButton.
Why am I required to implement (coder: NSCoder) constructor although I instantiate everything programatically
It has nothing to do with the coder. UIButton's init() calls init(frame: CGRect), which you haven't implemented. Add the following, and you should be good to go...
override init(frame: CGRect ) {
super.init(frame: frame)
println("Button frame allocated")
}

Resources