转自http://blog.youkuaiyun.com/dean19900504/article/details/8737862
SMethodSignature顾名思义应该就是“方法签名”,类似于C++中的编译器时的函数签名。
官方定义该类为对方法的参数、返回类似进行封装,协同NSInvocation实现消息转发。
通过消息转发可以用B实现A的方法。也是一种多重继承的解决方法。
<p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"><span class="kwd" style="color: rgb(0, 0, 136);">interface</span><span class="pln"> </span><span class="typ" style="color: rgb(102, 0, 102);">LOCBird</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">:</span><span class="pln"> </span><span class="typ" style="color: rgb(102, 0, 102);">NSObject</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">{</span>
<span class="pln"> </span><span class="typ" style="color: rgb(102, 0, 102);">NSString</span><span class="pun" style="color: rgb(102, 102, 0);">*</span><span class="pln"> name_</span><span class="pun" style="color: rgb(102, 102, 0);">;</span>
<span class="pln"> </span>
<span class="pun" style="color: rgb(102, 102, 0);">}</span>
<span class="lit" style="color: rgb(0, 102, 102);">@end</span>
<span class="lit" style="color: rgb(0, 102, 102);">@implementation</span><span class="pln"> </span><span class="typ" style="color: rgb(102, 0, 102);">LOCBird</span>
<span class="pun" style="color: rgb(102, 102, 0);">-</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln">id</span><span class="pun" style="color: rgb(102, 102, 0);">)</span><span class="pln">init</span>
<span class="pun" style="color: rgb(102, 102, 0);">{</span>
<span class="pln"> </span><span class="kwd" style="color: rgb(0, 0, 136);">self</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">[</span><span class="kwd" style="color: rgb(0, 0, 136);">super</span><span class="pln"> init</span><span class="pun" style="color: rgb(102, 102, 0);">];</span>
<span class="pln"> </span><span class="kwd" style="color: rgb(0, 0, 136);">if</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="kwd" style="color: rgb(0, 0, 136);">self</span><span class="pun" style="color: rgb(102, 102, 0);">)</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">{</span>
<span class="pln"> name_ </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">[[</span><span class="typ" style="color: rgb(102, 0, 102);">NSString</span><span class="pln"> alloc</span><span class="pun" style="color: rgb(102, 102, 0);">]</span><span class="pln"> initWithString</span><span class="pun" style="color: rgb(102, 102, 0);">:@</span><span class="str" style="color: rgb(0, 136, 0);">"I am a Bird!!"</span><span class="pun" style="color: rgb(102, 102, 0);">];</span>
<span class="pln"> </span>
<span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">}</span>
<span class="pln"> </span><span class="kwd" style="color: rgb(0, 0, 136);">return</span><span class="pln"> </span><span class="kwd" style="color: rgb(0, 0, 136);">self</span><span class="pun" style="color: rgb(102, 102, 0);">;</span>
<span class="pun" style="color: rgb(102, 102, 0);">}</span>
<span class="pun" style="color: rgb(102, 102, 0);">-</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="kwd" style="color: rgb(0, 0, 136);">void</span><span class="pun" style="color: rgb(102, 102, 0);">)</span><span class="pln">dealloc</span>
<span class="pun" style="color: rgb(102, 102, 0);">{</span>
<span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">[</span><span class="pln">name_ release</span><span class="pun" style="color: rgb(102, 102, 0);">];</span>
<span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">[</span><span class="kwd" style="color: rgb(0, 0, 136);">super</span><span class="pln"> dealloc</span><span class="pun" style="color: rgb(102, 102, 0);">];</span>
<span class="pun" style="color: rgb(102, 102, 0);">}</span>
<span class="pun" style="color: rgb(102, 102, 0);">-</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="typ" style="color: rgb(102, 0, 102);">NSMethodSignature</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">*)</span><span class="pln">methodSignatureForSelector</span><span class="pun" style="color: rgb(102, 102, 0);">:(</span><span class="pln">SEL</span><span class="pun" style="color: rgb(102, 102, 0);">)</span><span class="pln">aSelector</span>
<span class="pun" style="color: rgb(102, 102, 0);">{</span>
<span class="pln"> </span><span class="typ" style="color: rgb(102, 0, 102);">NSMethodSignature</span><span class="pun" style="color: rgb(102, 102, 0);">*</span><span class="pln"> signature </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">[</span><span class="kwd" style="color: rgb(0, 0, 136);">super</span><span class="pln"> methodSignatureForSelector</span><span class="pun" style="color: rgb(102, 102, 0);">:</span><span class="pln">aSelector</span><span class="pun" style="color: rgb(102, 102, 0);">];</span>
<span class="pln"> </span><span class="kwd" style="color: rgb(0, 0, 136);">if</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln">signature</span><span class="pun" style="color: rgb(102, 102, 0);">==</span><span class="kwd" style="color: rgb(0, 0, 136);">nil</span><span class="pun" style="color: rgb(102, 102, 0);">)</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">{</span>
<span class="pln"> signature </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">[</span><span class="pln">name_ methodSignatureForSelector</span><span class="pun" style="color: rgb(102, 102, 0);">:</span><span class="pln">aSelector</span><span class="pun" style="color: rgb(102, 102, 0);">];</span>
<span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">}</span>
<span class="pln"> </span><span class="typ" style="color: rgb(102, 0, 102);">NSUInteger</span><span class="pln"> argCount </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">[</span><span class="pln">signature numberOfArguments</span><span class="pun" style="color: rgb(102, 102, 0);">];</span>
<span class="pln"> </span><span class="kwd" style="color: rgb(0, 0, 136);">for</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="typ" style="color: rgb(102, 0, 102);">NSInteger</span><span class="pln"> i</span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="lit" style="color: rgb(0, 102, 102);">0</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">;</span><span class="pln"> i</span><span class="pun" style="color: rgb(102, 102, 0);"><</span><span class="pln">argCount </span><span class="pun" style="color: rgb(102, 102, 0);">;</span><span class="pln"> i</span><span class="pun" style="color: rgb(102, 102, 0);">++)</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">{</span>
<span class="pln"> </span><span class="typ" style="color: rgb(102, 0, 102);">NSLog</span><span class="pun" style="color: rgb(102, 102, 0);">(@</span><span class="str" style="color: rgb(0, 136, 0);">"%s"</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">[</span><span class="pln">signature getArgumentTypeAtIndex</span><span class="pun" style="color: rgb(102, 102, 0);">:</span><span class="pln">i</span><span class="pun" style="color: rgb(102, 102, 0);">]);</span>
<span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">}</span>
<span class="pln"> </span><span class="typ" style="color: rgb(102, 0, 102);">NSLog</span><span class="pun" style="color: rgb(102, 102, 0);">(@</span><span class="str" style="color: rgb(0, 136, 0);">"returnType:%s ,returnLen:%d"</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">[</span><span class="pln">signature methodReturnType</span><span class="pun" style="color: rgb(102, 102, 0);">]</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">[</span><span class="pln">signature methodReturnLength</span><span class="pun" style="color: rgb(102, 102, 0);">]);</span>
<span class="pln"> </span><span class="typ" style="color: rgb(102, 0, 102);">NSLog</span><span class="pun" style="color: rgb(102, 102, 0);">(@</span><span class="str" style="color: rgb(0, 136, 0);">"signature:%@"</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln"> signature</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pln"> </span><span class="kwd" style="color: rgb(0, 0, 136);">return</span><span class="pln"> signature</span><span class="pun" style="color: rgb(102, 102, 0);">;</span>
<span class="pun" style="color: rgb(102, 102, 0);">}</span>
<span class="pun" style="color: rgb(102, 102, 0);">-</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="kwd" style="color: rgb(0, 0, 136);">void</span><span class="pun" style="color: rgb(102, 102, 0);">)</span><span class="pln">forwardInvocation</span><span class="pun" style="color: rgb(102, 102, 0);">:(</span><span class="typ" style="color: rgb(102, 0, 102);">NSInvocation</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">*)</span><span class="pln">anInvocation</span>
<span class="pun" style="color: rgb(102, 102, 0);">{</span>
<span class="pln"> </span><span class="typ" style="color: rgb(102, 0, 102);">NSLog</span><span class="pun" style="color: rgb(102, 102, 0);">(@</span><span class="str" style="color: rgb(0, 136, 0);">"forwardInvocation:%@"</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln"> anInvocation</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pln"> SEL seletor </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">[</span><span class="pln">anInvocation selector</span><span class="pun" style="color: rgb(102, 102, 0);">];</span>
<span class="pln"> </span><span class="kwd" style="color: rgb(0, 0, 136);">if</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">([</span><span class="pln">name_ respondsToSelector</span><span class="pun" style="color: rgb(102, 102, 0);">:</span><span class="pln">seletor</span><span class="pun" style="color: rgb(102, 102, 0);">])</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">{</span>
<span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">[</span><span class="pln">anInvocation invokeWithTarget</span><span class="pun" style="color: rgb(102, 102, 0);">:</span><span class="pln">name_</span><span class="pun" style="color: rgb(102, 102, 0);">];</span>
<span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">}</span>
<span class="pln"> </span>
<span class="pun" style="color: rgb(102, 102, 0);">}</span>
<span class="lit" style="color: rgb(0, 102, 102);">@end</span></p><p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;">
</p><p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"><span class="com" style="color: rgb(136, 0, 0);">//调用</span></p><p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"><span class="com" style="color: rgb(136, 0, 0);"> id bird = [[LOCBird alloc] init];</span>
<span class="pln"> </span><span class="typ" style="color: rgb(102, 0, 102);">NSLog</span><span class="pun" style="color: rgb(102, 102, 0);">(@</span><span class="str" style="color: rgb(0, 136, 0);">"len= %d"</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">[</span><span class="pln">bird length</span><span class="pun" style="color: rgb(102, 102, 0);">]);</span></p>输出 参考
| 编码 | 含义 |
|---|---|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | C++标准的 |
| | |
| | 字符串( |
| | 对象(无论是静态指定的还是通过 |
| | 类( |
| | 方法选标( |
| [array type] | 数组 |
| {name=type...} | 结构体 |
| (name=type...) | 联合体 |
| | num个bit的位域 |
| | type类型的指针 |
| | 未知类型(其它时候,一般用来指函数指针) |
使用方法
<p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"><span class="pun" style="color: rgb(102, 102, 0);">-(</span><span class="kwd" style="color: rgb(0, 0, 136);">void</span><span class="pun" style="color: rgb(102, 102, 0);">)</span><span class="pln"> initWithTarget</span><span class="pun" style="color: rgb(102, 102, 0);">:(</span><span class="pln">id</span><span class="pun" style="color: rgb(102, 102, 0);">)</span><span class="pln"> rec selector</span><span class="pun" style="color: rgb(102, 102, 0);">:(</span><span class="pln">SEL</span><span class="pun" style="color: rgb(102, 102, 0);">)</span><span class="pln"> cb</span><span class="pun" style="color: rgb(102, 102, 0);">{</span>
<span class="pln"> anchorPoint_ </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln"> ccp</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="lit" style="color: rgb(0, 102, 102);">0.5f</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln"> </span><span class="lit" style="color: rgb(0, 102, 102);">0.5f</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pln"> </span><span class="typ" style="color: rgb(102, 0, 102);">NSMethodSignature</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">*</span><span class="pln"> sig </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln"> </span><span class="kwd" style="color: rgb(0, 0, 136);">nil</span><span class="pun" style="color: rgb(102, 102, 0);">;</span>
<span class="pln"> </span><span class="kwd" style="color: rgb(0, 0, 136);">if</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln"> rec </span><span class="pun" style="color: rgb(102, 102, 0);">&&</span><span class="pln"> cb </span><span class="pun" style="color: rgb(102, 102, 0);">)</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">{</span>
<span class="pln"> sig </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">[</span><span class="pln">rec methodSignatureForSelector</span><span class="pun" style="color: rgb(102, 102, 0);">:</span><span class="pln">cb</span><span class="pun" style="color: rgb(102, 102, 0);">];</span>
<span class="pln"> invocation </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln"> </span><span class="kwd" style="color: rgb(0, 0, 136);">nil</span><span class="pun" style="color: rgb(102, 102, 0);">;</span>
<span class="pln"> invocation </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">[</span><span class="typ" style="color: rgb(102, 0, 102);">NSInvocation</span><span class="pln"> invocationWithMethodSignature</span><span class="pun" style="color: rgb(102, 102, 0);">:</span><span class="pln">sig</span><span class="pun" style="color: rgb(102, 102, 0);">];</span>
<span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">[</span><span class="pln">invocation setTarget</span><span class="pun" style="color: rgb(102, 102, 0);">:</span><span class="pln">rec</span><span class="pun" style="color: rgb(102, 102, 0);">];</span>
<span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">[</span><span class="pln">invocation setSelector</span><span class="pun" style="color: rgb(102, 102, 0);">:</span><span class="pln">cb</span><span class="pun" style="color: rgb(102, 102, 0);">];</span>
<span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">[</span><span class="pln">invocation setArgument</span><span class="pun" style="color: rgb(102, 102, 0);">:&</span><span class="kwd" style="color: rgb(0, 0, 136);">self</span><span class="pln"> atIndex</span><span class="pun" style="color: rgb(102, 102, 0);">:</span><span class="lit" style="color: rgb(0, 102, 102);">2</span><span class="pun" style="color: rgb(102, 102, 0);">];</span>
<span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">[</span><span class="pln">invocation retain</span><span class="pun" style="color: rgb(102, 102, 0);">];</span>
<span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">}</span>
<span class="pun" style="color: rgb(102, 102, 0);">}</span></p>当
[invocation invoke
];是调用SEL。上述第二个参数为自身。
用
NSMethodSignature和
NSInvocation实现编码
- - (void)encodeWithCoder:(NSCoder *)encoder{
- NSDictionary *attrDic = [self getKeyAndObjectForDictionry];
- if (attrDic == nil) {
- return;
- }
- NSEnumerator *keyEnum = [attrDic keyEnumerator];
- id attributeName;
- while ((attributeName = [keyEnum nextObject])) {
- SEL getSel = NSSelectorFromString(attributeName);
- if ([self respondsToSelector:getSel]) {
- NSMethodSignature *signature = nil;
- signature = [self methodSignatureForSelector:getSel];
- NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
- [invocation setTarget:self];
- [invocation setSelector:getSel];
- NSObject *valueObj = nil;
- [invocation invoke];
- [invocation getReturnValue:&valueObj];
- if (valueObj) {
- [encoder encodeObject:valueObj forKey:attributeName];
- }
- }
- }
- }
本文介绍 Objective-C 中的消息转发机制,包括 SMethodSignature 的作用及其实现方式。通过 NSMethodSignature 和 NSInvocation 实现了对方法签名的封装,支持方法的动态调用和参数传递,展示了如何通过消息转发实现类的行为扩展。
208

被折叠的 条评论
为什么被折叠?



