แอตทริบิวต์ setter คุณสมบัติที่อ่อนแอและแข็งแกร่งใน Objective-C


94

อะไรคือความแตกต่างระหว่างแอตทริบิวต์ setter คุณสมบัติที่อ่อนแอและแข็งแกร่งใน Objective-C?

@property(retain, [weak/strong]) __attribute__((NSObject)) CFDictionaryRef myDictionary;

ผลกระทบและประโยชน์คืออะไร?

ฉันได้ยินมาว่าจุดอ่อนไม่สามารถใช้ได้ใน iOS 4 และเราจำเป็นต้องใช้การกำหนด

อ่อนแอคล้ายกับการมอบหมายหรือไม่?


คำตอบ:


102

คุณเปิดหรือปิด ARC สำหรับไฟล์ใดไฟล์หนึ่ง หากคุณไม่สามารถใช้retain release autoreleaseฯลฯ ... คุณใช้strong weakสำหรับคุณสมบัติหรือ__strong __weak ตัวแปรแทน (ค่าเริ่มต้นเป็น__strong) Strong เทียบเท่ากับการรักษาอย่างไรก็ตาม ARC จะจัดการการเปิดตัวให้คุณ

ครั้งเดียวที่คุณต้องการใช้จุดอ่อนคือถ้าคุณต้องการหลีกเลี่ยงวัฏจักรการรักษา (เช่นผู้ปกครองรักษาเด็กและเด็กยังคงรักษาผู้ปกครองไว้ไม่ให้ปล่อยออกมา)

ส่วน 'การเชื่อมต่อโทรฟรี' (การส่งจากNSถึงCF) นั้นค่อนข้างยุ่งยากเล็กน้อย คุณยังคงต้องจัดการด้วยตนเองCFRelease()และCFRetain()สำหรับวัตถุ CF เมื่อคุณแปลงกลับเป็นอ็อบเจ็กต์ NS คุณต้องบอกคอมไพเลอร์เกี่ยวกับจำนวนการเก็บรักษาเพื่อให้รู้ว่าคุณทำอะไรไปแล้ว

ทุกคนที่นี่


120

นี่คือข้อมูลที่ฉันรู้เกี่ยวกับคุณสมบัติตัวแปร

  1. อะตอม // ค่าเริ่มต้น
  2. ไม่ใช่อะตอม
  3. strong = คงไว้ // ค่าเริ่มต้น
  4. อ่อนแอ
  5. รักษา
  6. กำหนด // ค่าเริ่มต้น
  7. unsafe_unretained
  8. สำเนา
  9. อ่านเท่านั้น
  10. readwrite // ค่าเริ่มต้น

ด้านล่างนี้เป็นลิงค์บทความโดยละเอียดที่คุณสามารถค้นหาคุณลักษณะทั้งหมดที่กล่าวถึงข้างต้นซึ่งจะช่วยคุณได้ ขอบคุณทุกคนที่ให้คำตอบที่ดีที่สุดที่นี่ !!

คุณสมบัติตัวแปรคุณสมบัติหรือตัวปรับแต่งใน iOS

01. strong (iOS4 = คงไว้) - มันบอกว่า "เก็บสิ่งนี้ไว้ในกองจนกว่าฉันจะไม่ชี้ไปที่มันอีกต่อไป" - หรืออีกนัยหนึ่งคือ "ฉันเป็นเจ้าของคุณไม่สามารถยกเลิกการจัดสรรสิ่งนี้ก่อนที่จะตั้งเป้าหมายให้ดีด้วยสิ่งนั้นเหมือนกับที่เก็บไว้ "- คุณใช้แรงก็ต่อเมื่อคุณต้องการเก็บวัตถุ - โดยค่าเริ่มต้นตัวแปรอินสแตนซ์และตัวแปรท้องถิ่นทั้งหมดเป็นตัวชี้ที่ชัดเจน - โดยทั่วไปแล้วเราใช้ที่แข็งแกร่งสำหรับ UIViewControllers (ผู้ปกครองของรายการ UI) - Strong ใช้กับ ARC และโดยพื้นฐานแล้วจะช่วยคุณได้โดยไม่ต้องกังวลกับจำนวนการคงไว้ของวัตถุ ARC จะเผยแพร่ให้คุณโดยอัตโนมัติเมื่อคุณทำเสร็จแล้วการใช้คีย์เวิร์ดที่แข็งแกร่งหมายความว่าคุณเป็นเจ้าของออบเจ็กต์

ตัวอย่าง:

@property (strong, nonatomic) ViewController *viewController;

