8

クラスのインスタンス変数のどれが宣言されているかを知ることで恩恵を受けるツールを書いています__weak

この情報は実行時にどこかに存在する必要がありますが、文書化されているかどうかにかかわらず、それにアクセスする方法はありますか? (ツール用なのでアップデートで壊れてもあまり気にしません)

4

1 に答える 1

4

では、カスタム オブジェクトの実装を使用して、iVar が弱いかどうかを確認するための基本的なチェックを行うサンプル実装を次に示します。

BOOL iVarIsWeak(Class cls, Ivar ivar)
{
    id classInstance = [cls new];

    // our custom base class properly tracks reference counting, no weird voodoo
    id refCounter = [CustomBaseClass new];

    object_setIvar(classInstance, ivar, refCounter);

    if ([refCounter refCount] == 2)
    {
        return NO;
    }

    return YES;
}

上記のコードは ARC を有効にして使用することを意図していますが、次のカスタム オブジェクト コードはそうではありません。

@interface CustomBaseClass : NSObject

+(id) new;
+(id) alloc;
-(id) init;

-(id) retain;
-(void) release;
-(id) autorelease;
-(void) dealloc;

-(id) description;

-(unsigned) refCount;

@end


// easy way to get sizeof
struct CustomBaseClassAsStruct {
    voidPtr isa;
    unsigned volatile refcount;
};

@implementation CustomBaseClass
{
    unsigned volatile  refcount;
}

+(id) new
{
    return [[self alloc] init];
}

+(id) alloc
{
    struct CustomBaseClassAsStruct *results =  malloc(sizeof(struct CustomBaseClassAsStruct));
    results->isa = self;
    results->refcount = 0;
    return (id) results;
}

-(id) init
{
    [self retain];

    return self;
}

-(id) retain
{
    ++refcount;

    return self;
}

-(void) release
{
    if (--refcount == 0)
        [self dealloc];
}

-(id) autorelease
{
    // sample implementation of autorelease
    dispatch_async(dispatch_get_current_queue(), ^{
        [self release];
    });

    return self;
}

-(unsigned) refCount
{
    return refcount;
}

-(void) dealloc
{
    free(self);

    // no call to [super dealloc], we are using custom memory-managment
}

@end

これは、弱い iVar に対してのみ機能します。変数を使用unsafe_unretainedすると、誤検知が発生します。これについての私の最良の推測は、__weak情報は実行時に保存されますが、情報は保存されunsafe_unretainedないためです。

これが役立つことを願っています!

于 2012-07-23T22:49:31.340 に答える