代码之家  ›  专栏  ›  技术社区  ›  Mark

Objective-C检测一个参数是否可以保留?

  •  0
  • Mark  · 技术社区  · 15 年前

    我正在运行一个参数列表,但是在这些参数中,值可以是从NSInteger、选择器到NSObjects的任何值。但如果它是NSObject,则需要正确地保留它。我不能简单地检查该类是否与NSObject相同,或者它是否响应retain方法,因为如果在选择器或整数上执行此操作,它就会崩溃。那你怎么还能做到呢?我不知道。

    我甚至试着在里面放一个@try@catch,如果没有,就试着保留它可能是一个不需要保留的对象。但它也会立即崩溃:(这里没有错误例外。


    object_getClass();
    

    但是当你超过一个NSInteger的时候它就崩溃了。


    看看NSInvocation类,你可以调用retainArguments方法,不幸的是,这也会使应用程序崩溃。但是在setArgument的描述中有一点奇怪:

    当参数值是一个对象时,传递一个指向要从中复制对象的变量(或内存)的指针

    这就意味着有一些东西可以检测出一个参数是否是一个对象,但是如何检测呢?


    - (void)addObserver:(NSObject *)observer selector:(SEL)selector arguments:(id)firstObj, ... {
        // Define signature
        NSMethodSignature *signature  = [[observer class] instanceMethodSignatureForSelector:selector];
        NSInvocation      *invocation = [NSInvocation invocationWithMethodSignature:signature];
    
        // Prepare invocation
        [invocation setTarget:observer];
        [invocation setSelector:selector];
    
        id        currentObject;
        va_list   argumentsList;
        NSInteger currentIndex = 2;
    
        if (firstObj) {
            va_start (argumentsList, firstObj);
            while (currentObject = va_arg(argumentsList, id)) {
                [invocation setArgument:&currentObject atIndex:currentIndex];
                currentIndex++;
            }
            va_end(argumentsList);
        }
    
        // The observer can easily be retained by doing [observer retain];
        // However the arguments may consist of NSIntegers etc. which really don't like
        // to be retained (logically). So I want to skip the argument that don't need
        // retaining.
    }
    

    目标

    我有一个随机的方法,比如:

    - (void)fetchFruitApples:(NSInteger)amount inRange:(NSRange)range withString:(NSString *)aString {
        //Can I fetch fruit? 
        //If so, execute method. 
        //If not wait for a certain event to occur (without blocking the main thread) 
        //Then retry this method with the arguments passed.
        //Thats why here I want to do [MyObject addObserver:self selector:@selector(fetchFruitApples:inRange:withString:) arguments:amount, range, aString, nil];
    }
    
    5 回复  |  直到 14 年前
        1
  •  0
  •   Kenny Winker    15 年前

    不如把你的数字作为NSNumber对象传递,这样你就可以确保你得到的一切都是一个对象,并且会对类似的东西做出响应 [arg retain] [arg isKindOfClass:[NSNumber class]]

        2
  •  0
  •   Kenny Winker    15 年前

    你所说的目标让我觉得你应该探索一下NSOperationQueue。

    “这就引出了下一点NSOperation依赖关系。到目前为止,nshread还没有用于添加依赖项的内置机制。但是,对于操作的依赖关系,使用了NSVOID操作机制。因此,让我们进入NSOperationQueue…”

    http://cocoasamurai.blogspot.com/2008/04/guide-to-threading-on-leopard.html

        3
  •  0
  •   PeyloW    15 年前

    可能是最简单的解决方案:

    [myInvocation setRetainArguments:YES];
    

    这将告诉调用实例保留您设置的任何对象参数。所以从你的角度看根本没有工作。

    -[NSMethodSignature getArgumentTypeAtIndex:] . 它将返回一个 char * 类型的编码格式与 @encode() 使用。可以这样使用:

    char* type = [myMethodSignature getArgumentTypeAtIndex:3];
    if (strcmp(type, @encode(id)) == 0) {
      // It is an object!
    }
    

    NSInvocation

    我已经写过关于这个主题的博客,完整的源代码可以从这里获得: http://blog.jayway.com/2010/03/30/performing-any-selector-on-the-main-thread/

    还有更多: http://blog.jayway.com/2010/08/19/future-cocoa-operation/

        4
  •  0
  •   Stephen Darlington    15 年前

    [NSString stringWithFormat:] . 调用者总是知道正确的类型,那么为什么不让它传递这些信息呢?

    - (void)addObserver:(NSObject *)observer selector:(SEL)selector argumentFormat:(NSString*)format arguments:(id)firstObj, ... {
    
      // parse format
    
    }
    

    format 就像是: isS 这意味着第一个参数是一个整数,第二个参数是一个字符串,第三个参数是一个选择器(即,保留第二个参数,但不保留其他两个参数)。

        5
  •  0
  •   Mark    15 年前

    经过一天的艰苦努力,我终于找到了解决问题的办法,特别感谢佩洛给我指出了正确的方向。阅读他的博客: http://blog.jayway.com/2010/03/30/performing-any-selector-on-the-main-thread/

    关键是:

    const char *type   = [signature getArgumentTypeAtIndex:index];
    NSString *dataType = [[[NSString alloc] initWithCString:type] autorelease];
    if ([dataType isEqualToString:@"@"]) // The argument is an object!