@synthesize viewController;

02. อ่อนแอ (iOS4 = unsafe_unretained) - มีข้อความว่า "เก็บสิ่งนี้ไว้ตราบเท่าที่มีคนอื่นชี้ให้เห็นอย่างชัดเจน" - เช่นเดียวกับการมอบหมายไม่มีการเก็บรักษาหรือการปล่อย - การอ้างอิง "อ่อนแอ" คือการอ้างอิงที่คุณไม่ได้เก็บรักษาไว้ - โดยทั่วไปเราใช้จุดอ่อนสำหรับ IBOutlets (UIViewController's Childs) สิ่งนี้ได้ผลเนื่องจากวัตถุลูกจำเป็นต้องมีอยู่ตราบเท่าที่ออบเจ็กต์หลักทำเท่านั้น - การอ้างอิงที่อ่อนแอคือการอ้างอิงที่ไม่ปกป้องวัตถุที่อ้างอิงจากการรวบรวมโดยผู้รวบรวมขยะ - โดยพื้นฐานแล้วจุดอ่อนคือการมอบหมายทรัพย์สินที่ไม่ได้คืน ยกเว้นเมื่อวัตถุถูกยกเลิกการจัดสรรตัวชี้ที่อ่อนแอจะถูกตั้งค่าเป็นศูนย์โดยอัตโนมัติ

ตัวอย่าง:

@property (weak, nonatomic) IBOutlet UIButton *myButton;

@synthesize myButton;

อธิบาย : ขอบคุณ BJ Homer

ลองนึกภาพวัตถุของเราคือสุนัขและสุนัขต้องการที่จะวิ่งหนี (ถูกจัดสรรทิ้ง) ตัวชี้ที่แข็งแกร่งก็เหมือนสายจูงสุนัข ตราบใดที่คุณมีสายจูงติดกับสุนัขสุนัขจะไม่วิ่งหนี หากมีคนห้าคนผูกสายจูงไว้กับสุนัขหนึ่งตัว (ตัวชี้ที่แข็งแกร่งห้าตัวต่อวัตถุชิ้นเดียว) สุนัขจะไม่วิ่งหนีจนกว่าสายจูงทั้งห้าจะหลุดออก ในทางกลับกันตัวชี้ที่อ่อนแอก็เหมือนกับเด็กตัวเล็ก ๆ ที่ชี้ไปที่สุนัขและพูดว่า "ดูสิสุนัข!" ตราบใดที่สุนัขยังอยู่ในสายจูงเด็ก ๆ ยังสามารถมองเห็นสุนัขได้และพวกเขาก็ยังชี้ไปที่มัน ทันทีที่สายจูงทั้งหมดหลุดออกสุนัขจะวิ่งหนีไม่ว่าเด็ก ๆ จะชี้ไปที่มันกี่ตัวก็ตาม ทันทีที่ตัวชี้ที่แข็งแกร่งตัวสุดท้าย (สายจูง) ไม่ชี้ไปที่วัตถุอีกต่อไปวัตถุนั้นจะถูกจัดสรรและตัวชี้ที่อ่อนแอทั้งหมดจะถูกทำให้เป็นศูนย์ เมื่อเราใช้อ่อนแอ? ครั้งเดียวที่คุณต้องการใช้จุดอ่อนคือถ้าคุณต้องการหลีกเลี่ยงวัฏจักรการรักษา (เช่นผู้ปกครองรักษาเด็กและเด็กยังคงรักษาผู้ปกครองไว้ไม่ให้ปล่อยออกมา)


1
ในรายการเริ่มต้นฉันไม่แน่ใจจริงๆว่าคุณหมายถึงอะไรโดย "ค่าเริ่มต้น" คุณมีทั้งสองอย่างstrong=retainและassignติดป้ายกำกับว่าเป็นค่าเริ่มต้น แต่ไม่สามารถเป็นทั้งสองอย่างได้
Slipp D. Thompson

27
ชอบสุนัขในการเปรียบเทียบสายจูง อธิบายได้ดีทีเดียว
Jarrett Barnett

1
คำอธิบายที่ดีแม้ว่า iOS จะไม่ใช้การเก็บขยะ ARC! = การเก็บขยะ (!) ซึ่งเป็นเทคโนโลยีที่แตกต่างกัน

1
อ่อนแอและไม่ปลอดภัย (ไม่ปลอดภัย) แตกต่างกัน (ครั้งแรกใช้การอ้างอิงที่อ่อนแอเป็นศูนย์ในขณะที่หลังทำหมอบ)
wcochran

1
ฉันกำลังเรียนรู้ iOS เท่านั้น แต่ดูเหมือนว่าคุณจะใส่ผิดที่weakและstrongในตัวอย่างของคุณ มันจะสมเหตุสมผลกว่าไหมที่ผู้ปกครองมีstrongการอ้างอิงถึงลูก ๆ ของตน (ในฐานะmyButtonสมบัติของUIViewControllerชั้นเรียนที่คุณแสดงให้เห็นweak) และเด็ก ๆ ยังคงweakอ้างอิงถึงพ่อแม่ของพวกเขา (เช่นviewControllerทรัพย์สินของชั้นลูกที่คุณ ' ve แทนตั้งค่าเป็นstrong) ตัวอย่างเช่นการอ่านของ Matt Neuburg iOS 7 Programming Fundamentalsเขาแสดงให้เห็นว่าชั้นเรียนที่ประกาศผู้แทนเป็นทรัพย์สินจะทำให้มัน `` อ่อนแอซึ่งดูเหมือนจะยุติธรรม
Bogdan Alexandru

2

หากต้องการเรียกบางส่วนของเอกสารที่โรเบิร์ตอ้างอิงซึ่งตอบคำถามสองข้อสุดท้ายของคุณอย่างชัดเจน

// The following declaration is similar to "@property(assign) MyClass *myObject;"
// except that if the MyClass instance is deallocated,
// the property value is set to nil instead of remaining as a dangling pointer.
@property(weak) MyClass *myObject;

สิ่งนี้เรียกว่าการอ้างอิงที่อ่อนแอเป็นศูนย์ คุณสามารถสร้างการอ้างอิงที่ไม่เหมาะสมซึ่งไม่ได้ทำให้การอ้างอิงที่อ่อนแอเป็นศูนย์โดยใช้ __unsafe_unretained แต่โดยทั่วไปแล้วไม่แนะนำให้ใช้ชื่อนี้

นอกจากนี้ในเอกสาร:

Weak references are not supported in Mac OS X v10.6 and iOS 4.

1
ใช่นี่ถูกต้อง __unsafe_unretainedเป็นเวอร์ชัน ARC ของassign.
Robert

2

การใช้คุณสมบัติที่อ่อนแออย่างชัดเจนมีดังนี้:

Any control whose properties we need to change(eg:text of a label) is declared weak and as below:

@property(nonatomic,weak) IBOutlet Type *name;
Eg: @property(nonatomic,weak) IBOutlet UILabel *myLabel;

1
เมื่อใช้คุณสมบัติที่อ่อนแอฉันได้รับคำเตือนว่า: "ตัวรับสัญญาณที่อ่อนแออาจตั้งค่าเป็นศูนย์โดยไม่คาดคิด" ฉันเคยเห็นโพสต์อื่น ๆ ที่เพื่อป้องกันคำเตือนนี้คุณต้องสร้างข้อมูลอ้างอิงที่รัดกุมในท้องถิ่น และถ้าเป็นจริงอะไรคือจุดที่ทำให้คุณสมบัติอ่อนแอถ้าในตอนท้ายฉันต้องสร้างข้อมูลอ้างอิงที่รัดกุม?
Arh

0

ลองดูตัวอย่างเพื่ออธิบายเพิ่มเติม (คำตอบข้างบนดีอยู่แล้ว) ตัวอย่างนี้อาจช่วยได้อีกเล็กน้อย

ให้เรามีสองคลาส A และ B

//A.h

#import <Foundation/Foundation.h>
#import "B.h"

@interface A : NSObject

@property (nonatomic, strong) B *objB;

@end

@implementation A
//

@end

//B.h

    #import <Foundation/Foundation.h>
    #import "A.h"


    @interface B : NSObject

    @property strong text(nonatomic, strong) A *objA;

    @end

    @implementation B
    //

    @end

    and in main

    #import "B.h"
    #import "A.h"

    {
    A *obja =[[A alloc]init];
    B *objb =[[B alloc]init];
    A.objB=objb;
    B.objA=obja;
   }

รหัสด้านบนจะสร้างวงจรการเก็บรักษาเนื่องจากทั้งสองเป็นประเภทที่แข็งแกร่ง a --------> b ---------> a

ดังนั้นเพื่อหลีกเลี่ยงไม่ให้คุณต้องใช้คุณสมบัติ week ของหนึ่งในนั้นเพื่อให้ทุกสัปดาห์อ้างถึงวัตถุและไม่เพิ่มจำนวนอ้างอิง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.