Semantic Issue: Getter synthesized getter เป็นไปตามหลักการตั้งชื่อ Cocoa สำหรับการคืนค่าออบเจ็กต์ 'เจ้าของ'


283

ขณะนี้ฉันใช้ iOS 5 SDK พยายามพัฒนาแอพของฉัน ฉันกำลังพยายามสร้าง NSString พร็อพเพอร์ตี้แล้วทำการสังเคราะห์ในไฟล์. m (ฉันเคยทำสิ่งนี้มาก่อนโดยไม่มีปัญหา) ตอนนี้ฉันเจอสิ่งนี้: "ปัญหาทางความหมาย: ตัวสังเคราะห์ที่ได้รับจากทรัพย์สินตามแผนการตั้งชื่อโกโก้สำหรับส่งคืนวัตถุที่เป็นเจ้าของ"

นี่คือรหัสของฉัน: .h

@interface ViewController : UIViewController {
     NSString *newTitle;
}
@property (strong, nonatomic) NSString *newTitle;

.m

@synthesize newTitle;

ไม่มีใครมีเงื่อนงำฉันจะแก้ไขได้อย่างไร ขอบคุณ !!


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

คำตอบ:


606

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

คุณเป็นเจ้าของวัตถุถ้าคุณสร้างขึ้นโดยใช้วิธีการที่ชื่อขึ้นต้นด้วย“ alloc”,“ new”,“ copy” หรือ“ mutableCopy”

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

คุณสามารถแก้ปัญหานี้ได้โดย:

  1. การเปลี่ยนชื่อคุณสมบัตินั้น:

    @property (strong, nonatomic) NSString *theNewTitle;
  2. การรักษาชื่อคุณสมบัติและการระบุชื่อ getter ที่ไม่ได้ขึ้นต้นด้วยคำนำหน้าชื่อวิธีพิเศษอย่างใดอย่างหนึ่ง:

    @property (strong, nonatomic, getter=theNewTitle) NSString *newTitle;
  3. การรักษาทั้งชื่อคุณสมบัติและชื่อ getter และบอกคอมไพเลอร์ว่าแม้ว่าชื่อ getter เริ่มต้นด้วยnewมันเป็นของnoneตระกูลเมธอดเมื่อเทียบกับnewตระกูลเมธอด:

    #ifndef __has_attribute
    #define __has_attribute(x) 0  // Compatibility with non-clang compilers
    #endif
    
    #if __has_attribute(objc_method_family)
    #define BV_OBJC_METHOD_FAMILY_NONE __attribute__((objc_method_family(none)))
    #else
    #define BV_OBJC_METHOD_FAMILY_NONE
    #endif
    
    @interface ViewController : UIViewController
    @property (strong, nonatomic) NSString *newTitle;
    - (NSString *)newTitle BV_OBJC_METHOD_FAMILY_NONE;
    @end

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


สำหรับบันทึก Apple ได้เผยแพร่Transitioning เป็น ARC Release Notesซึ่งระบุว่า:

คุณไม่สามารถให้คุณสมบัติชื่อที่ขึ้นต้นด้วยหรือnewcopy

พวกเขาได้รับแจ้งว่าคำสั่งของพวกเขาไม่ถูกต้องนัก: ผู้ร้ายคือชื่อเมธอด getter ไม่ใช่ชื่อคุณสมบัติ


แก้ไข 17 มกราคม 2558:ฉันเพิ่งสังเกตเห็นความมุ่งมั่นล่าสุดต่อ Clangที่แนะนำตัวเลือก 3 ด้านบน (โดยใช้objc_method_family(none)) รวมถึงตัวแก้ไขสำหรับกรณีทั่วไปที่ชื่อคุณสมบัติตรงกับหนึ่งในคำนำหน้าตระกูลวิธีการพิเศษ Xcode มีแนวโน้มที่จะรวมการเปลี่ยนแปลงนี้ในที่สุด


6
ทำงานเหมือนคนมีเสน่ห์ !! ขอบคุณ !!! สำหรับการอ้างอิงในอนาคต - ฉันใช้ "@property (strong, nonatomic, getter = theNewTitle) NSString * newTitle;"
Noam

8
คำตอบที่ยอดเยี่ยม ฉันมีตัวแปรนำหน้า "ใหม่"

ฉันมีปัญหานี้ด้วยและเสียเวลามาก! คุณเป็นอัจฉริยะจริงๆ ~ ขอบคุณ!
H Lai

