ฉันจะแทนที่การอ้างอิงที่อ่อนแอเมื่อใช้ ARC และกำหนดเป้าหมายเป็น iOS 4.0 ได้อย่างไร


87

ฉันได้เริ่มพัฒนาแอป iOS ตัวแรกของฉันด้วย Xcode 4.2 และกำหนดเป้าหมายเป็น iOS 5.0 ด้วยเทมเพลต "แอปพลิเคชันยูทิลิตี้" (ซึ่งมาพร้อมกับ FlipsideViewController)

ฉันอ่านว่าเนื่องจาก ARC เป็นคุณสมบัติเวลาคอมไพล์จึงควรเข้ากันได้กับ iOS 4 ด้วยดังนั้นฉันจึงพยายามกำหนดเป้าหมายแอปของฉันเป็น 4.3 และลองรวบรวม เมื่อทำเช่นนั้นฉันได้รับข้อผิดพลาดนี้:

FlipsideViewController.m: error: Automatic Reference Counting Issue: เป้าหมายการปรับใช้ปัจจุบันไม่รองรับการอ้างอิง __weak อัตโนมัติ

มันอ้างถึงบรรทัดนี้:

@synthesize delegate = _delegate;

ตัวแปรนั้นถูกประกาศเป็น:

@property (weak, nonatomic) IBOutlet id <FlipsideViewControllerDelegate> delegate;

ฉันเข้าใจว่า "การอ้างอิงที่ไม่เหมาะสม" ไม่ได้รับการสนับสนุนใน iOS 4 แต่ฉันไม่เข้าใจจริงๆว่าทำไมฉันถึงต้องการใช้การอ้างอิงที่อ่อนแอเพื่อเริ่มต้นและฉันไม่สามารถคิดได้ว่าฉันจะเขียนสิ่งต่าง ๆ ใหม่เพื่อหลีกเลี่ยงการใช้มันในขณะที่ ยังคงใช้ประโยชน์จาก ARC (ท้ายที่สุดมันควรจะทำงานกับ iOS 4 และ 5 ใช่มั้ย?)

คำตอบ:


149

หากต้องการกำหนดเป้าหมายระบบปฏิบัติการรุ่นเก่าคุณสามารถใช้unsafe_unretainedแทนการweakประกาศคุณสมบัติของคุณได้และส่วนใหญ่ควรทำงานในลักษณะเดียวกัน weakการอ้างอิงไม่มีตัวตนเมื่อเป้าหมายจากไป แต่ยังunsafe_unretainedเปิดโอกาสให้วัตถุที่คุณกำลังเชื่อมโยงอยู่อาจกลายเป็นตัวชี้ห้อยเมื่อถูกยกเลิกการจัดสรร พฤติกรรมหลังเป็นลักษณะเดียวกับที่คุณใช้assignเป็นการประกาศคุณสมบัติในการจัดการหน่วยความจำด้วยตนเอง

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


ขอบคุณสำหรับคำแนะนำ. คุณพูดว่า "กำหนดเป้าหมาย OS รุ่นเก่า ... " นี่หมายความว่าฉันควรใช้ unsafe_unretained ในรุ่นของแอปที่เก่ากว่า 5.0 เท่านั้นใช่หรือไม่ หรือฉันสามารถใช้ unsafe_unretained ในโค้ดของฉันและสร้างขึ้นเพื่อกำหนดเป้าหมายทั้ง 4.x และ 5.x ได้หรือไม่
Mason G. Zhwiti

1
@Mason - unsafe_unretainedรองรับทั้ง iOS 4.x และ 5.0 ดังนั้นจึงสามารถใช้งานร่วมกันได้แบบย้อนหลัง หากคุณกำลังสร้างเวอร์ชัน 5.0 เท่านั้นคุณอาจเปลี่ยนweakไปใช้ประโยชน์จากความปลอดภัยเพิ่มเติมที่มอบให้กับคุณ
Brad Larson

ฉันลอง unsafe_unretained แล้วมันก็ใช้ได้อยู่ดี อย่างไรก็ตามฉันได้รับคำเตือนมากมายเช่น '"** __NSAutoreleaseNoPool (): Object 0x564bd90 ของคลาส __NSArrayM ที่ปล่อยอัตโนมัติโดยไม่มีพูลอยู่ - แค่รั่ว" * "นั่นเป็นเรื่องปกติ?
ที่ห้า

1
@fifth - นั่นเป็นปัญหาที่ไม่เกี่ยวข้องกันเลย คุณกำลังเรียกใช้บางอย่างบนเธรดพื้นหลังโดยไม่ต้องมีกลุ่มการปล่อยอัตโนมัติในสถานที่ เธรดที่สร้างขึ้นด้วยตนเองไม่มีกลุ่มการปล่อยอัตโนมัติของตนเองดังนั้นคุณต้องสร้างด้วยตนเองโดยใช้@autoreleasepool(ภายใต้ ARC, NSAutoreleasePool สำหรับการอ้างอิงการใช้งานที่นับด้วยตนเองที่เก่ากว่า)
Brad Larson

@ แบรดนั่นเป็นประโยชน์คำเตือนหายไปฉันได้รับการเรียกใช้ performSelectorInBackground หลายครั้ง
ที่ห้า

11

หากใช้เฉพาะการอ้างอิงที่ไม่รัดกุมเพื่อความปลอดภัยเพิ่มเติมให้เรียกฟังก์ชันรันไทม์ใหม่ด้วยตนเองหากพร้อมใช้งานและเปลี่ยนกลับเป็นการกำหนด__unsafe_unretainedตัวแปรง่ายๆหากไม่มี

ZWRCompatibility.hจะทำให้สิ่งนี้ง่ายขึ้นบ้าง


10

ต้องขอบคุณPLWeakCompatibiltyไลบรารีความเข้ากันได้ของ Mike Ash ตอนนี้คุณสามารถใช้ __weak บน iOS 4.x ได้เช่นกัน

มันง่ายอย่างเหลือเชื่อในการกำหนดค่าและไม่ต้องพิจารณาหรือใช้ความพยายามเพิ่มเติมในช่วง 5.x

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