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


101

คุณสมบัติใน Objective-C 2.0 จำเป็นต้องมีการประกาศตัวแปรอินสแตนซ์ที่เกี่ยวข้องหรือไม่ ตัวอย่างเช่นฉันเคยทำสิ่งนี้:

MyObject.h

@interface MyObject : NSObject {
NSString *name;
}
@property (nonatomic, retain) NSString *name;
@end

MyObject.m

@implementation
@synthesize name;
@end

อย่างไรก็ตามถ้าฉันทำสิ่งนี้แทน:

MyObject.h

@interface MyObject : NSObject {
}
@property (nonatomic, retain) NSString *name;
@end

ตอนนี้ยังใช้ได้ไหม และมันแตกต่างจากตัวอย่างก่อนหน้านี้หรือไม่?


เหตุใด 'MyObject.h' ที่สองจึงเป็นตัวหนาไม่ใช่ "MyObject.m"
Ríomhaire

คำตอบ:


93

หากคุณใช้ Modern Objective-C Runtime (นั่นคือ iOS 3.x ขึ้นไปหรือ Snow Leopard 64 บิตขึ้นไป) คุณไม่จำเป็นต้องกำหนด ivars สำหรับคุณสมบัติของคุณในกรณีเช่นนี้

เมื่อคุณได้@synthesizeทรัพย์สินไอวาร์ก็จะถูกสังเคราะห์ให้คุณด้วย สิ่งนี้จะเข้าใกล้สถานการณ์ "เปราะบาง - ไอวาร์" คุณสามารถอ่านเพิ่มเติมเกี่ยวกับCocoa with Love


71

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

คุณสามารถแทนที่ getter / setter ที่เข้ารหัสอัตโนมัติได้ตลอดเวลาโดยระบุของคุณเอง โดยปกติจะทำกับmanagedObjectContextคุณสมบัติที่โหลดอย่างเกียจคร้าน ดังนั้นคุณจึงประกาศว่าคุณmanagedObjectContextเป็นทรัพย์สิน แต่ก็เขียน-(NSManagedObjectContext *)managedObjectContextวิธีการด้วย จำไว้ว่าเมธอดซึ่งมีชื่อเดียวกับตัวแปรอินสแตนซ์ / คุณสมบัติคือเมธอด "getter"

@propertyวิธีประกาศนี้ยังช่วยให้คุณมีตัวเลือกอื่น ๆ เช่นretainและreadonlyซึ่งตัวแปรเช่นวิธีการประกาศไม่ได้ โดยพื้นฐานแล้วivarเป็นวิธีการแบบเก่าและ@propertyขยายออกไปและทำให้มันดูเพ้อฝัน / ง่ายขึ้น คุณสามารถอ้างถึงโดยใช้ตัวเอง คำนำหน้าหรือไม่ไม่สำคัญตราบใดที่ชื่อยังไม่ซ้ำกับคลาสนั้น มิฉะนั้นถ้าซุปเปอร์คลาสของคุณมีชื่อคุณสมบัติเดียวกับคุณคุณจะต้องพูดเช่น self.name หรือ super.name เพื่อระบุชื่อที่คุณกำลังพูดถึง

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

หวังว่านี่จะช่วยล้างความสับสนและข้อมูลที่ผิด ๆ ที่ลอยอยู่รอบ ๆ ออกไป


วันนี้ไม่จำเป็นต้องเขียน @synthesize ดังนั้นคำตอบนี้ใช้ได้อย่างไรในกรณีนั้น!
raaz

คุณไม่ต้องประกาศ <code> @property ... @ สังเคราะห์ </code> การใช้การสังเคราะห์ช่วยให้คุณไม่ต้องเขียน getter / setter ในการนำไปใช้งาน ถ้าคุณไม่สังเคราะห์คุณต้องม้วนตัวรับ / เซ็ตเตอร์ของคุณเอง
PapaSmurf

2
@PapaSmurf ไม่ถูกต้อง คุณสามารถใช้@propertyและไม่ใช้@synthesizeและไม่ได้ใช้งานด้วยตนเอง คอมไพเลอร์จะอัตโนมัติsynthesizeให้คุณโดยไม่ต้องเขียนอีกต่อไป
jbrennan

8

มันใช้ได้ทั้งสองวิธี แต่ถ้าคุณไม่ได้ประกาศไว้ในวงเล็บปีกกาคุณจะไม่เห็นค่าของมันในตัวดีบั๊กใน xcode


3

จากเอกสารประกอบ:

โดยทั่วไปลักษณะการทำงานของคุณสมบัติจะเหมือนกันทั้งในรันไทม์ที่ทันสมัยและแบบเดิม (ดู“ เวอร์ชันรันไทม์และแพลตฟอร์ม” ใน Objective-C Runtime Programming Guide) มีข้อแตกต่างที่สำคัญประการหนึ่งคือรันไทม์ที่ทันสมัยรองรับการสังเคราะห์ตัวแปรอินสแตนซ์ในขณะที่รันไทม์เดิมไม่ได้

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


3

หากคุณใช้ XCode 4.4 หรือใหม่กว่ามันจะสร้างโค้ดสังเคราะห์ตัวแปรอินสแตนซ์ให้คุณ

คุณต้องประกาศคุณสมบัติดังต่อไปนี้ มันจะสร้างรหัสสังเคราะห์และรหัสประกาศตัวแปรอินสแตนซ์ให้คุณ

@property (nonatomic, strong) NSString *name;

มันจะสร้างรหัสสังเคราะห์เป็น

@synthesize name = _name;

และคุณสามารถเข้าถึงตัวแปรอินสแตนซ์โดยใช้ _name ซึ่งคล้ายกับการประกาศ

NSString* _name

แต่ถ้าคุณประกาศคุณสมบัติแบบอ่านอย่างเดียวก็ชอบ

@property (nonatomic, strong, readonly) NSString *name;

มันจะสร้างรหัส

@synthesize name;

หรือ

@synthesize name = name; 

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

@synthesize name = _name;

1

ภาษาโปรแกรม Objective-C: คำสั่งการนำไปใช้งานคุณสมบัติ

มีความแตกต่างในลักษณะการทำงานของการสังเคราะห์ตัวเข้าถึงที่ขึ้นอยู่กับรันไทม์ (ดูเพิ่มเติมที่“ ความแตกต่างของรันไทม์”):

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

  • สำหรับรันไทม์ที่ทันสมัย ​​(ดู“ เวอร์ชันรันไทม์และแพลตฟอร์ม” ใน Objective-C Runtime Programming Guide) ตัวแปรอินสแตนซ์จะถูกสังเคราะห์ตามความจำเป็น หากมีตัวแปรอินสแตนซ์ที่มีชื่อเดียวกันอยู่แล้วจะใช้

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