lvp lvp - 6 months ago 15
Swift Question

Struct inside subclass, unwrap optional when assigning to self

To be honest I couldn't came with better title, so If anyone can suggest something more meaningful it would be great.

Some time ago I saw great talk Let's Play: Refactor the Mega Controller! by Andy Matuschak. He showed nice pattern: using struct to inject data to the view, to decouple view's internals from view controller.
It goes like this:

class TaskTableViewCell: UITableViewCell {
struct ViewData {
let title: String
let timingDescription: String
}

var viewData: ViewData? {
didSet {
textLabel!.text = viewData?.title
detailTextLabel!.text = viewData?.timingDescription.lowercaseString
}
}
}


Now as you can see, in
didSet
for
viewData
we update
textLabel
and
detailTextLabel
of
TaskTableViewCell
. Well, actually of
UITableViewCell
since both of them are inherited properties.

But this is basic table view cell, I want something customised. I've added
someText
property, and required inits. Now, class looks as follows:

class TaskTableViewCell: UITableViewCell {
struct ViewData {
let title: String
let timingDescription: String
}

var viewData: ViewData? {
didSet {
textLabel!.text = viewData?.title
detailTextLabel!.text = viewData?.timingDescription.lowercaseString
}
}

var someText: String

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
someText = ""
super.init(style: style, reuseIdentifier: reuseIdentifier)
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}


And of course I would like to update
someText
, let's say with
title
property of
ViewData
struct.

/// In didSet
someText = viewData?.title


which gives me following error:

TaskTableViewCell.swift:21:34: Value of optional type 'String?' not unwrapped; did you mean to use '!' or '?'?


Which is weird, because there is no optional String in either
TaskTableViewCell
nor
ViewData
.
I can fix this with
someText = (viewData?.title)!

or
someText = viewData!.title

but I would like to avoid force-unwrapping.

Can you explain to me what's happening here?

And why compiler doesn't prints error when assigning to inherited property?

Answer
someText = viewData?.title

someText is not optional, property title in struct is not optional, but the instance of struct viewData is optional, so viewData's title is optional. So complier will give the error.

UILable's property text is an optional, default value is nil. So
textLabel!.text = viewData?.title is OK.

Comments