【问题标题】:Understanding @weakify macro了解@weakify 宏
【发布时间】:2016-03-15 02:35:46
【问题描述】:

@weakify 如何在幕后工作?使用 @weakify(self) 的想法是让它作为这个的简写:

__weak __typeof__(self) weakSelf = self;

注意:@weakify 宏定义为here

我试图通过收集它使用的所有宏来了解它的工作原理:

#define weakify(...) \
            ext_keywordify \
            metamacro_foreach_cxt(ext_weakify_,, __weak, __VA_ARGS__)

#define ext_weakify_(INDEX, CONTEXT, VAR) \
    CONTEXT __typeof__(VAR) metamacro_concat(VAR, _weak_) = (VAR);

#define metamacro_foreach_cxt(MACRO, SEP, CONTEXT, ...) \
        metamacro_concat(metamacro_foreach_cxt, metamacro_argcount(__VA_ARGS__))(MACRO, SEP, CONTEXT, __VA_ARGS__)

#define metamacro_argcount(...) \
        metamacro_at(20, __VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)


#define metamacro_concat(A, B) \
        metamacro_concat_(A, B)

#define metamacro_concat_(A, B) A ## B

#define metamacro_foreach_cxt1(MACRO, SEP, CONTEXT, _0) MACRO(0, CONTEXT, _0)

#define metamacro_at(N, ...) \
        metamacro_concat(metamacro_at, N)(__VA_ARGS__)

#define metamacro_head(...) \
        metamacro_head_(__VA_ARGS__, 0)

#define metamacro_head_(FIRST, ...) FIRST

#define metamacro_at0(...) metamacro_head(__VA_ARGS__)
#define metamacro_at1(_0, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at2(_0, _1, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at3(_0, _1, _2, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at4(_0, _1, _2, _3, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at5(_0, _1, _2, _3, _4, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at6(_0, _1, _2, _3, _4, _5, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at7(_0, _1, _2, _3, _4, _5, _6, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at8(_0, _1, _2, _3, _4, _5, _6, _7, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at9(_0, _1, _2, _3, _4, _5, _6, _7, _8, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at10(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at11(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at12(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at13(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at14(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at15(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at17(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at18(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at19(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at20(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, ...) metamacro_head(__VA_ARGS__)

#if DEBUG
#define ext_keywordify autoreleasepool {}
#else
#define ext_keywordify try {} @catch (...) {}
#endif

我将上面和下面的整个代码放入一个 .c 文件中:

@weakify(self)

并使用 gcc -E test.c 编译它。

我得到的输出是:

@try {} @catch (...) {} __attribute__((objc_gc(weak))) __typeof__(self) self_weak_ = (self);

问题:

鉴于宏生成的输出是self_weak_。在使用@weakify(self)的普通代码中,self在weakify()调用后仍然是直接引用的,那么self的使用是如何变成weak self的?不使用 self_weak_?

例如,我经常看到这种情况:

 @weakify(self)
 [[self.obj doSomething];

self.obj 如何使用弱自身?代码不应该是:

 @weakify(self)
 [[self_weak_.obj doSomething];

【问题讨论】:

标签: objective-c memory-management macros automatic-ref-counting weak-references


【解决方案1】:

如果您使用

转储 clang 预定义宏
clang -dM -E -x c /dev/null

你会发现

#define __weak __attribute__((objc_gc(weak)))

因此,如果您在源代码中写 __weak,这将扩展为 clang 属性objc_gc(weak)。换句话说,

@try {} @catch (...) {} __attribute__((objc_gc(weak))) __typeof__(self) self_weak_ = (self);

等价于

@try {} @catch (...) {} __weak __typeof__(self) self_weak_ = (self);

现在@try {} @catch (...) {} 是一个空操作(定义一个 似乎@字符开头的宏,比较How can I use commercial at sign in Objective-C macro?), 所以剩下的就是

__weak __typeof__(self) self_weak_ = (self);

这是定义和初始化弱变量self_weak_ 指向self 指向的同一对象的标准。

@weakify 与其对应的@strongify 一起使用, 例如:

@weakify(self);
// Expands to:
// __weak __typeof__(self) self_weak_ = (self);

void (^someClosure)(void) = ^void () {

    @strongify(self);
    // Expands to:
    // __strong __typeof__(self) self = (self_weak_);

    if (self) {
        [self doSomething];
        [self doSomethingElse];
    }
};

在闭包内部,self 是一个 local 变量并初始化为 如果该对象仍然存在,则对该对象的强引用。 如果对象同时被释放(因为没有强 对它的引用不再存在),self_weak_nil 和局部变量 self 也是 nil

【讨论】:

  • 谢谢。问题通常是使用弱化的代码继续引用自我。如何使用weakify使self指向弱自己?
  • @Boon:对不起,我不明白。 self_weak_ 被初始化为self,所以self_weak_ 是对self 指向的同一对象的弱引用。
  • 抱歉给您带来了困惑 - 让我举个例子。
  • 在问题末尾添加示例。
  • @Boon:在你的例子中,[[self.obj doSomething]; not 指的是弱指针。但请注意,还有另一个宏 @strongify,并且 创建了与原始名称相同的强局部变量,在您的情况下为 self
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-05
  • 2014-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多