Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can Apple declare optional protocol funcs without @objc, and unowned optional variables, but I can't?

Tags:

ios

swift

I am not sure about how to declare delegate in swift. So I checked Apple's UITableView's code (by command + click on the UITableView in XCode), and find something strange.

Following is the declare of the delegate of a UITableView:

enter image description here

The delegate is a unowned(unsafe) optional value, but according to Apple's doc:

enter image description here

It is said that

an unowned reference is assumed to always have a value

However, a delegate can of course be nil, i.e. does not have a value. In fact, the delegate is declared as UITableViewDelegate?, which is an optional value. Isn't there a problem?

Moreover, following is the declaration of UITableViewDelegate:

enter image description here

Obviously there are several optional functions. According to Apple's doc:

enter image description here

It is said that

Optional protocol requirements can only be specified if your protocol is marked with the @objc attribute

However, the UITableViewDelegate is not marked as @objc. Isn't there a problem?

Following is the code I tried to copy Apple's way to define protocol and delegate:

protocol CSImagePickerDelegate : NSObjectProtocol {
    optional func imagerPickerDidPickImage(picker: CSImagePicker, image: UIImage)
}

class CSImagePicker: UIViewController {

    unowned(unsafe) var delegate: CSImagePickerDelegate?

}

Unsurprisingly, two error occurs:

enter image description here

So my question is, why can Apple do this by I can't?

BTW, what is the correct way to declare delegate? I guess I should use

weak var delegate: SomeDelegate?

Right?

like image 425
HanXu Avatar asked Oct 25 '14 04:10

HanXu


1 Answers

The UIKit interfaces you see are not actual Swift implementations— they're just declarations that expose ObjC APIs to Swift and describe their behavior in Swift terms.

The @objc attribute exposes a Swift symbol to the ObjC runtime. You don't see @objc on these because they're imported from ObjC.

You see unowned(unsafe) on properties that are marked assign in ObjC. These are, as the name suggests, unsafe: ARC doesn't retain the object, and it doesn't make sure the reference gets reset to nil if the object goes away. Most of these are delegates that predate ARC and for whatever reason (binary compatibility, maybe?) never got changed to ARC weak references.

So, don't expect the kit to show you idiomatic Swift that you can imitate. Your deduction is correct: to make your own delegate property in Swift, declare it like this:

weak var delegate: SomeDelegate?
like image 122
rickster Avatar answered Oct 21 '22 03:10

rickster