运行时编程动态方法时使用ARC编译错误 [英] Error compiling with ARC when runtime programming dynamic method

查看:124
本文介绍了运行时编程动态方法时使用ARC编译错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在Objective-C上做一些运行时编程。
为了做到这一点我覆盖了 resolveClassMethod 方法。



不幸的是我想出了一些编译错误,活动:


错误:选择器'dynamic'没有已知的类方法


如果我使用gcc或clang没有ARC( -fno-objc-arc 选项传递),一切正常,除了警告而不是错误。



我知道ARC需要知道调用的方法的名称,以了解如何使用返回值管理内存(以下方法名称约定)。但是如何在没有丑陋的 performSelector 调用而不是直接方法调用的情况下解决这个问题?



这是我的代码:



Test.m

  #importTest.h 
#import< objc / runtime.h>

NSString * dynamicImp(id slef,SEL _cmd)
{
NSLog(@Dynamic method called);
return @dynamicImp;
}

@implementation Test

- (NSString *)name
{
return @John
}

+(BOOL)resolveClassMethod:(SEL)name
{
if(name == @selector(dynamic))
{
Class metaClass = objc_getMetaClass([NSStringFromClass([self class])UTF8String]);
class_addMethod(metaClass,name,(IMP)dynamicImp,@@:);
return YES;
}
return NO;
}

+(IMP)methodForSelector:(SEL)aSelector
{
if(aSelector == @selector(dynamic))
{
return(IMP)dynamicImp;
}
else
{
return [super methodForSelector:aSelector];
}
}

- (BOOL)responsesToSelector:(SEL)aSelector
{
if(aSelector == @selector(dynamic))
{
return YES;
}
else
{
return [NSObject respondingToSelector:aSelector];
}
}

@end

strong> Test.h

  #import< Cocoa / Cocoa.h> 

@interface测试:NSObject< NSObject> {
NSString * _name;
}

- (NSString *)name;

@end

main.m / p>

  #import< Cocoa / Cocoa.h> 
#import< stdio.h>
#importTest.h

int main(int argc,char * argv [])
{
@autoreleasepool {
Test * test = [[Test alloc] init];
NSLog(@Hello,%@,[test name]);
NSLog(@How are you,%@,[Test dynamic]);
}
return 0;
}

没有ARC的GCC或铛

编译结果




main.m:13:36:警告:类方法'+动态'未找到(返回类型
默认为'id')

  NSLog 你好,%@,[测试动态]); 


输出

b
$ b


2012-10-22 10:33:15.563 test-clang [957:707]你好,约翰2012-10-22



2012-10-22 10:33:15.565 test-clang [957:707]动态方法调用2012-10-22



2012 -10-22 10:33:15.565 test-clang [957:707]你好吗,dynamicImp


ARC



编辑结果




main.m:13:36:error:没有已知的用于选择器'dynamic'的类方法

  NSLog你,%@,[测试动态]); 


解决方案

在您的通话中

  NSLog(@How are you,%@,[Test dynamic]); 

ARC编译器不知道方法的返回类型。但ARC需要知道该方法是否返回一个对象来添加适当的 retain / release 调用来管理生命周期。



即使没有ARC,也会收到编译器警告


'not found(return type defaults to'id')


但ARC编译器更严格。



您可以致电

  NSLog(@How are you,%@,[[Test class] performSelector:@selector(dynamic)]); 

因为 performSelector 返回 id 。对于返回对象以外的任何函数的函数,您可以使用 NSInvocation



$ c>动态方法:

  @interface测试(DynamicMethods)
+(NSString *)dynamic;
@end


I am trying to do some runtime programmation on Objective-C. In order to do this I override the resolveClassMethod method.

Unfortunately I come up with some compilation error with clang when ARC is active :

error: no known class method for selector 'dynamic'

Everything works fine if I use gcc or clang without ARC (-fno-objc-arc option passed), except a warning instead of the error.

I am aware that ARC need to know the name of the method called to figure out how to manage the memory with returned value (following method name convention). But how to this issue without an ugly performSelector call instead of a direct method call ?

Here is my code :

Test.m

#import "Test.h"
#import <objc/runtime.h>

NSString* dynamicImp(id slef, SEL _cmd)
{
    NSLog(@"Dynamic method called");
    return @"dynamicImp";
}

@implementation Test

- (NSString*)name
{
    return @"John";
}

+ (BOOL)resolveClassMethod:(SEL)name
{
    if (name == @selector(dynamic))
    {
        Class metaClass = objc_getMetaClass([NSStringFromClass([self class]) UTF8String]);
        class_addMethod(metaClass, name, (IMP) dynamicImp, "@@:");
        return YES;
    }
    return NO;
}

+ (IMP)methodForSelector:(SEL)aSelector
{
    if (aSelector == @selector(dynamic))
    {
        return (IMP) dynamicImp;
    }
    else
    {
        return [super methodForSelector:aSelector];
    }
}

- (BOOL)respondsToSelector:(SEL)aSelector
{
    if (aSelector == @selector(dynamic))
    {
        return YES;
    }
    else
    {
        return [NSObject respondsToSelector:aSelector];
    }
}

@end

Test.h

#import <Cocoa/Cocoa.h>

@interface Test : NSObject <NSObject> {
    NSString *_name;
}

- (NSString*)name;

@end

main.m

#import <Cocoa/Cocoa.h>
#import <stdio.h>
#import "Test.h"

int main(int argc, char* argv[])
{
    @autoreleasepool {
        Test *test = [[Test alloc] init];
        NSLog(@"Hello, %@", [test name]);
        NSLog(@"How are you , %@", [Test dynamic]);
    }
    return 0;
}

Gcc or clang without ARC

Compilation result

main.m:13:36: warning: class method '+dynamic' not found (return type defaults to 'id')

    NSLog(@"How are you , %@", [Test dynamic]);

Output

2012-10-22 10:33:15.563 test-clang[957:707] Hello, John 2012-10-22

2012-10-22 10:33:15.565 test-clang[957:707] Dynamic method called 2012-10-22

2012-10-22 10:33:15.565 test-clang[957:707] How are you , dynamicImp

Clang with ARC

Compilation result

main.m:13:36: error: no known class method for selector 'dynamic'

    NSLog(@"How are you , %@", [Test dynamic]);

PS : I didn't care for the moment on memory management as my goal is to compile this code with ARC activated.

解决方案

In your call

NSLog(@"How are you , %@", [Test dynamic]);

the ARC compiler does not know the return type of the method. But ARC needs to know if the method returns an object to add the appropriate retain/release calls for managing the lifetime.

Even without ARC you get a compiler warning

class method '+dynamic' not found (return type defaults to 'id')

but the ARC compiler is more strict.

You can call

NSLog(@"How are you , %@", [[Test class] performSelector:@selector(dynamic)]);

because performSelector returns an id. For functions returning anything other than an object you can use NSInvocation.

Alternatively, you can declare the dynamic method using a Class Extension:

@interface Test (DynamicMethods)
+ (NSString *)dynamic;
@end

这篇关于运行时编程动态方法时使用ARC编译错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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