لدي مرجع دائري.كيف يمكنني إنشاء ضعف الإشارة في الهدف C ؟

StackOverflow https://stackoverflow.com/questions/1072541

سؤال

أنا أعمل على تطبيق اي فون.أنا كائن من الدرجة Row الذي يحتاج إلى الإفراج عن العديد من الكائنات من فئة Block.كل Block حاليا الممتلكات التي يحتفظ متغير مثيل من فئة Row.

@interface Block : UIImageView {
  Row *yCoord;
}
@property (nonatomic,retain) Row *yCoord;
@end

كل Row يحتوي على NSMutableArray من هذه الكتل.

@interface Row : NSObject {
    NSMutableArray *blocks;
}
-(void)addBlock:(Block*)aBlock;
@end

@implementation Row
-(void)addBlock:(Block*)aBlock {
    [blocks addObject:aBlock];
    aBlock.yCoord = self;
}
@end

أنا أفهم أن هذا هو مرجع دائري.أبل الوثائق الدول من أجل تخصيص كائن مع مرجع دائري أحتاج إلى ضعف الإشارة بدلا من إشارة قوية (a تحتفظ المنشأة) لكن لا من خلال متابعة وشرح كيف بالضبط لا تذهب عن القيام بذلك.أنا خطة لاطلاق سراح dealloc جميع الكتل داخل الصف وكذلك الصف نفسه في وقت واحد.كيف يمكنني إعداد ضعف الإشارة في كل من الكتل إلى "الأم" الصف ؟

هل كانت مفيدة؟

المحلول

تحرير: منذ السائل توضيح انه ليس باستخدام جمع القمامة (اي فون حاليا لا تدعم ذلك), نصيحتي هي أن تجنب دورات من خلال وجود واحد فقط من الأجسام الإبقاء على أخرى ، تماما كما تفعل مع مندوب.عند استخدام خصائص استخدام "تعيين" بدلا من "الاحتفاظ" لتحقيق ذلك.على سبيل المثال:

@property (nonatomic,assign) Row *yCoord;

بقية الإجابة إجابة تتعلق "إشارات ضعيفة" من حيث الهدف-C 2.0 و GC.


عندما كنت تعمل مع جمع القمامة (10.5+) ، وضعف المرجعية يتم إنشاؤه من قبل التقديم متغير الإعلان مع __weak.عند تعيين هذا المتغير ، GC (إذا تمكين) بتتبع المرجعية سوف صفر لك تلقائيا إذا كان كل إشارات قوية إلى الكائن المشار إليه تختفي.(إذا GC لم يتم تمكين ، __weak السمة تجاهلها.)

وهكذا, يمكنك بأمان تعديل الإجابة أعلاه للعب أجمل مع جمع القمامة (حاليا على 10.5+, وربما يوما ما على اي فون) على النحو التالي:(انظر ذات الصلة أبل مستندات.)

@property (nonatomic,assign) __weak Row *yCoord;

اقتباس كريس هانسون (حيث يمكنك العثور على معلومات أكثر تفصيلا):

"من خلال التقديم متغير مثيل الإعلان مع __weak, أخبر القمامة جامع ذلك إن كان ذلك فقط الإشارة إلى كائن كائن ينبغي النظر للتحصيل."

أود توضيح ذلك بالقول "إذا كان هناك أي غير ضعيف إشارات إلى كائن".بمجرد أن آخر إشارة قوية إزالة الكائن قد جمعها ، و كل الإشارات الضعيفة سيتم ركزت تلقائيا.

ملاحظة: هذا ليس مباشرة تتعلق بإنشاء إشارات ضعيفة ، ولكن هناك أيضا __strong السمة ، ولكن منذ الهدف-C كائن المتغيرات إشارات قوية بشكل افتراضي ، يتم عموما إلا الخام ج مؤشرات إلى أشياء مثل البنيات أو الأوليات أن جامع القمامة لن لعلاج الجذور ، سيتم جمعها من تحت لك إذا كنت لا تعلن لهم قوية.(في حين أن عدم وجود __weak يمكن أن يسبب الاحتفاظ دورات تسرب الذاكرة ، وعدم وجود __strong يمكن أن يؤدي إلى ذاكرة الدوس و غريب و غدرا الأخطاء التي تحدث من غير deterministically و يمكن أن يكون من الصعب جدا لتعقب.)

نصائح أخرى

ومجرد تغيير لتعيين بدلا من الاحتفاظ بها والمراجع لا أكثر دائرية.

@interface Block : UIImageView {
  Row *yCoord;
}
@property (nonatomic,assign) Row *yCoord;
@end

