3

我见过几个需要定义委托的 Objective-C 代码示例。例如,在使用 MapKit 时,我看到如下语句:

[self.mapView.delegate self];

我有时也会看到以下内容:

[self.mapView setDelegate:self];

我仍然找到一些执行以下操作的示例:

self.mapView.delegate = self;

我知道第二个和第三个是如何等效的,但是我不明白第一个是如何运行的,更不用说编译了。我的意思是:self在这种情况下,一个有效的选择器如何?此代码如何转换为委托属性的赋值语句?

4

1 回答 1

11

self in [self.mapView.delegate self]; and [self.mapView setDelegate:self]; are different — yet related things. while the latter self represents the object in its scope it is used, [object self] is a method -(id)self defined in the NSObject protocol.

from the doc:

self
Returns the receiver. (required)

- (id)self 

Return Value The receiver.

Availability Available in OS X v10.0 and later.

As the NSObject class implements the NSObject protocol, nearly any object we use in our codes will understand this method.

A clue, what it useful for, gives us the GNUStep documentation:

self

- (id) self; 

Availability: OpenStep

Returns the receiver. In a proxy, this may (but is not required to) return the proxied object.

We can use it for proxies.
Also in KVC it can be useful that there is a method called self, as the operator needs a right key path, but actually the object itself is what we need:

NSArray *numbers = @[@1, @1, @2 ,@3, @5]
NSNumber* sum = [numbers valueForKeyPath: @"@sum.self"];

sum will be 12.


[self.mapView setDelegate:self]; and self.mapView.delegate = self; are equivalent and self sends for the object it is used in. Basically each Objective-C message translates to a C function, that takes at least two parameters. -setDelegate: would be translation in runtime to

void setDelegate(id self, SEL _cmd, id delegate)
{
    // implementation ....
} 

As you can see here, self is just the default name of the object passed in as the first parameter by the runtime and refers to the object of the class the method is defined on.

Although it is often referred as a keyword, self isn't. it is just a convention. As it is possible to construct Objective-C methods by using C functions, the Implementation IMP type and selector SEL type, you could decide to call the first object differently, like this if you would like to have C++ naming.

于 2014-05-18T18:27:32.263 回答