Senseful Senseful - 7 months ago 9
Swift Question

What if I want to assign a property to itself?

If I attempt to run the following code:

photographer = photographer


I get the error: "Assigning a property to itself."




I want to run this code is because the
photographer
property has a
didSet
block declared, and I want to force that code to run.

Here's a real-life example: In the "16. Segues and Text Fields" lecture of the Winter 2013 Stanford iOS course (13:20), the professor recommends writing code similar to the following:

@IBOutlet weak var photographerLabel: UILabel!

var photographer: Photographer? {
didSet {
self.title = photographer.name
if isViewLoaded() { reload() }
}
}

override func viewDidLoad() {
super.viewDidLoad()
reload()
}

func reload() {
photographerLabel.text = photographer.name
}


Note: I made the following changes: (1) the code was switched from Objective-C to Swift; (2) because it's in Swift, I use the
didSet
block of the property instead of the
setPhotographer:
method; (3) instead of
self.view.window
I am using
isViewLoaded
because the former erroneously forces the view to load upon access of the
view
property; (4) the
reload()
method (only) updates a label for simplicity purposes, and because it resembles my code more closely; (5) the photographer
IBOutlet
label was added to support this simpler code; (6) since I'm using Swift, the
isViewLoaded()
check no longer exists simply for performance reasons, it is now required to prevent a crash, since the IBOutlet is defined as
UILabel!
and not
UILabel?
so attempting to access it before the view is loaded will crash the application; this wasn't mandatory in Objective-C since it uses the null object pattern.

The reason we call reload twice is because we don't know if the property will be set before or after the view is created. For example, the user might first set the property, then present the view controller, or they might present the view controller, and then update the property.

I like how this property is agnostic as to when the view is loaded (it's best not to make any assumptions about view loading time), so I want to use this same pattern (only slightly modified) in my own code:

@IBOutlet weak var photographerLabel: UILabel?

var photographer: Photographer? {
didSet {
photographerLabel?.text = photographer.name
}
}

override func viewDidLoad() {
super.viewDidLoad()
photographer = photographer
}


Here instead of creating a new method to be called from two places, I just want the code in the
didSet
block. I want
viewDidLoad
to force the
didSet
to be called, so I assign the property to itself. Swift doesn't allow me to do that, though. How can I force the
didSet
to be called?

Answer

To assign property name to itself, just do:

name = (name)

This is just too fun not to be shared. I'm sure the community can come up with many more ways to do this, the crazier the better

class Test {
    var name: String? {
        didSet {
            print("It was set")
        }
    }

    func testit() {
        name = (name)
        (name) = name
        (name) = (name)
        name = [name][0]
        name = [name].last!
        name = [name].first!
        name = [1:name][1]!
        name = name ?? nil
        name = nil ?? name
        name = {self.name}()
        name = Optional(name)!
        name = ImplicitlyUnwrappedOptional(name)
        name = true ? name : name
        name = false ? name : name
        let temp = name; name = temp
        name = name as Any as? String
    }
}

let test = Test()
test.testit()