Arda Arda - 6 months ago 38
Swift Question

Super init in Swift

I am trying to convert code objective c to swift. I convert many of them but I have a problem in code init part.


How can I fix my 3 error. It is looking easy to fix them deleting if statement. But for this problem I could not find real solution.
Deleting if statement It can cause the problem?

My codes:

My objective c code:

-(id)init
{
self = [super init];
if (self) // In swift I can delete this statement to solve my problem. Is it causing the problem?
{
[self commonInit];
}
return self;
}
-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) //Also I can delete this if to solve the error but I am not sure is it the best way
{
[self commonInit];
}
return self;
}


-(void)commonInit
{
self.backgroundColor = [UIColor clearColor];
self.contentView.backgroundColor = [UIColor clearColor];
self.selectionStyle = UITableViewCellSelectionStyleNone;
self.accessoryType = UITableViewCellAccessoryNone;

_textView = [[UITextView alloc] init];

_timeLabel = [[UILabel alloc] init];
_statusIcon = [[UIImageView alloc] init];

[self.contentView addSubview:_timeLabel];
[self.contentView addSubview:_statusIcon];

}


And my swift code:

init() {

super.init() //Gives Error: Must call a designated initializer of the superclass 'UITableViewCell'

if self != nil { //Value of type 'MessageCell' can never be nil, comparison isn't allowed

self.commonInit()
}
}

//Added this init because Xcode gives error if not add
required init?(coder aDecoder: NSCoder) {

super.init(coder: aDecoder)

fatalError("init(coder:) has not been implemented")
}


override init(style: UITableViewCellStyle, reuseIdentifier: String?){

super.init(style: style, reuseIdentifier: reuseIdentifier)

if self != nil { //Error: Value of type 'MessageCell' can never be nil, comparison isn't allowed

self.commonInit()
}

}

func commonInit() {

//set values

self.backgroundColor = UIColor.clearColor()
self.contentView.backgroundColor = UIColor.clearColor()
self.selectionStyle = .None
self.accessoryType = .None

self.timeLabel = UILabel()
self.statusIcon = UIImageView()

self.contentView.addSubview(timeLabel)
self.contentView.addSubview(statusIcon)
}

Answer

If you go inside the sources of UITableViewCell, you will see:

public init(style: UITableViewCellStyle, reuseIdentifier: String?)
public init?(coder aDecoder: NSCoder)

There is no init(), that's why you are getting the Must call a designated initializer error; you are trying to call NSObject's init method.
On a first pass, you could write something like this:

init() {
   super.init(style: UITableViewCellStyle.Default, reuseIdentifier: "example reuse id")
   self.commonInit()
}
override init(style: UITableViewCellStyle, reuseIdentifier: String?){
   super.init(style: style, reuseIdentifier: reuseIdentifier)
   self.commonInit()
}

Note that there is no need to check if self is nil in the second initializer, as it is not failable - meaning you will always have a valid and fully initialized object.
But, seeing that there is now quite a bit of duplication, if you still want a default init() you can get rid of the commonInit all together:

convenience init() {
   self.init(style: UITableViewCellStyle.Default, reuseIdentifier: "example reuse id")
}
override init(style: UITableViewCellStyle, reuseIdentifier: String?){
   super.init(style: style, reuseIdentifier: reuseIdentifier)
   //you can initialize your object here, or call your commonInit
}

Mind that if you don't need default values, you can also get rid of the first convenience init() :)

Comments