Objective-C 前向调用: [英] Objective-C forwardInvocation:

查看:75
本文介绍了Objective-C 前向调用:的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我经常做这样的事情:

CoolViewController *coolViewController = [[CoolViewController alloc] init];
[self.navigationController pushViewController:coolViewController animated:YES];
[coolViewController release];

UINavigationController 的类别中,我如何覆盖 forwardInvocation: 以便我可以这样做:

How would I, in a category of UINavigationController, override forwardInvocation: so that I could just instead do:

[self.navigationController pushCoolViewControllerAnimated:YES];

  1. 请在您的答案中包含相关代码,而不仅仅是解释.谢谢!

  1. Please include the relevant code in your answer, not just an explanation. Thank you!

请随意评论这是否是好的做法.我也是出于教育目的而提出这个要求,但在我看来,在这种情况下,代码的简化可能会超过处理时间和处理时间方面不明显(正确?)的成本.内存使用情况.此外,我来自 Ruby 背景,喜欢使用动态编程来简化事情,例如 Rails 中的动态查找器(例如 find_by_name).

Feel free to comment on whether this is good practice. I'm also asking this for educational purposes, but it seems to me that in this case, the simplification in code may outweight the unnoticeable (correct?) cost in processing time & memory usage. Also, I come from a Ruby background and love to use dynamic programming to simplify things, e.g., dynamic finders (e.g., find_by_name) in Rails.

如果你可以实现 pushCoolViewControllerAnimated:withBlock 并在初始化视图控制器后调用块,允许我在创建的视图控制器上设置某些实例变量,那么奖励积分.

Bonus points if you could implement pushCoolViewControllerAnimated:withBlock and invoke the block after initializing the view controller, allowing me to set certain instance variables on the view controller created.

更新:我只记得 ARC 即将推出.所以这个具体的例子可能没有那么有用,但仍然是一个很好的练习/例子,可以在其他情况下使用,例如 Core Data & 的动态查找器.传递一个块来配置 NSFetchRequest.

UPDATE: I just remembered that ARC is coming soon. So this specific example may not be so helpful then, but still a great exercise/example that could be used in other cases, e.g., dynamic finders for Core Data & passing a block to configure the NSFetchRequest.

推荐答案

使用Objective-C Runtime Programming Guide中描述的动态方法解析机制,具体来说,+[NSObject resolveInstanceMethod:]:

Use the dynamic method resolution mechanism described in the Objective-C Runtime Programming Guide, specifically, +[NSObject resolveInstanceMethod:]:

@implementation UINavigationController (FWD)
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
    NSString *name = NSStringFromSelector(sel);
    NSString *prefix = @"push";
    NSString *suffix = @"Animated:";
    if ([name hasPrefix:prefix] && [name hasSuffix:suffix]) {
        NSRange classNameRange = {[prefix length],
            [name length] - [prefix length] - [suffix length]}
        NSString *className = [name substringWithRange:classNameRange];
        Class cls = NSClassFromString(className);
        if (cls) {
            IMP imp = imp_implementationWithBlock(
            ^(id me, BOOL animated) {
                id vc = [[cls alloc] init];
                [me pushViewController:vc animated:animated];
                [vc release];
            });
            class_addMethod(cls, sel, imp, "v@:c");
            return YES;
        }
    }
    return [super resolveInstanceMethod:sel];
}
@end

当然,如果UINavigationController 已经使用了+resolveInstanceMethod:,那么您现在已经破坏了它.在 UINavigationController 的子类中执行此操作,或使用方法 swizzling 启用调用原始实现,将解决该问题.

Of course, if UINavigationController already uses +resolveInstanceMethod:, you've now broken it. Doing this in a subclass of UINavigationController, or using method swizzling to enable invoking the original implementation, would solve that problem.

接受创建后块的版本是一个简单的扩展(更改块参数、更改类型编码、更改选择器名称模式以及提取预期类名称的方式).

The version accepting a post-creation block is a straightforward extension (change the block parameters, change the type encoding, change the selector name pattern and how you extract the intended class name).

这篇关于Objective-C 前向调用:的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