وإشارة ضعيفة هي ببساطة مهمة (إلا إذا كنت تتحدث عن جمع القمامة وهو يمكن فصل كامل من الديدان، ولكن لا يعانون من الاحتفاظ دورات).

وعادة، في الكاكاو، Row سيحتفظ الكائنات Block (عن طريق إشراكها في NSMutableArray)، ولكن Block لن تحتفظ Row، كل ببساطة تخزينها في ايفار (مع "تعيين" الملكية).

وطالما Row يحرص على إطلاق سراح كل Block قبل يتم deallocated أنه (أي dealloc لها يجب الافراج عن NSMutableArray التي سوف الافراج عن كتل طالما لا أحد لديه أي مؤشرات لهم) ثم سوف يمكن deallocated كل شيء حسب الاقتضاء .

ويمكنك أيضا أن تأخذ الاحتياطات من التصفير الإشارة الصف من كتل قبل إزالة entiries من مجموعة، شيء من هذا القبيل:

- (void) dealloc {
    for (Block* b in _blocks) {
        b.row = nil;
    }
    [_blocks release];
    [super dealloc];
}

وحيث _blocks هو ايفار المشار إليها بواسطة الخاصية كتل.

باستخدام تعيين إلى إنشاء إشارات ضعيفة يمكن أن تكون غير آمنة في مؤشرات النظام ، خاصة عندما يكون أي كائن يمكن الاحتفاظ بها من قبل ثالثة وجوه ، ثم تستخدم dereference كائن آخر.

لحسن الحظ, هذا هو في كثير من الأحيان مشكلة التسلسل الهرمي الكائن التي تحتوي على إشارة ضعيفة يهتم فقط حول الكائن فإنه يشير إلى المشار إليها الكائن مدى الحياة.هذا هو الوضع المعتاد مع متفوقة<->علاقة التبعية.

أعتقد أن القضية في OP تعليق خرائط هذا مع صف = متفوقة بلوك = المرؤوس.

في هذه الحالة, وأود أن استخدام مؤشر إلى الرجوع إلى أعلى من الثانوية:

// Superior.h

@class Superior;

@interface SuperiorHandle : NSObject {
    @private
        Superior* superior_;
}

// note the deliberate avoidance of "nonatomic"
@property (readonly) Superior *superior;

@end

@interface Superior : NSObject {
    @private
        SuperiorHandle *handle_;
        // add one or more references to Subordinate instances
}

// note the deliberate avoidance of "nonatomic"
@property (readonly) SuperiorHandle *handle;

@end


// Superior.m

#import "Superior.h"

@implementation SuperiorHandle

@synthesize
    superior = superior_;

- (id)initWithSuperior:(Superior *)superior {
    if ((self = [super init])) {
        superior_ = superior; // weak reference
    }
}

- (void)invalidate {
    @synchronized (self) {
        superior_ = nil;
    }
}

- (Superior *)superior {
    @synchronized (self) {
        // retain and autorelease is required to prevent dealloc before we're ready, thanks to AndroidDev for pointing out this mistake
        return [[superior_ retain] autorelease];
    }
}

@end

@implementation Superior

@synthesize
    handle = handle_;

- (id)init {
    if ((self = [super init])) {
        handle_ = [[SuperiorHandle alloc] initWithSuperior:self];
    }
    return self;
}

- (void)dealloc {
    [handle_ invalidate];
    [handle_ release];

    [super dealloc];
}

@end


// Subordinate.h

@class Superior;
@class SuperiorHandle;

@interface Subordinate : NSObject {
    @private
        SuperiorHandle *superior_handle_;
}

@property (readonly) Superior *superior;

@end


// Subordinate.m

#import "Subordinate.h"

#import "Superior.h"

@implementation Subordinate

// no synthesize this time, superior's implementation is special

- (id)initWithSuperior:(Superior *)superior {
    if ((self = [super init])) {
        superior_handle_ = [superior.handle retain];
    }
    return self;
}

- (void)dealloc {
    [superior_handle_ release];

    [super dealloc];
}

- (Superior *)superior { 
    @synchronized (superior_handle_) {
        return superior_handle_.superior; 
    }
}

@end

بعض المزايا:

  1. إنه موضوع آمنة.لا توجد وسيلة يمكن أن يكون ضعف الإشارة الواردة في المرؤوس يصبح مؤشر غير صالح.قد تصبح معدومة ولكن هذا هو موافق.
  2. فقط الكائنات نفسها تحتاج إلى معرفته حول جزءا لا يتجزأ من ضعف الإشارة.كل الكائنات الأخرى يمكن علاج التابعة كما لو أنه قد منتظم الإشارة إلى متفوقة.
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top