วัตถุที่ไม่เก็บไว้: เมื่อไหร่จะปล่อย?

ภายในวิธีการเริ่มต้น ฉันมีรหัสต่อไปนี้

- (id)init {

    self = [super init];

    if (self) {

        UIButton *tempButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        tempButton.frame = CGRectMake(0,0,300,44);

        // some custom code...

        self.myButton = tempButton;
    }

    return self;
}

โดยที่ myButton คือทรัพย์สินที่คงไว้ ฉันรู้ว่าสำหรับกฎการจัดการหน่วยความจำ วิธีนี้เท่ากับวิธีอื่น:

- (id)init {

    self = [super init];

    if (self) {

        UIButton *tempButton = [[UIButton alloc] initWithFrame:CGRectMake(0,0,300,44)];

        // some custom code...

        self.myButton = tempButton;
        [tempButton release];
    }

    return self;
}

แต่ในกรณีนี้ ฉันจำเป็นต้องใช้ "เวอร์ชัน" แรก เนื่องจากคุณสมบัติ buttonType เป็นแบบอ่านอย่างเดียว และฉันไม่สามารถเปลี่ยนแปลงได้หลังจากที่ปุ่มเริ่มใช้งานแล้ว

เนื่องจากฉันพบว่าตัวเองใช้เวอร์ชัน "non init-release" ในหลายวิธีทั่วแอปพลิเคชันของฉัน และสำหรับออบเจ็กต์หลายอย่าง (ส่วนใหญ่เป็น NSString) คำถามของฉันคือ: ไม่นับในกรณีนี้การมอบหมายให้กับคุณสมบัติที่ยังคงรักษา object วัตถุ tempButton จะถูกปล่อยออกมาเมื่อใด? อาจจะอยู่ท้ายคำสั่ง method/if ใช่ไหม? หรือ "เวอร์ชัน" แรกจะนำไปสู่การใช้หน่วยความจำที่เพิ่มขึ้น เนื่องจากวัตถุไม่ได้ถูกปล่อยออกมาทันที แต่หลังจากผ่านไประยะหนึ่งแล้ว


person Andrea Sprega    schedule 15.02.2012    source แหล่งที่มา


คำตอบ (2)


ฉันคิดว่าคุณสับสนเล็กน้อยที่นี่: ในตัวอย่างทั้งสองของคุณ คุณสร้างวัตถุ tempButton แต่แล้วคุณก็กำหนดมันให้กับ self.myButton ณ จุดนั้น ทั้ง tempButton และ self.myButton เป็นตัวชี้ไปยังวัตถุเดียวกัน ตอนนี้ สันนิษฐานว่า myButton @property ที่คุณใช้อยู่เป็นคุณสมบัติที่แข็งแกร่ง ดังนั้นโดยการกำหนด tempButton ให้กับมัน คุณจะเพิ่มจำนวนการเก็บรักษา และดังนั้นในโค้ดเวอร์ชันใดเวอร์ชันหนึ่ง ก็จะมีการนับคงเป็น +1 ในตอนท้าย และ จะไม่ถูกจัดสรรคืน

ตามสมมุติฐาน หาก myButton ไม่ใช่คุณสมบัติที่แข็งแกร่ง ก็อาจมีข้อผิดพลาดในโค้ดของคุณ และในทั้งสองกรณี tempButton จะถูกรีลีสก่อนกำหนดและถูกจัดสรรคืน สิ่งที่จะเกิดขึ้นในสองกรณีมีดังนี้:

ในเวอร์ชันแรกของคุณ เนื่องจากคุณได้รับ tempButton มาจากอย่างอื่นที่ไม่ใช่เมธอด init หรือ copy มันจึงได้รับค่าคงไว้เป็น +1 แต่จะเผยแพร่โดยอัตโนมัติ เมื่อสิ้นสุดการวนซ้ำปัจจุบันของ run loop การรีลีสอัตโนมัติจะเริ่มทำงาน ทำให้นับการคงไว้เป็น 0 และทำให้เกิดการจัดสรรคืน

ในเวอร์ชันที่สอง ขั้นแรกคุณจะได้รับ tempButton ที่มีจำนวนการเก็บรักษาเป็น 1 เนื่องจากมาจากเมธอด init แต่ต่อมาคุณปล่อยมันอย่างชัดเจน โดยนับการคงไว้เป็น 0 ซึ่ง ณ จุดนี้มันจะถูกจัดสรรคืนทันที

person yuji    schedule 15.02.2012
comment
โอ้ ฉันพลาดส่วน run loop ไป เป็นไปได้ไหมที่คุณจะแม่นยำมากขึ้นเกี่ยวกับการวนซ้ำปัจจุบันของ run loop? การวนซ้ำนั้นเกี่ยวข้องกับวิธีเดียวหรือบางอย่างที่นานกว่านั้น อาจเป็นระยะเวลาคงที่หรือไม่? อาจเป็นอายุการใช้งานแอปพลิเคชันทั้งหมดหรือไม่ ฉันพยายามเข้าใจมากขึ้นโดยการอ่านบทช่วยสอน แต่ไม่มีใครอธิบายเรื่องนี้ได้อย่างชัดเจน - person Andrea Sprega; 15.02.2012
comment
การวนซ้ำปัจจุบันของ run loop นั้นแม่นยำที่สุดเท่าที่จะเป็นไปได้ รันลูปคือลูปการประมวลผลเหตุการณ์ใน Cocoa นี่เป็นโพสต์บนบล็อกที่ดีหากคุณต้องการทราบข้อมูลเพิ่มเติม: blog.shinetech.com/2009/06/02/run-loops-vs-threads-in-cocoa - person yuji; 15.02.2012

วิธีการที่ไม่ใช่ init จะเหมือนกับ:

UIButton *tempButton = [[[UIButton alloc] initWithFrame:CGRectMake(0,0,300,44)] autorelease];

ดังนั้นแนวคิดก็คือต้องเข้าใจให้มากขึ้นเกี่ยวกับวิธีการทำงานของพูลการเผยแพร่อัตโนมัติ ซึ่งมีประโยชน์มากเกือบตลอดเวลา แต่คุณต้องเข้าใจว่ามันทำงานอย่างไร ในกรณีที่คุณจะใช้ออบเจ็กต์ในแอปในภายหลัง และเพื่อสังเกตบางสิ่งบางอย่าง เมื่อคุณเพิ่มปุ่ม temp เข้าไปในมุมมองของคุณ มุมมองนั้นจะยังคงอยู่ และจะปล่อยมันเมื่อมันถูกลบออกจากมัน คุณสามารถใช้เครื่องมือและตรวจสอบจำนวนการคงไว้ของวัตถุได้ หากคุณต้องการดูว่าปล่อย/ ยังคงมีการดำเนินการต่อไป หากคุณต้องการเห็นการทำงานจริง

person Ehab Amer    schedule 15.02.2012