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

目标C安全铸造宏

  •  6
  • LandonSchropp  · 技术社区  · 14 年前

    我在Objective-C中编写了一个宏来执行安全强制转换。以下是目前为止的情况:

    #define SAFE_CAST(OBJECT, TYPE) ([OBJECT isKindOfClass:[TYPE class]] ? (TYPE *) OBJECT: nil)
    

    这真的很好,但是如果有一种方法可以将对象存储在变量中,这样就不会被调用两次。例如,使用宏如下:

    NSString *str = SAFE_CAST([dictinary objectForKey:key], NSString);
    

    当宏展开时,会产生与此类似的代码:

    NSString *str = ([[dictinary objectForKey:key] isKindOfClass:[NSString class]] ? (NSString *) [dictinary objectForKey:key]: nil);
    

    我希望它能像这样工作:

    id obj = [dictionary objectForKey:key];
    NSString *str = ([obj objectForKey:key] isKindOfClass[NSString class]] ? (NSString *) obj : nil);
    

    谢谢。

    3 回复  |  直到 14 年前
        1
  •  9
  •   Yuji    14 年前

    您可以使用一个名为语句的GCC扩展 statement expressions 拥有

    #define SAFE_CAST(OBJECT, TYPE) ({ id obj=OBJECT;[obj isKindOfClass:[TYPE class]] ? (TYPE *) obj: nil; })
    

    也就是说,我认为在你需要使用的情况下使用这种方法通常是一种糟糕的方法。 SAFE_CAST 很多。 不要将不同类的对象放入数组中;不要重复使用操作消息 (IBAction)someAction:(id)sender 对于不同类的UI对象。那么你通常不需要使用 安全铸件 .

        2
  •  4
  •   Georg Fritzsche    14 年前

    如果您真的认为必须这样做,您可以使用一个函数:

    #define SAFE_CAST(Object, Type) (Type *)cast_helper(Object, [Type class])
    static id cast_helper(id x, Class c) {
        return [x isKindOfClass:c] ? x : nil;
    }
    
        3
  •  0
  •   jer    14 年前

    这样写吧,只要用do while(0)<-把它包装起来,而不只是用括号。

    #define SAFE_CAST(OBJECT, TYPE, VAR) do { \
        id obj = OBJECT; \
        VAR = [obj isKindOfClass:[TYPE class]] ? (TYPE *) obj : nil; \
    } while(0)