Informal Protocols

6 篇文章 0 订阅

Informal Protocols

You may occasionally see, online or in the documentation, a reference to aninformal protocol. An informal protocol isn’t really a protocol at all; it’s just a way of providing the compiler with a method signature so that it will allow a message to be sent without complaining.

There are two complementary ways to implement an informal protocol. One is to define a category on NSObject; this makes any object eligible to receive the messages listed in the category. The other is to define a protocol to which no class formally conforms; instead, send any message listed in the protocol only to objects typed as id, thus suppressing any possible objections from the compiler.  ??

These techniques were widespread before protocols could declare methods as optional; now they are largely unnecessary. (They are still used, but decreasingly so; in iOS 7 very few informal protocols remain.) They are also mildly dangerous, because you might accidentally define a method with the same name as an existing method but a different signature, with unpredictable results.

Optional Methods

A protocol can explicitly designate some or all of its methods as optional. The question thus arises: How, in practice, is such an optional method feasible? We know that if a message is sent to an object and the object can’t handle that message, an exception is raised and your app will likely crash. But a method declaration is a contract suggesting that the objectcan handle that message. If we subvert that contract by declaring a method that might or might not be implemented, aren’t we inviting crashes?

The answer is that Objective-C is not only dynamic but also introspective. You can ask an object whether it can really deal with a message without actually sending it that message. The key method here is NSObject’s respondsToSelector:, which takes a selector parameter and returns a BOOL. With it, you can send a message to an object only if it would be safe to do so:

MyClass* mc = [MyClass new];

if ([mc respondsToSelector:@selector(woohoo)]) {

    [mc woohoo];

}

You wouldn’t want to do this before sending just any old message, because it isn’t necessary except for optional methods, and it slows things down a little. But Cocoa does in fact call respondsToSelector: on your objectsas a matter of course. To see that this is true, implement respondsToSelector: on AppDelegate in our Empty Window project and instrument it with logging:

- (BOOL) respondsToSelector: (SEL) sel {

    NSLog(@"%@", NSStringFromSelector(sel));

    return [super respondsToSelector:(sel)];

}

The output on my machine, as the Empty Window app launches, includes the following (I’m omitting private methods and multiple calls to the same method):

application:handleOpenURL:

application:openURL:sourceApplication:annotation:

applicationDidReceiveMemoryWarning:

applicationWillTerminate:

applicationSignificantTimeChange:

application:willChangeStatusBarOrientation:duration:

application:didChangeStatusBarOrientation:

application:willChangeStatusBarFrame:

application:didChangeStatusBarFrame:

application:deviceAccelerated:

application:deviceChangedOrientation:

applicationDidBecomeActive:

applicationWillResignActive:

applicationDidEnterBackground:

applicationWillEnterForeground:

applicationWillSuspend:

application:didResumeWithOptions:

application:shouldSaveApplicationState:

application:supportedInterfaceOrientationsForWindow:

application:performFetchWithCompletionHandler:

application:didReceiveRemoteNotification:fetchCompletionHandler:

application:willFinishLaunchingWithOptions:

application:didFinishLaunchingWithOptions:

That’s Cocoa, checking to see which of the optional UIApplicationDelegate protocol methods (including a couple of undocumented methods) are actually implemented by our AppDelegate instance — which, because it is the UIApplication object’s delegate and formally conforms to the UIApplicationDelegate protocol, has explicitly agreed that itmight be willing to respond to any of those messages. The entire delegate pattern (Chapter 11) depends upon this technique. Observe the policy followed here by Cocoa: it checks all the optional protocol methods once, when it first meets the object in question, and presumably stores the results; thus, the app is slowed a tiny bit by this one-time initialbombardment of respondsToSelector: calls, but now Cocoa knows all the answers and won’t have to perform any of these same checks on the same object later.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值