NS_RETURNS_NOT_RETAINEDเป็นสิ่งที่คุณต้องการเช่นกัน
DawnSong

55

ชื่อวัตถุที่ยอมรับไม่ได้

  • newButton
  • copyLabel
  • allocTitle

ชื่อวัตถุที่ยอมรับได้

  • neueButton
  • mCopyLabel
  • _allocTitle

#arc # สังเคราะห์อัตโนมัติ # xcode-4.6.1

** แก้ไข **

เห็นได้ชัดว่าคุณไม่สามารถใช้mutableCopy ได้เช่นกัน


1
ฉันยังสังเกตเห็นว่าไม่สามารถใช้ "การคัดลอก" ได้ในขณะนี้
Rishab

30

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


8

ARC ไม่อนุญาตให้ใช้ "ใหม่ .... " ในชื่อคุณสมบัติ แต่คุณสามารถใช้ "newTitle" ได้โดยเปลี่ยนชื่อ getter

@property (nonatomic, strong, getter=theNewTitle) NSString *newTitle;

6

ดูเหมือนว่าสิ่งที่บาวาเรียแนะนำคือสิ่งที่คุณต้องการทำ สิ่งที่คุณต้องการทำคือประกาศตัวแปรอินสแตนซ์NewTitleแล้วสังเคราะห์คุณสมบัติ เราเคยต้องประกาศตัวแปรอินสแตนซ์และคุณสมบัติ ไม่มีอีกแล้ว

ตอนนี้ฉันเชื่อว่าวิธีที่ถูกต้องในการทำเช่นนี้คือ:

.h

@interface ViewController : UIViewController

@property (nonatomic, strong) NSString *newTitle;

.m

@synthesize newTitle = _newTitle; // Use instance variable _newTitle for storage

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

ดูตัวอย่าง: การประกาศคุณสมบัติและการสังเคราะห์ตัวเข้าถึง


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

ฉันไม่คิดว่าคุณจะแก้ไขปัญหา สำหรับ Xcode 9 เป็นข้อผิดพลาดไม่ใช่คำเตือน NS_RETURNS_NOT_RETAINEDคือสิ่งที่คุณต้องการ
DawnSong

4

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

ไม่มีบันทึกข้อผิดพลาดและบรรทัดที่แสดงพร้อมกับ "จุดพักข้อยกเว้นทั้งหมด" จะไม่ช่วยคุณเลย


3

การเขียน setter ด้วยตนเองโดยใช้ชื่อเดียวกับคำเตือนนี้


ใน Xcode 7.3 สิ่งนี้ไม่ได้ช่วย ข้อผิดพลาดยังคงปรากฏบนบรรทัดคำจำกัดความของคุณสมบัติ
arlomedia

1

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

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

อีกอย่าง: ลองตั้งชื่อฟังก์ชั่นและเมธอดด้วยกริยาก่อนเช่น setSomething หรือ getSomething แต่ในคุณสมบัติพยายามตั้งชื่อวัตถุเป็นอันดับแรกเช่น heightMinimum, heightMaximum, ฯลฯ -> เมื่อคุณใช้ตัวตรวจสอบของคุณเมื่อคุณทำการเข้ารหัสคุณจะมองหาวัตถุอยู่เสมอ ลองดู ;-)


1

NS_RETURNS_NOT_RETAINED ใช้สำหรับแก้ปัญหาการตั้งชื่อ

@property (nonatomic, copy) NSString *newTitle NS_RETURNS_NOT_RETAINED;

เราสามารถค้นหาคำจำกัดความของมันได้ดังนี้

#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))

แอตทริบิวต์ 'ns_returns_not_retained' เป็นส่วนเสริมของ 'ns_returns_retained' ในกรณีที่ฟังก์ชั่นหรือวิธีการอาจปฏิบัติตามอนุสัญญาโกโก้และส่งคืนวัตถุโกโก้ที่เก็บรักษาไว้คุณลักษณะนี้สามารถใช้เพื่อระบุว่าการอ้างอิงวัตถุที่ส่งคืนไม่ควรถือเป็นการอ้างอิง "เป็นเจ้าของ" ที่ส่งคืนไปยังผู้โทร เฟรมเวิร์กพื้นฐานกำหนดแมโคร NS_RETURNS_NOT_RETAINED ที่เทียบเท่ากับที่แสดงด้านล่าง

แนบรายละเอียดเพิ่มเติมที่นี่


-2

ลองนี้: -

@property (nonatomic,retain) NSString *newTitle;

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