ข้อผิดพลาด: คุณสมบัติอะตอมแบบเขียนได้ไม่สามารถจับคู่ setter / getter ที่สังเคราะห์ได้กับ setter / getter ที่ผู้ใช้กำหนด


128

ฉันเพิ่งพยายามรวบรวมโครงการ Xcode รุ่นเก่า (ซึ่งใช้ในการรวบรวมได้ดี) และตอนนี้ฉันเห็นข้อผิดพลาดมากมายของแบบฟอร์มนี้:

error: writable atomic property 'someProperty' cannot pair a synthesized setter/getter with a user defined setter/getter

รูปแบบรหัสที่ทำให้เกิดข้อผิดพลาดเหล่านี้จะเป็นดังนี้:

// Interface:

@property (retain) NSObject * someProperty;

// Implementation:

@synthesize someProperty; // to provide the getter
- (void)setSomeProperty:(NSObject *)newValue
{
    //..
}

ฉันเห็นได้ว่าเหตุใดจึงเกิดข้อผิดพลาดขึ้น ฉันบอกคอมไพเลอร์เพื่อสังเคราะห์ accessors คุณสมบัติของฉัน (ทั้งทะเยอทะยานและ setter) และหลังจากนั้นทันทีฉันแทนที่ตัวตั้งค่าด้วยตนเอง รหัสนั้นมีกลิ่นเล็กน้อย

ดังนั้นวิธีที่เหมาะสมในการทำเช่นนี้คืออะไร? ถ้าฉันใช้@dynamicแทน@synthesizeฉันจะต้องเขียนทะเยอทะยานเช่นกัน นั่นเป็นวิธีเดียวหรือไม่


สิ่งนี้เกิดขึ้นกับatomicคุณสมบัติได้หรือไม่ ในกรณีที่คุณสมบัติของอะตอมอาจเป็นความคิดที่ดีที่จะทำให้คู่ getter / setter ซิงค์กันกับกลยุทธ์การล็อค นี่เป็นเรื่องยากหากมีการสังเคราะห์ส่วนหนึ่งในขณะที่ส่วนอื่นเป็นรหัสที่กำหนดเอง
Nikolai Ruhe

มันจะหายไปอย่างแน่นอนถ้าฉันสร้างคุณสมบัติที่ไม่ใช่เชิงอะตอม น่าสนใจ ฉันไม่ได้คิดเกี่ยวกับปัญหาการซิงโครไนซ์
e.James

ฉันไปที่หัวข้อนี้เพื่อค้นหาวิธีแก้ไขปัญหาที่แน่นอน ฉันไม่ต้องการเขียนตัวทะเยอทะยานและตัวตั้งตัวเองจริงๆ ดี ...
Constantino Tsarouhas

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

คำตอบ:


218

ฉันมีปัญหาเดียวกันและหลังจากทำการวิจัยเล็กน้อยนี่คือข้อสรุปของฉันเกี่ยวกับปัญหานี้:

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

ในการทำให้คำเตือนนั้นหายไป:

ถ้าคุณประกาศ a @propertyเป็น atomic ให้ทำอย่างใดอย่างหนึ่งต่อไปนี้:

  • ใช้@dynamicหรือ;
  • ใช้@synthesizeและรักษา setter ที่ถูกสังเคราะห์และทะเยอทะยานหรือ;
  • ให้ดำเนินการด้วยตนเองของ ทั้ง setter และ getter (โดยไม่ต้องใช้หนึ่งในคำสั่งข้างต้น)

ถ้าคุณประกาศ @propertyด้วย(nonatomic)คุณสามารถผสมการปรับใช้ด้วยตนเองและแบบสังเคราะห์ของตัวรับและตัวตั้งค่า

อัปเดต: หมายเหตุเกี่ยวกับการสังเคราะห์คุณสมบัติอัตโนมัติ

ในฐานะของ LLVM 4.0 @dynamicเสียงดังกราวให้อัตโนมัติสังเคราะห์สำหรับคุณสมบัติของประกาศว่าจะไม่ โดยค่าเริ่มต้นแม้ว่าคุณจะออกจาก@synthesizeที่รวบรวมจะให้วิธีการ getter และ setter สำหรับคุณ อย่างไรก็ตามกฎสำหรับคุณสมบัติของอะตอมยังคงเหมือนเดิม: ให้คอมไพเลอร์จัดเตรียมทั้ง getter และ setter หรือใช้ทั้งสองตัวเอง!


ขอบคุณ! "ประกาศ @property ด้วย (nonatomic)"
Nianliang

14

คุณจำเป็นต้องติดตั้ง getter ด้วย ตัวอย่าง:

// Interface:

@property (retain) NSObject * someProperty;

// Implementation:

- (void)setSomeProperty:(NSObject *)newValue
{
    @synchronized (self)
    {
        // ...
    }
}

- (NSObject *)someProperty
{
    NSObject *ret = nil;

    @synchronized (self)
    {
        ret = [[someProperty retain] autorelease];
    }

    return ret;
}

12

คำถามนี้คุณจะไม่ได้รับการอัปเดตด้วยข้อมูลเกี่ยวกับ "setter =" หรือ "getter ="

ดังนั้นเพื่อให้ข้อมูลเพิ่มเติมเกี่ยวกับคำถามนี้:

คุณสามารถระบุการโทร @property ด้วยวิธีการของคุณเองโดยการเขียน

    @property(setter = MySetterMethod:, getter = MyGetterMethod)

สังเกตุโคลอนสำหรับวิธีเซ็ตเตอร์ที่ให้มา

เอกสารอ้างอิงของApple

แก้ไข: ฉันไม่แน่ใจว่าการเปลี่ยนแปลงใหม่ในคุณสมบัติของ Objective-C (ตอนนี้ฉลาดมากขึ้น) เปลี่ยนคำตอบสำหรับคำถามนี้ บางทีมันควรจะถูกทำเครื่องหมายว่าล้าสมัย


ฉันพบว่าการตั้งค่าเมธอด setter ไม่ได้เป็นการลบคำเตือนจริงๆ เช่น -> "@property (assign, setter = setDelegate :) รหัสผู้แทน;" ในกรณีนี้สิ่งที่ฉันทำได้คือเพิ่มตัวทะเยอทะยานของฉันเองหรือเพิ่มคุณสมบัติที่ไม่ใช่เชิงอะตอมซึ่งฉันไม่แน่ใจว่าควรจะทำอย่างไรหากฉันตั้งตัวแทนของตัวเองด้วยวิธีทางอะตอมมันไม่สำคัญว่าจะมีคุณสมบัติที่ไม่ใช่เชิงอะตอม หรือดังนั้นฉันเข้าใจ
David van Dugteren

น่าสนใจเดวิด "รุ่น" ของ Objective-C คืออะไรในนี้ (ฉันสมมติว่า XCode-version จะมีประโยชน์มากกว่า) ฉันไม่แน่ใจว่าการเปลี่ยนแปลงล่าสุดของ Objective-C โดยเฉพาะกับ iOS 6 มีผลกับสิ่งนี้อย่างไร
Matias Forbord

0

สำหรับคนอื่น ๆ ที่ได้รับข้อผิดพลาดนี้ไม่ใช่เหตุผลที่ OP อธิบายไว้คุณอาจมีปัญหาเช่นเดียวกับฉัน:

คุณมี @property ซึ่งมีชื่อเหมือนกับเมธอด - ()

บางสิ่งเช่นนี้

@property UIView *mainView;

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