คู่มือฉบับย่อ Objective-C
Objective-C เป็นภาษาวัตถุประสงค์ทั่วไปที่ได้รับการพัฒนาขึ้นจากภาษาโปรแกรม C โดยการเพิ่มคุณสมบัติของภาษาโปรแกรม Small Talk ทำให้เป็นภาษาเชิงวัตถุ ส่วนใหญ่จะใช้ในการพัฒนาระบบปฏิบัติการ iOS และ Mac OS X รวมถึงแอพพลิเคชั่น
ในขั้นต้น Objective-C ได้รับการพัฒนาโดย NeXT สำหรับ NeXTSTEP OS ซึ่ง Apple ถูกยึดครองสำหรับ iOS และ Mac OS X
การเขียนโปรแกรมเชิงวัตถุ
รองรับการเขียนโปรแกรมเชิงวัตถุอย่างเต็มที่รวมถึงเสาหลักทั้งสี่ของการพัฒนาเชิงวัตถุ -
- Encapsulation
- การซ่อนข้อมูล
- Inheritance
- Polymorphism
ตัวอย่างรหัส
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSLog (@"hello world");
[pool drain];
return 0;
}
กรอบมูลนิธิ
Foundation Framework มีคุณสมบัติมากมายและแสดงไว้ด้านล่าง
ประกอบด้วยรายการประเภทข้อมูลเพิ่มเติมเช่น NSArray, NSDictionary, NSSet และอื่น ๆ
ประกอบด้วยชุดฟังก์ชันมากมายที่จัดการไฟล์สตริงและอื่น ๆ
มันมีคุณสมบัติสำหรับการจัดการ URL ยูทิลิตี้เช่นการจัดรูปแบบวันที่การจัดการข้อมูลการจัดการข้อผิดพลาด ฯลฯ
จุดประสงค์การเรียนรู้ -C
สิ่งที่สำคัญที่สุดที่ต้องทำเมื่อเรียนรู้ Objective-C คือการมุ่งเน้นไปที่แนวคิดและอย่าหลงในรายละเอียดทางเทคนิคของภาษา
จุดประสงค์ของการเรียนรู้ภาษาโปรแกรมคือการเป็นโปรแกรมเมอร์ที่ดีขึ้น นั่นคือจะมีประสิทธิภาพมากขึ้นในการออกแบบและใช้ระบบใหม่และการดูแลระบบเก่า
การใช้ Objective-C
Objective-C ตามที่กล่าวไว้ก่อนหน้านี้ใช้ใน iOS และ Mac OS X มีฐานผู้ใช้ iOS จำนวนมากและผู้ใช้ Mac OS X เพิ่มขึ้นเป็นส่วนใหญ่ และเนื่องจาก Apple ให้ความสำคัญกับคุณภาพเป็นอันดับแรกและยอดเยี่ยมสำหรับผู้ที่เริ่มเรียนรู้ Objective-C
การตั้งค่าสภาพแวดล้อมท้องถิ่น
หากคุณยังคงเต็มใจที่จะตั้งค่าสภาพแวดล้อมของคุณสำหรับภาษาการเขียนโปรแกรม Objective-C คุณต้องมีซอฟต์แวร์สองตัวต่อไปนี้ที่มีอยู่ในคอมพิวเตอร์ของคุณ (a) Text Editor และ (b) The GCC Compiler
แก้ไขข้อความ
สิ่งนี้จะใช้ในการพิมพ์โปรแกรมของคุณ ตัวอย่างของตัวแก้ไขบางตัว ได้แก่ Windows Notepad, OS Edit command, Brief, Epsilon, EMACS และ vim หรือ vi
ชื่อและเวอร์ชันของโปรแกรมแก้ไขข้อความอาจแตกต่างกันไปตามระบบปฏิบัติการต่างๆ ตัวอย่างเช่น Notepad จะใช้กับ Windows และสามารถใช้ vim หรือ vi บน windows ได้เช่นเดียวกับ Linux หรือ UNIX
ไฟล์ที่คุณสร้างด้วยโปรแกรมแก้ไขเรียกว่าไฟล์ต้นฉบับและมีซอร์สโค้ดของโปรแกรม ไฟล์ต้นฉบับสำหรับโปรแกรม Objective-C มักมีชื่อนามสกุลว่า ".m".
ก่อนเริ่มการเขียนโปรแกรมตรวจสอบให้แน่ใจว่าคุณมีโปรแกรมแก้ไขข้อความหนึ่งตัวและคุณมีประสบการณ์เพียงพอในการเขียนโปรแกรมคอมพิวเตอร์บันทึกลงในไฟล์รวบรวมและดำเนินการในที่สุด
คอมไพเลอร์ GCC
ซอร์สโค้ดที่เขียนในซอร์สไฟล์เป็นซอร์สที่มนุษย์สามารถอ่านได้สำหรับโปรแกรมของคุณ จำเป็นต้อง "คอมไพล์" เพื่อเปลี่ยนเป็นภาษาเครื่องเพื่อให้ CPU ของคุณสามารถรันโปรแกรมได้จริงตามคำแนะนำที่ให้ไว้
คอมไพเลอร์ GCC นี้จะใช้ในการคอมไพล์ซอร์สโค้ดของคุณลงในโปรแกรมสุดท้าย ฉันถือว่าคุณมีความรู้พื้นฐานเกี่ยวกับคอมไพเลอร์ภาษาโปรแกรม
คอมไพเลอร์ GCC มีให้ใช้งานฟรีบนแพลตฟอร์มต่างๆและขั้นตอนการตั้งค่าบนแพลตฟอร์มต่างๆมีอธิบายไว้ด้านล่าง
การติดตั้งบน UNIX / Linux
ขั้นตอนเริ่มต้นคือติดตั้ง gcc พร้อมกับแพ็คเกจ gcc Objective-C ทำได้โดย -
$ su - $ yum install gcc
$ yum install gcc-objc
ขั้นตอนต่อไปคือการตั้งค่าการอ้างอิงแพ็คเกจโดยใช้คำสั่งต่อไปนี้ -
$ yum install make libpng libpng-devel libtiff libtiff-devel libobjc
libxml2 libxml2-devel libX11-devel libXt-devel libjpeg libjpeg-devel
เพื่อรับคุณสมบัติเต็มรูปแบบของ Objective-C ให้ดาวน์โหลดและติดตั้ง GNUStep ซึ่งสามารถทำได้โดยดาวน์โหลดแพ็คเกจจากhttp://main.gnustep.org/resources/downloads.php.
ตอนนี้เราต้องเปลี่ยนไปใช้โฟลเดอร์ที่ดาวน์โหลดมาและคลายไฟล์โดย -
$ tar xvfz gnustep-startup-
.tar.gz
ตอนนี้เราต้องเปลี่ยนไปใช้โฟลเดอร์ gnustep-startup ที่สร้างขึ้นโดยใช้ -
$ cd gnustep-startup-<version>
ต่อไปเราต้องกำหนดค่ากระบวนการสร้าง -
$ ./configure
จากนั้นเราสามารถสร้างโดย -
$ make
ในที่สุดเราต้องตั้งค่าสภาพแวดล้อมโดย -
$ . /usr/GNUstep/System/Library/Makefiles/GNUstep.sh
เรามี helloWorld.m Objective-C ดังนี้ -
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSLog (@"hello world");
[pool drain];
return 0;
}
ตอนนี้เราสามารถคอมไพล์และเรียกใช้ไฟล์ Objective-C พูดว่า helloWorld.m ได้โดยเปลี่ยนไปใช้โฟลเดอร์ที่มีไฟล์โดยใช้ cd จากนั้นทำตามขั้นตอนต่อไปนี้ -
$ gcc `gnustep-config --objc-flags`
-L/usr/GNUstep/Local/Library/Libraries
-lgnustep-base helloWorld.m -o helloWorld
$ ./helloWorld
เราสามารถดูผลลัพธ์ต่อไปนี้ -
2013-09-07 10:48:39.772 tutorialsPoint[12906] hello world
การติดตั้งบน Mac OS
หากคุณใช้ Mac OS X วิธีที่ง่ายที่สุดในการรับ GCC คือดาวน์โหลดสภาพแวดล้อมการพัฒนา Xcode จากเว็บไซต์ของ Apple และทำตามคำแนะนำในการติดตั้งอย่างง่าย เมื่อคุณตั้งค่า Xcode แล้วคุณจะสามารถใช้คอมไพเลอร์ GNU สำหรับ C / C ++
Xcode ใช้ได้ในขณะนี้ที่developer.apple.com/technologies/tools/
การติดตั้งบน Windows
ในการรันโปรแกรม Objective-C บน windows เราจำเป็นต้องติดตั้ง MinGW และ GNUStep Core ทั้งสองอย่างมีจำหน่ายที่https://www.gnu.org/software/gnustep/windows/installer.html.
ขั้นแรกเราต้องติดตั้งแพ็คเกจ MSYS / MinGW System จากนั้นเราต้องติดตั้งแพ็คเกจ GNUstep Core ทั้งสองอย่างนี้มีตัวติดตั้ง windows ซึ่งอธิบายได้ด้วยตนเอง
จากนั้นใช้ Objective-C และ GNUstep โดยเลือก Start -> All Programs -> GNUstep -> Shell
สลับไปยังโฟลเดอร์ที่มี helloWorld.m
เราสามารถรวบรวมโปรแกรมโดยใช้ -
$ gcc `gnustep-config --objc-flags`
-L /GNUstep/System/Library/Libraries hello.m -o hello -lgnustep-base -lobjc
เราสามารถรันโปรแกรมได้โดยใช้ -
./hello.exe
เราได้ผลลัพธ์ดังต่อไปนี้ -
2013-09-07 10:48:39.772 tutorialsPoint[1200] hello world
ก่อนที่เราจะศึกษาหน่วยการสร้างพื้นฐานของภาษาการเขียนโปรแกรม Objective-C ให้เราดูโครงสร้างโปรแกรม Objective-C ขั้นต่ำที่เปลือยเปล่าเพื่อให้เราสามารถใช้เป็นข้อมูลอ้างอิงในบทต่อ ๆ ไปได้
Objective-C ตัวอย่าง Hello World
โดยทั่วไปโปรแกรม Objective-C ประกอบด้วยส่วนต่างๆดังต่อไปนี้ -
- คำสั่ง Preprocessor
- Interface
- Implementation
- Method
- Variables
- คำสั่งและนิพจน์
- Comments
ให้เราดูรหัสง่ายๆที่จะพิมพ์คำว่า "Hello World" -
#import <Foundation/Foundation.h>
@interface SampleClass:NSObject
- (void)sampleMethod;
@end
@implementation SampleClass
- (void)sampleMethod {
NSLog(@"Hello, World! \n");
}
@end
int main() {
/* my first program in Objective-C */
SampleClass *sampleClass = [[SampleClass alloc]init];
[sampleClass sampleMethod];
return 0;
}
ให้เราดูส่วนต่างๆของโปรแกรมข้างต้น -
บรรทัดแรกของโปรแกรม#import <Foundation / Foundation.h>คือคำสั่งพรีโปรเซสเซอร์ซึ่งบอกให้คอมไพเลอร์ Objective-C รวมไฟล์ Foundation.h ก่อนที่จะไปคอมไพล์จริง
บรรทัดถัดไป@interface SampleClass: NSObjectแสดงวิธีสร้างอินเทอร์เฟซ สืบทอด NSObject ซึ่งเป็นคลาสพื้นฐานของอ็อบเจ็กต์ทั้งหมด
บรรทัดถัดไป- (โมฆะ) sampleMethod; แสดงวิธีการประกาศวิธีการ
บรรทัดถัดไป@endจะเป็นจุดสิ้นสุดของอินเทอร์เฟซ
บรรทัดถัดไป@implementation SampleClassแสดงวิธีใช้อินเทอร์เฟซ SampleClass
บรรทัดถัดไป- (void) sampleMethod {}แสดงการใช้งาน sampleMethod
บรรทัดถัดไป@endหมายถึงการสิ้นสุดการใช้งาน
บรรทัดถัดไปint main ()คือฟังก์ชั่นหลักที่เริ่มการทำงานของโปรแกรม
บรรทัดถัดไป /*...*/ จะถูกคอมไพเลอร์ไม่สนใจและถูกนำไปใส่ความคิดเห็นเพิ่มเติมในโปรแกรม ดังนั้นบรรทัดดังกล่าวจึงเรียกว่าคอมเมนต์ในโปรแกรม
บรรทัดถัดไปNSLog (... )เป็นอีกฟังก์ชันที่มีอยู่ใน Objective-C ซึ่งทำให้เกิดข้อความ "Hello, World!" ที่จะแสดงบนหน้าจอ
บรรทัดถัดไป return 0; ยุติฟังก์ชัน main () และส่งกลับค่า 0
คอมไพล์และดำเนินการโปรแกรม Objective-C
ตอนนี้เมื่อเราคอมไพล์และรันโปรแกรมเราจะได้ผลลัพธ์ดังต่อไปนี้
2017-10-06 07:48:32.020 demo[65832] Hello, World!
คุณได้เห็นโครงสร้างพื้นฐานของโปรแกรม Objective-C แล้วดังนั้นจึงง่ายต่อการทำความเข้าใจโครงสร้างพื้นฐานอื่น ๆ ของภาษาโปรแกรม Objective-C
โทเค็นใน Objective-C
โปรแกรม Objective-C ประกอบด้วยโทเค็นต่างๆและโทเค็นเป็นทั้งคีย์เวิร์ดตัวระบุค่าคงสตริงลิเทอรัลหรือสัญลักษณ์ ตัวอย่างเช่นคำสั่ง Objective-C ต่อไปนี้ประกอบด้วยโทเค็นหกรายการ -
NSLog(@"Hello, World! \n");
โทเค็นแต่ละรายการคือ -
NSLog
@
(
"Hello, World! \n"
)
;
อัฒภาค;
ในโปรแกรม Objective-C อัฒภาคเป็นตัวยุติคำสั่ง นั่นคือแต่ละคำสั่งจะต้องลงท้ายด้วยอัฒภาค ระบุจุดสิ้นสุดของเอนทิตีตรรกะหนึ่ง
ตัวอย่างเช่นต่อไปนี้เป็นสองคำสั่งที่แตกต่างกัน
NSLog(@"Hello, World! \n");
return 0;
ความคิดเห็น
ความคิดเห็นเป็นเหมือนข้อความช่วยในโปรแกรม Objective-C ของคุณและคอมไพเลอร์จะเพิกเฉย เริ่มต้นด้วย / * และสิ้นสุดด้วยอักขระ * / ดังที่แสดงด้านล่าง -
/* my first program in Objective-C */
คุณไม่สามารถแสดงความคิดเห็นในความคิดเห็นได้และจะไม่เกิดขึ้นภายในสตริงหรืออักขระตามตัวอักษร
ตัวระบุ
ตัวระบุ Objective-C คือชื่อที่ใช้เพื่อระบุตัวแปรฟังก์ชันหรือรายการที่ผู้ใช้กำหนดอื่น ๆ ตัวระบุเริ่มต้นด้วยตัวอักษร A ถึง Z หรือ a ถึง z หรือขีดล่าง _ ตามด้วยตัวอักษรศูนย์หรือมากกว่าขีดล่างและตัวเลข (0 ถึง 9)
Objective-C ไม่อนุญาตให้ใช้อักขระเครื่องหมายวรรคตอนเช่น @, $ และ% ภายในตัวระบุ Objective-C คือไฟล์case-sensitiveภาษาโปรแกรม ดังนั้นกำลังคนและกำลังคนจึงเป็นตัวบ่งชี้สองตัวที่แตกต่างกันใน Objective-C นี่คือตัวอย่างบางส่วนของตัวระบุที่ยอมรับได้ -
mohd zara abc move_name a_123
myname50 _temp j a23b9 retVal
คำหลัก
รายการต่อไปนี้แสดงคำสงวนสองสามคำใน Objective-C ห้ามใช้คำสงวนเหล่านี้เป็นค่าคงที่หรือตัวแปรหรือชื่อตัวระบุอื่น ๆ
อัตโนมัติ | อื่น | ยาว | สวิตซ์ |
หยุดพัก | enum | ลงทะเบียน | typedef |
กรณี | ภายนอก | กลับ | สหภาพแรงงาน |
ถ่าน | ลอย | สั้น | ไม่ได้ลงนาม |
const | สำหรับ | ลงนาม | เป็นโมฆะ |
ดำเนินการต่อ | ไปที่ | ขนาดของ | ระเหย |
ค่าเริ่มต้น | ถ้า | คงที่ | ในขณะที่ |
ทำ | int | โครงสร้าง | _ บรรจุ |
สองเท่า | มาตรการ | อินเตอร์เฟซ | การนำไปใช้งาน |
อสส | NSInteger | NSNumber | CGFloat |
ทรัพย์สิน | ไม่ใช่อะตอม; | รักษา | แข็งแรง |
อ่อนแอ | unsafe_unretained; | อ่านเขียน | อ่านเท่านั้น |
ช่องว่างใน Objective-C
บรรทัดที่มีเฉพาะช่องว่างอาจมีข้อคิดเห็นเรียกว่าบรรทัดว่างและคอมไพเลอร์ Objective-C จะละเว้นมันโดยสิ้นเชิง
Whitespace เป็นคำที่ใช้ใน Objective-C เพื่ออธิบายช่องว่างแท็บอักขระขึ้นบรรทัดใหม่และข้อคิดเห็น ช่องว่างแยกส่วนหนึ่งของคำสั่งออกจากอีกส่วนหนึ่งและช่วยให้คอมไพเลอร์ระบุตำแหน่งที่องค์ประกอบหนึ่งในคำสั่งเช่น int สิ้นสุดลงและองค์ประกอบถัดไปเริ่มต้น ดังนั้นในข้อความต่อไปนี้ -
int age;
ต้องมีอักขระช่องว่างอย่างน้อยหนึ่งอักขระ (โดยปกติจะเป็นช่องว่าง) ระหว่าง int และอายุเพื่อให้คอมไพเลอร์สามารถแยกแยะได้ ในทางกลับกันในข้อความต่อไปนี้
fruit = apples + oranges; // get the total fruit
ไม่จำเป็นต้องใช้อักขระเว้นวรรคระหว่างผลไม้และ = หรือระหว่าง = และแอปเปิ้ลแม้ว่าคุณจะมีอิสระที่จะใส่อักขระบางตัวหากต้องการเพื่อจุดประสงค์ในการอ่าน
ในภาษาโปรแกรม Objective-C ชนิดข้อมูลหมายถึงระบบที่กว้างขวางที่ใช้สำหรับการประกาศตัวแปรหรือฟังก์ชันประเภทต่างๆ ประเภทของตัวแปรจะกำหนดพื้นที่ที่ใช้ในหน่วยเก็บข้อมูลและวิธีการตีความรูปแบบบิตที่จัดเก็บ
ประเภทใน Objective-C สามารถแบ่งได้ดังนี้ -
ซีเนียร์ | ประเภทและคำอธิบาย |
---|---|
1 | Basic Types − เป็นประเภทเลขคณิตและประกอบด้วยสองประเภท: (a) ประเภทจำนวนเต็มและ (b) ประเภททศนิยม |
2 | Enumerated types − เป็นประเภทเลขคณิตอีกครั้งและใช้เพื่อกำหนดตัวแปรที่สามารถกำหนดได้เฉพาะค่าจำนวนเต็มไม่ต่อเนื่องบางค่าตลอดทั้งโปรแกรม |
3 | The type void − ตัวระบุชนิดเป็นโมฆะระบุว่าไม่มีค่า |
4 | Derived types − ซึ่งรวมถึง (a) ประเภทตัวชี้ (b) ประเภทอาร์เรย์ (c) ประเภทโครงสร้าง (ง) ประเภทสหภาพและ (จ) ประเภทฟังก์ชัน |
ประเภทอาร์เรย์และประเภทโครงสร้างเรียกรวมกันว่าประเภทการรวม ประเภทของฟังก์ชันระบุชนิดของค่าที่ส่งกลับของฟังก์ชัน เราจะเห็นประเภทพื้นฐานในส่วนต่อไปนี้ในขณะที่ประเภทอื่น ๆ จะกล่าวถึงในบทต่อ ๆ ไป
ประเภทจำนวนเต็ม
ตารางต่อไปนี้ให้รายละเอียดเกี่ยวกับประเภทจำนวนเต็มมาตรฐานพร้อมขนาดพื้นที่จัดเก็บและช่วงค่า -
ประเภท | ขนาดการจัดเก็บ | ช่วงค่า |
---|---|---|
ถ่าน | 1 ไบต์ | -128 ถึง 127 หรือ 0 ถึง 255 |
ถ่านที่ไม่ได้ลงนาม | 1 ไบต์ | 0 ถึง 255 |
ลงนามถ่าน | 1 ไบต์ | -128 ถึง 127 |
int | 2 หรือ 4 ไบต์ | -32,768 ถึง 32,767 หรือ -2,147,483,648 ถึง 2,147,483,647 |
int ที่ไม่ได้ลงนาม | 2 หรือ 4 ไบต์ | 0 ถึง 65,535 หรือ 0 ถึง 4,294,967,295 |
สั้น | 2 ไบต์ | -32,768 ถึง 32,767 |
สั้นไม่ได้ลงนาม | 2 ไบต์ | 0 ถึง 65,535 |
ยาว | 4 ไบต์ | -2,147,483,648 ถึง 2,147,483,647 |
ไม่ได้ลงนามยาว | 4 ไบต์ | 0 ถึง 4,294,967,295 |
หากต้องการรับขนาดที่แน่นอนของประเภทหรือตัวแปรบนแพลตฟอร์มใดแพลตฟอร์มหนึ่งคุณสามารถใช้ไฟล์ sizeofตัวดำเนินการ นิพจน์sizeof (type)ให้ขนาดหน่วยเก็บข้อมูลของอ็อบเจ็กต์หรือพิมพ์เป็นไบต์ ต่อไปนี้เป็นตัวอย่างเพื่อรับขนาดของประเภท int บนเครื่องใด ๆ -
#import <Foundation/Foundation.h>
int main() {
NSLog(@"Storage size for int : %d \n", sizeof(int));
return 0;
}
เมื่อคุณคอมไพล์และรันโปรแกรมข้างต้นโปรแกรมจะสร้างผลลัพธ์ต่อไปนี้บน Linux -
2013-09-07 22:21:39.155 demo[1340] Storage size for int : 4
ประเภทจุดลอยตัว
ตารางต่อไปนี้ให้รายละเอียดเกี่ยวกับประเภทจุดลอยตัวมาตรฐานพร้อมขนาดพื้นที่จัดเก็บและช่วงค่าและความแม่นยำ -
ประเภท | ขนาดการจัดเก็บ | ช่วงค่า | ความแม่นยำ |
---|---|---|---|
ลอย | 4 ไบต์ | 1.2E-38 ถึง 3.4E + 38 | ทศนิยม 6 ตำแหน่ง |
สองเท่า | 8 ไบต์ | 2.3E-308 ถึง 1.7E + 308 | ทศนิยม 15 ตำแหน่ง |
คู่ยาว | 10 ไบต์ | 3.4E-4932 ถึง 1.1E + 4932 | ทศนิยม 19 ตำแหน่ง |
ไฟล์ส่วนหัว float.h กำหนดมาโครที่อนุญาตให้คุณใช้ค่าเหล่านี้และรายละเอียดอื่น ๆ เกี่ยวกับการแทนค่าเลขฐานสองของจำนวนจริงในโปรแกรมของคุณ ตัวอย่างต่อไปนี้จะพิมพ์พื้นที่เก็บข้อมูลที่ถ่ายโดยประเภทลอยและค่าช่วง -
#import <Foundation/Foundation.h>
int main() {
NSLog(@"Storage size for float : %d \n", sizeof(float));
return 0;
}
เมื่อคุณคอมไพล์และรันโปรแกรมข้างต้นโปรแกรมจะสร้างผลลัพธ์ต่อไปนี้บน Linux -
2013-09-07 22:22:21.729 demo[3927] Storage size for float : 4
ประเภทโมฆะ
ประเภทโมฆะระบุว่าไม่มีค่า ใช้ในสถานการณ์สามประเภท -
ซีเนียร์ | ประเภทและรายละเอียด |
---|---|
1 | Function returns as void มีฟังก์ชั่นต่างๆใน Objective-C ซึ่งไม่คืนค่าหรือคุณสามารถพูดได้ว่ามันคืนค่าเป็นโมฆะ ฟังก์ชันที่ไม่มีค่าส่งคืนจะมีประเภทการส่งคืนเป็นโมฆะ ตัวอย่างเช่น,void exit (int status); |
2 | Function arguments as void มีฟังก์ชันต่างๆใน Objective-C ซึ่งไม่ยอมรับพารามิเตอร์ใด ๆ ฟังก์ชันที่ไม่มีพารามิเตอร์สามารถยอมรับว่าเป็นโมฆะ ตัวอย่างเช่น,int rand(void); |
ในตอนนี้คุณอาจไม่เข้าใจประเภทโมฆะดังนั้นให้เราดำเนินการต่อและเราจะกล่าวถึงแนวคิดเหล่านี้ในบทต่อ ๆ ไป
ตัวแปรไม่ใช่อะไรนอกจากชื่อที่กำหนดให้กับพื้นที่จัดเก็บที่โปรแกรมของเราสามารถจัดการได้ ตัวแปรแต่ละตัวใน Objective-C มีประเภทเฉพาะซึ่งกำหนดขนาดและรูปแบบของหน่วยความจำของตัวแปร ช่วงของค่าที่สามารถเก็บไว้ในหน่วยความจำนั้น และชุดของการดำเนินการที่สามารถนำไปใช้กับตัวแปร
ชื่อของตัวแปรสามารถประกอบด้วยตัวอักษรตัวเลขและอักขระขีดล่าง ต้องขึ้นต้นด้วยตัวอักษรหรือขีดล่าง อักษรตัวพิมพ์ใหญ่และตัวพิมพ์เล็กมีความแตกต่างกันเนื่องจาก Objective-C คำนึงถึงตัวพิมพ์เล็กและใหญ่ จากประเภทพื้นฐานที่อธิบายไว้ในบทที่แล้วจะมีประเภทตัวแปรพื้นฐานดังต่อไปนี้ -
ซีเนียร์ | ประเภทและคำอธิบาย |
---|---|
1 | char โดยทั่วไปเป็นอ็อกเต็ตเดี่ยว (หนึ่งไบต์) นี่คือประเภทจำนวนเต็ม |
2 | int ขนาดของจำนวนเต็มที่เป็นธรรมชาติที่สุดสำหรับเครื่อง |
3 | float ค่าทศนิยมที่มีความแม่นยำเดียว |
4 | double ค่าทศนิยมที่มีความแม่นยำสองเท่า |
5 | void แสดงถึงการไม่มีประเภท |
ภาษาโปรแกรม Objective-C ยังอนุญาตให้กำหนดตัวแปรประเภทอื่น ๆ ได้อีกด้วยซึ่งเราจะกล่าวถึงในบทต่อ ๆ ไปเช่น Enumeration, Pointer, Array, Structure, Union เป็นต้นสำหรับบทนี้ให้เราศึกษาเฉพาะตัวแปรพื้นฐานประเภทต่างๆ
นิยามตัวแปรใน Objective-C
นิยามตัวแปรหมายถึงการบอกคอมไพเลอร์ว่าจะสร้างหน่วยเก็บข้อมูลสำหรับตัวแปรได้ที่ไหนและเท่าใด นิยามตัวแปรระบุชนิดข้อมูลและมีรายการตัวแปรประเภทนั้นอย่างน้อยหนึ่งรายการดังนี้ -
type variable_list;
ที่นี่ type ต้องเป็นชนิดข้อมูล Objective-C ที่ถูกต้องซึ่งรวมถึง char, w_char, int, float, double, bool หรือออบเจ็กต์ที่ผู้ใช้กำหนดเองเป็นต้นและ variable_listอาจประกอบด้วยชื่อตัวบ่งชี้อย่างน้อยหนึ่งชื่อโดยคั่นด้วยเครื่องหมายจุลภาค การประกาศที่ถูกต้องบางส่วนแสดงไว้ที่นี่ -
int i, j, k;
char c, ch;
float f, salary;
double d;
เส้น int i, j, k;ทั้งประกาศและกำหนดตัวแปร i, j และ k; ซึ่งสั่งให้คอมไพเลอร์สร้างตัวแปรชื่อ i, j และ k ประเภท int
ตัวแปรสามารถเริ่มต้นได้ (กำหนดค่าเริ่มต้น) ในการประกาศ initializer ประกอบด้วยเครื่องหมายเท่ากับตามด้วยนิพจน์คงที่ดังนี้ -
type variable_name = value;
ตัวอย่างบางส่วน ได้แก่ -
extern int d = 3, f = 5; // declaration of d and f.
int d = 3, f = 5; // definition and initializing d and f.
byte z = 22; // definition and initializes z.
char x = 'x'; // the variable x has the value 'x'.
สำหรับนิยามที่ไม่มีตัวเริ่มต้น: ตัวแปรที่มีระยะเวลาการจัดเก็บแบบคงที่จะเริ่มต้นโดยปริยายด้วย NULL (ไบต์ทั้งหมดมีค่า 0) ไม่ได้กำหนดค่าเริ่มต้นของตัวแปรอื่น ๆ ทั้งหมด
การประกาศตัวแปรใน Objective-C
การประกาศตัวแปรให้การรับรองกับคอมไพลเลอร์ว่ามีตัวแปรหนึ่งตัวที่มีอยู่ในประเภทและชื่อที่กำหนดเพื่อให้คอมไพลเลอร์ดำเนินการรวบรวมต่อไปโดยไม่ต้องการรายละเอียดทั้งหมดเกี่ยวกับตัวแปร การประกาศตัวแปรมีความหมายในช่วงเวลาของการคอมไพเลอร์เท่านั้นคอมไพเลอร์ต้องการการประกาศตัวแปรจริงในขณะที่เชื่อมโยงโปรแกรม
การประกาศตัวแปรมีประโยชน์เมื่อคุณใช้หลายไฟล์และคุณกำหนดตัวแปรของคุณในไฟล์ใดไฟล์หนึ่งซึ่งจะพร้อมใช้งานเมื่อทำการเชื่อมโยงโปรแกรม คุณจะใช้externคีย์เวิร์ดเพื่อประกาศตัวแปร ณ ที่ใด ๆ แม้ว่าคุณจะสามารถประกาศตัวแปรได้หลายครั้งในโปรแกรม Objective-C ของคุณ แต่สามารถกำหนดได้เพียงครั้งเดียวในไฟล์ฟังก์ชันหรือบล็อกโค้ด
ตัวอย่าง
ลองใช้ตัวอย่างต่อไปนี้ซึ่งมีการประกาศตัวแปรไว้ที่ด้านบนสุด แต่ได้รับการกำหนดและเริ่มต้นภายในฟังก์ชันหลัก -
#import <Foundation/Foundation.h>
// Variable declaration:
extern int a, b;
extern int c;
extern float f;
int main () {
/* variable definition: */
int a, b;
int c;
float f;
/* actual initialization */
a = 10;
b = 20;
c = a + b;
NSLog(@"value of c : %d \n", c);
f = 70.0/3.0;
NSLog(@"value of f : %f \n", f);
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-07 22:43:31.695 demo[14019] value of c : 30
2013-09-07 22:43:31.695 demo[14019] value of f : 23.333334
แนวคิดเดียวกันนี้ใช้กับการประกาศฟังก์ชันที่คุณระบุชื่อฟังก์ชันในขณะที่ประกาศและสามารถกำหนดนิยามที่แท้จริงได้จากที่อื่น ในตัวอย่างต่อไปนี้อธิบายโดยใช้ฟังก์ชัน C และอย่างที่คุณทราบ Objective-C รองรับฟังก์ชันสไตล์ C ด้วย -
// function declaration
int func();
int main() {
// function call
int i = func();
}
// function definition
int func() {
return 0;
}
Lvalues และ Rvalues ใน Objective-C
มีนิพจน์สองประเภทใน Objective-C -
lvalue- นิพจน์ที่อ้างถึงตำแหน่งหน่วยความจำเรียกว่านิพจน์ "lvalue" ค่า lvalue อาจปรากฏเป็นด้านซ้ายหรือด้านขวาของงาน
rvalue- คำว่า rvalue หมายถึงค่าข้อมูลที่เก็บไว้ที่ที่อยู่บางส่วนในหน่วยความจำ rvalue คือนิพจน์ที่ไม่สามารถกำหนดค่าได้ซึ่งหมายความว่า rvalue อาจปรากฏทางด้านขวา แต่ไม่ใช่ด้านซ้ายของงาน
ตัวแปรคือ lvalues ดังนั้นจึงอาจปรากฏทางด้านซ้ายมือของงาน ตัวอักษรตัวเลขเป็นค่า r จึงไม่สามารถกำหนดได้และจะไม่ปรากฏทางด้านซ้ายมือ ต่อไปนี้เป็นคำสั่งที่ถูกต้อง -
int g = 20;
แต่ต่อไปนี้ไม่ใช่คำสั่งที่ถูกต้องและจะสร้างข้อผิดพลาดเวลาคอมไพล์ -
10 = 20;
ค่าคงที่หมายถึงค่าคงที่ซึ่งโปรแกรมไม่สามารถเปลี่ยนแปลงได้ในระหว่างการดำเนินการ ค่าคงที่เหล่านี้เรียกอีกอย่างว่าliterals.
คงสามารถใด ๆ ของชนิดข้อมูลพื้นฐานเช่นค่าคงที่จำนวนเต็มคงลอยค่าคงที่ตัวอักษรหรือตัวอักษรสตริง นอกจากนี้ยังมีค่าคงที่การแจงนับเช่นกัน
constants ได้รับการปฏิบัติเช่นเดียวกับตัวแปรทั่วไปยกเว้นว่าไม่สามารถแก้ไขค่าหลังจากนิยามได้
ตัวอักษรจำนวนเต็ม
ลิเทอรัลจำนวนเต็มสามารถเป็นค่าคงที่ทศนิยมฐานแปดหรือฐานสิบหก คำนำหน้าระบุฐานหรือรัศมี: 0x หรือ 0X สำหรับเลขฐานสิบหก, 0 สำหรับฐานแปดและไม่มีอะไรเป็นทศนิยม
ลิเทอรัลจำนวนเต็มยังสามารถมีส่วนต่อท้ายที่รวมกันของ U และ L สำหรับไม่ได้ลงนามและยาวตามลำดับ คำต่อท้ายสามารถเป็นตัวพิมพ์ใหญ่หรือตัวพิมพ์เล็กและสามารถเรียงลำดับอย่างไรก็ได้
นี่คือตัวอย่างบางส่วนของตัวอักษรจำนวนเต็ม -
212 /* Legal */
215u /* Legal */
0xFeeL /* Legal */
078 /* Illegal: 8 is not an octal digit */
032UU /* Illegal: cannot repeat a suffix */
ต่อไปนี้เป็นตัวอย่างอื่น ๆ ของตัวอักษรจำนวนเต็มประเภทต่างๆ -
85 /* decimal */
0213 /* octal */
0x4b /* hexadecimal */
30 /* int */
30u /* unsigned int */
30l /* long */
30ul /* unsigned long */
ตัวอักษรทศนิยม
ลิเทอรัลจุดลอยตัวมีส่วนจำนวนเต็มจุดทศนิยมส่วนเศษส่วนและส่วนเลขชี้กำลัง คุณสามารถแสดงลิเทอรัลจุดลอยตัวได้ทั้งในรูปแบบทศนิยมหรือรูปแบบเลขชี้กำลัง
ในขณะที่แสดงโดยใช้รูปแบบทศนิยมคุณต้องใส่จุดทศนิยมเลขชี้กำลังหรือทั้งสองอย่างและในขณะที่แสดงโดยใช้รูปแบบเลขชี้กำลังคุณต้องรวมส่วนจำนวนเต็มส่วนเศษส่วนหรือทั้งสองอย่าง เลขชี้กำลังที่ลงชื่อถูกนำมาใช้โดย e หรือ E
นี่คือตัวอย่างบางส่วนของตัวอักษรทศนิยม -
3.14159 /* Legal */
314159E-5L /* Legal */
510E /* Illegal: incomplete exponent */
210f /* Illegal: no decimal or exponent */
.e55 /* Illegal: missing integer or fraction */
ค่าคงที่ของอักขระ
ตามตัวอักษรจะอยู่ในเครื่องหมายคำพูดเดี่ยวเช่น 'x' และสามารถเก็บไว้ในตัวแปรง่ายๆของ char ประเภท.
อักขระลิเทอรัลอาจเป็นอักขระธรรมดา (เช่น 'x'), ลำดับการหลีก (เช่น '\ t') หรืออักขระสากล (เช่น '\ u02C0')
มีอักขระบางตัวใน C เมื่อดำเนินการโดยแบ็กสแลชซึ่งจะมีความหมายพิเศษและใช้แทนเช่น newline (\ n) หรือ tab (\ t) ที่นี่คุณมีรายการรหัสลำดับการหลบหนีดังกล่าว -
ลำดับการหลบหนี | ความหมาย |
---|---|
\\ | \ อักขระ |
\ ' | 'ตัวละคร |
\ " | "ตัวละคร |
\? | เหรอ? ตัวละคร |
\ ก | แจ้งเตือนหรือกระดิ่ง |
\ b | Backspace |
\ ฉ | ฟีดรูปแบบ |
\ n | ขึ้นบรรทัดใหม่ |
\ r | การกลับรถ |
\ t | แท็บแนวนอน |
\ v | แท็บแนวตั้ง |
\ ooo | เลขฐานแปดหนึ่งถึงสามหลัก |
\ xhh . . | เลขฐานสิบหกของตัวเลขตั้งแต่หนึ่งหลักขึ้นไป |
ต่อไปนี้เป็นตัวอย่างในการแสดงอักขระลำดับการหลีก -
#import <Foundation/Foundation.h>
int main() {
NSLog(@"Hello\tWorld\n\n");
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-07 22:17:17.923 demo[17871] Hello World
ตัวอักษรสตริง
ตัวอักษรสตริงหรือค่าคงที่อยู่ในเครื่องหมายคำพูดคู่ "" สตริงประกอบด้วยอักขระที่คล้ายกับตัวอักษรอักขระ: อักขระธรรมดาลำดับการหลีกและอักขระสากล
คุณสามารถแบ่งบรรทัดยาวออกเป็นหลาย ๆ บรรทัดโดยใช้ตัวอักษรสตริงและแยกออกโดยใช้ช่องว่าง
นี่คือตัวอย่างบางส่วนของตัวอักษรสตริง ทั้งสามรูปแบบเป็นสตริงที่เหมือนกัน
"hello, dear"
"hello, \
dear"
"hello, " "d" "ear"
การกำหนดค่าคงที่
C มีสองวิธีง่ายๆในการกำหนดค่าคงที่ -
การใช้ #define พรีโปรเซสเซอร์
การใช้ const คำสำคัญ.
#define พรีโปรเซสเซอร์
ต่อไปนี้เป็นรูปแบบที่จะใช้ #define preprocessor เพื่อกำหนดค่าคงที่ -
#define identifier value
ตัวอย่างต่อไปนี้อธิบายโดยละเอียด -
#import <Foundation/Foundation.h>
#define LENGTH 10
#define WIDTH 5
#define NEWLINE '\n'
int main() {
int area;
area = LENGTH * WIDTH;
NSLog(@"value of area : %d", area);
NSLog(@"%c", NEWLINE);
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-07 22:18:16.637 demo[21460] value of area : 50
2013-09-07 22:18:16.638 demo[21460]
คีย์เวิร์ด const
คุณสามารถใช้ได้ const คำนำหน้าเพื่อประกาศค่าคงที่ด้วยประเภทเฉพาะดังนี้ -
const type variable = value;
ตัวอย่างต่อไปนี้อธิบายโดยละเอียด -
#import <Foundation/Foundation.h>
int main() {
const int LENGTH = 10;
const int WIDTH = 5;
const char NEWLINE = '\n';
int area;
area = LENGTH * WIDTH;
NSLog(@"value of area : %d", area);
NSLog(@"%c", NEWLINE);
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-07 22:19:24.780 demo[25621] value of area : 50
2013-09-07 22:19:24.781 demo[25621]
โปรดทราบว่าการเขียนโปรแกรมเป็นวิธีที่ดีในการกำหนดค่าคงที่ในตัวพิมพ์ใหญ่
ตัวดำเนินการคือสัญลักษณ์ที่บอกให้คอมไพเลอร์ดำเนินการจัดการทางคณิตศาสตร์หรือตรรกะเฉพาะ ภาษา Objective-C อุดมไปด้วยตัวดำเนินการในตัวและมีตัวดำเนินการประเภทต่อไปนี้ -
- ตัวดำเนินการเลขคณิต
- ตัวดำเนินการเชิงสัมพันธ์
- ตัวดำเนินการทางตรรกะ
- ตัวดำเนินการ Bitwise
- ผู้ดำเนินการมอบหมาย
- ตัวดำเนินการอื่น ๆ
บทช่วยสอนนี้จะอธิบายเกี่ยวกับเลขคณิตเชิงสัมพันธ์ตรรกะบิตการกำหนดและตัวดำเนินการอื่น ๆ ทีละรายการ
ตัวดำเนินการเลขคณิต
ตารางต่อไปนี้แสดงตัวดำเนินการทางคณิตศาสตร์ทั้งหมดที่สนับสนุนโดยภาษา Objective-C สมมติตัวแปรA ถือ 10 และตัวแปร B ถือ 20 แล้ว -
แสดงตัวอย่าง
ตัวดำเนินการ | คำอธิบาย | ตัวอย่าง |
---|---|---|
+ | เพิ่มสองตัวถูกดำเนินการ | A + B จะให้ 30 |
- | ลบตัวถูกดำเนินการที่สองจากตัวแรก | A - B จะให้ -10 |
* | คูณตัวถูกดำเนินการทั้งสอง | A * B จะให้ 200 |
/ | หารตัวเศษด้วยตัวส่วน | B / A จะให้ 2 |
% | ตัวดำเนินการโมดูลัสและส่วนที่เหลือหลังจากการหารจำนวนเต็ม | B% A จะให้ 0 |
++ | ตัวดำเนินการส่วนเพิ่มจะเพิ่มค่าจำนวนเต็มทีละหนึ่ง | A ++ จะให้ 11 |
- | ตัวดำเนินการลดจะลดค่าจำนวนเต็มทีละหนึ่ง | A-- จะให้ 9 |
ตัวดำเนินการเชิงสัมพันธ์
ตารางต่อไปนี้แสดงตัวดำเนินการเชิงสัมพันธ์ทั้งหมดที่สนับสนุนโดยภาษา Objective-C สมมติตัวแปรA ถือ 10 และตัวแปร B ถือ 20 แล้ว -
แสดงตัวอย่าง
ตัวดำเนินการ | คำอธิบาย | ตัวอย่าง |
---|---|---|
== | ตรวจสอบว่าค่าของตัวถูกดำเนินการสองตัวเท่ากันหรือไม่ ถ้าใช่เงื่อนไขจะกลายเป็นจริง | (A == B) ไม่เป็นความจริง |
! = | ตรวจสอบว่าค่าของตัวถูกดำเนินการสองตัวเท่ากันหรือไม่ ถ้าค่าไม่เท่ากันเงื่อนไขจะกลายเป็นจริง | (A! = B) เป็นจริง |
> | ตรวจสอบว่าค่าของตัวถูกดำเนินการด้านซ้ายมากกว่าค่าของตัวถูกดำเนินการด้านขวาหรือไม่ ถ้าใช่เงื่อนไขจะกลายเป็นจริง | (A> B) ไม่เป็นความจริง |
< | ตรวจสอบว่าค่าของตัวถูกดำเนินการด้านซ้ายน้อยกว่าค่าของตัวถูกดำเนินการด้านขวาหรือไม่ ถ้าใช่เงื่อนไขจะกลายเป็นจริง | (A <B) เป็นจริง |
> = | ตรวจสอบว่าค่าของตัวถูกดำเนินการด้านซ้ายมากกว่าหรือเท่ากับค่าของตัวถูกดำเนินการด้านขวาหรือไม่ ถ้าใช่เงื่อนไขจะกลายเป็นจริง | (A> = B) ไม่เป็นความจริง |
<= | ตรวจสอบว่าค่าของตัวถูกดำเนินการด้านซ้ายน้อยกว่าหรือเท่ากับค่าของตัวถูกดำเนินการด้านขวาหรือไม่ ถ้าใช่เงื่อนไขจะกลายเป็นจริง | (A <= B) เป็นจริง |
ตัวดำเนินการทางตรรกะ
ตารางต่อไปนี้แสดงตัวดำเนินการทางตรรกะทั้งหมดที่สนับสนุนโดยภาษา Objective-C สมมติตัวแปรA ถือ 1 และตัวแปร B ถือ 0 แล้ว -
แสดงตัวอย่าง
ตัวดำเนินการ | คำอธิบาย | ตัวอย่าง |
---|---|---|
&& | เรียกว่าตัวดำเนินการ Logical AND หากตัวถูกดำเนินการทั้งสองไม่ใช่ศูนย์เงื่อนไขจะกลายเป็นจริง | (A && B) เป็นเท็จ |
|| | เรียกว่า Logical OR Operator หากตัวถูกดำเนินการสองตัวใดตัวหนึ่งไม่ใช่ศูนย์เงื่อนไขจะกลายเป็นจริง | (A || B) เป็นจริง |
! | เรียกว่า Logical NOT Operator ใช้เพื่อย้อนกลับสถานะตรรกะของตัวถูกดำเนินการ หากเงื่อนไขเป็นจริงตัวดำเนินการ Logical NOT จะสร้างเท็จ | ! (A && B) เป็นเรื่องจริง |
ตัวดำเนินการ Bitwise
ตัวดำเนินการ Bitwise ทำงานบนบิตและดำเนินการทีละบิต ตารางความจริงสำหรับ &, | และ ^ มีดังนี้ -
น | q | p & q | p | q | p ^ q |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
สมมติว่า A = 60; และ B = 13; ตอนนี้ในรูปแบบไบนารีพวกเขาจะเป็นดังนี้ -
A = 0011 1100
B = 0000 1101
-----------------
A&B = 0000 1100
ก | B = 0011 1101
ก ^ B = 0011 0001
~ A = 1100 0011
ตัวดำเนินการ Bitwise ที่รองรับโดยภาษา Objective-C แสดงอยู่ในตารางต่อไปนี้ สมมติตัวแปร A ถือ 60 และตัวแปร B ถือ 13 แล้ว -
แสดงตัวอย่าง
ตัวดำเนินการ | คำอธิบาย | ตัวอย่าง |
---|---|---|
& | ไบนารี AND Operator จะคัดลอกบิตไปยังผลลัพธ์หากมีอยู่ในตัวถูกดำเนินการทั้งสอง | (A & B) จะให้ 12 ซึ่งก็คือ 0000 1100 |
| | ไบนารีหรือตัวดำเนินการจะคัดลอกบิตหากมีอยู่ในตัวถูกดำเนินการอย่างใดอย่างหนึ่ง | (A | B) จะให้ 61 ซึ่งก็คือ 0011 1101 |
^ | ตัวดำเนินการ XOR ไบนารีจะคัดลอกบิตหากตั้งค่าไว้ในตัวถูกดำเนินการเดียว แต่ไม่ใช่ทั้งสองอย่าง | (A ^ B) จะให้ 49 ซึ่งก็คือ 0011 0001 |
~ | Binary Ones Complement Operator เป็นเอกภาพและมีผลของบิต 'พลิก' | (~ A) จะให้ -61 ซึ่งก็คือ 1100 0011 ในรูปแบบประกอบของ 2 |
<< | ตัวดำเนินการกะซ้ายแบบไบนารี ค่าตัวถูกดำเนินการด้านซ้ายจะถูกย้ายไปทางซ้ายตามจำนวนบิตที่ระบุโดยตัวถูกดำเนินการด้านขวา | A << 2 จะให้ 240 ซึ่งก็คือ 1111 0000 |
>> | ตัวดำเนินการกะไบนารีขวา ค่าตัวถูกดำเนินการด้านซ้ายจะถูกย้ายไปทางขวาตามจำนวนบิตที่ระบุโดยตัวถูกดำเนินการด้านขวา | A >> 2 จะให้ 15 ซึ่งก็คือ 0000 1111 |
ผู้ดำเนินการมอบหมาย
มีตัวดำเนินการกำหนดดังต่อไปนี้ที่สนับสนุนโดยภาษา Objective-C -
แสดงตัวอย่าง
ตัวดำเนินการ | คำอธิบาย | ตัวอย่าง |
---|---|---|
= | ตัวดำเนินการกำหนดแบบง่ายกำหนดค่าจากตัวถูกดำเนินการด้านขวาไปยังตัวถูกดำเนินการด้านซ้าย | C = A + B จะกำหนดค่า A + B ให้เป็น C |
+ = | เพิ่มและกำหนดตัวดำเนินการมันจะเพิ่มตัวถูกดำเนินการด้านขวาไปยังตัวถูกดำเนินการด้านซ้ายและกำหนดผลลัพธ์ให้กับตัวถูกดำเนินการด้านซ้าย | C + = A เทียบเท่ากับ C = C + A |
- = | ตัวดำเนินการลบและกำหนดมันจะลบตัวถูกดำเนินการด้านขวาจากตัวถูกดำเนินการด้านซ้ายและกำหนดผลลัพธ์ให้กับตัวถูกดำเนินการด้านซ้าย | C - = A เทียบเท่ากับ C = C - A |
* = | ตัวดำเนินการคูณและการกำหนดมันคูณตัวถูกดำเนินการด้านขวาด้วยตัวถูกดำเนินการด้านซ้ายและกำหนดผลลัพธ์ให้กับตัวถูกดำเนินการด้านซ้าย | C * = A เทียบเท่ากับ C = C * A |
/ = | ตัวดำเนินการหารและกำหนดมันแบ่งตัวถูกดำเนินการด้านซ้ายกับตัวถูกดำเนินการด้านขวาและกำหนดผลลัพธ์ให้กับตัวถูกดำเนินการด้านซ้าย | C / = A เทียบเท่ากับ C = C / A |
% = | ตัวดำเนินการโมดูลัสและการกำหนดใช้โมดูลัสโดยใช้ตัวถูกดำเนินการสองตัวและกำหนดผลลัพธ์ให้กับตัวถูกดำเนินการด้านซ้าย | C% = A เทียบเท่ากับ C = C% A |
<< = | กะซ้ายและตัวดำเนินการกำหนด | C << = 2 เหมือนกับ C = C << 2 |
>> = | กะขวาและตัวดำเนินการกำหนด | C >> = 2 เหมือนกับ C = C >> 2 |
& = | ตัวดำเนินการกำหนด Bitwise AND | C & = 2 เหมือนกับ C = C & 2 |
^ = | บิตพิเศษ OR และตัวดำเนินการกำหนด | C ^ = 2 เหมือนกับ C = C ^ 2 |
| = | รวมบิตหรือและตัวดำเนินการกำหนด | C | = 2 เหมือนกับ C = C | 2 |
ตัวดำเนินการอื่น ๆ ↦ sizeof & ternary
มีตัวดำเนินการที่สำคัญอื่น ๆ รวมถึง sizeof และ ? : รองรับโดย Objective-C Language
แสดงตัวอย่าง
ตัวดำเนินการ | คำอธิบาย | ตัวอย่าง |
---|---|---|
ขนาดของ() | ส่งคืนขนาดของตัวแปร | sizeof (a) โดยที่ a เป็นจำนวนเต็มจะส่งกลับ 4 |
& | ส่งกลับที่อยู่ของตัวแปร | & a; จะให้ที่อยู่จริงของตัวแปร |
* | ชี้ไปที่ตัวแปร | * ก; จะชี้ไปที่ตัวแปร |
เหรอ? : | นิพจน์เงื่อนไข | ถ้า Condition เป็นจริง? จากนั้นค่า X: หรือค่า Y |
ลำดับความสำคัญของตัวดำเนินการใน Objective-C
ลำดับความสำคัญของตัวดำเนินการกำหนดการจัดกลุ่มคำศัพท์ในนิพจน์ สิ่งนี้มีผลต่อวิธีการประเมินนิพจน์ ตัวดำเนินการบางอย่างมีลำดับความสำคัญสูงกว่าผู้อื่น ตัวอย่างเช่นตัวดำเนินการคูณมีลำดับความสำคัญสูงกว่าตัวดำเนินการบวก -
ตัวอย่างเช่น x = 7 + 3 * 2; ที่นี่ x ถูกกำหนดให้เป็น 13 ไม่ใช่ 20 เนื่องจากตัวดำเนินการ * มีลำดับความสำคัญสูงกว่า + ดังนั้นจึงได้รับการคูณด้วย 3 * 2 ก่อนแล้วจึงเพิ่มเป็น 7
ที่นี่ตัวดำเนินการที่มีลำดับความสำคัญสูงสุดจะปรากฏที่ด้านบนสุดของตารางตัวดำเนินการที่มีค่าต่ำสุดจะปรากฏที่ด้านล่าง ภายในนิพจน์ตัวดำเนินการที่มีลำดับความสำคัญสูงกว่าจะได้รับการประเมินก่อน
ประเภท | ตัวดำเนินการ | ความสัมพันธ์ |
---|---|---|
Postfix | () [] ->. ++ - - | จากซ้ายไปขวา |
ยูนารี | + -! ~ ++ - - (type) * & sizeof | จากขวาไปซ้าย |
หลายหลาก | * /% | จากซ้ายไปขวา |
สารเติมแต่ง | + - | จากซ้ายไปขวา |
กะ | << >> | จากซ้ายไปขวา |
เชิงสัมพันธ์ | <<=>> = | จากซ้ายไปขวา |
ความเท่าเทียมกัน | ==! = | จากซ้ายไปขวา |
Bitwise XOR | ^ | จากซ้ายไปขวา |
Bitwise หรือ | | | จากซ้ายไปขวา |
ตรรกะ AND | && | จากซ้ายไปขวา |
ตรรกะหรือ | || | จากซ้ายไปขวา |
เงื่อนไข | ?: | จากขวาไปซ้าย |
การมอบหมายงาน | = + = - = * = / =% = >> = << = & = ^ = | = | จากขวาไปซ้าย |
จุลภาค | , | จากซ้ายไปขวา |
อาจมีสถานการณ์เมื่อคุณต้องดำเนินการบล็อกรหัสหลาย ๆ ครั้ง โดยทั่วไปคำสั่งจะดำเนินการตามลำดับ: คำสั่งแรกในฟังก์ชันจะถูกเรียกใช้งานก่อนตามด้วยคำสั่งที่สองและอื่น ๆ
ภาษาโปรแกรมจัดเตรียมโครงสร้างการควบคุมต่างๆที่ช่วยให้เส้นทางการดำเนินการซับซ้อนมากขึ้น
คำสั่งวนซ้ำช่วยให้เราดำเนินการคำสั่งหรือกลุ่มของคำสั่งได้หลายครั้งและต่อไปนี้เป็นรูปแบบทั่วไปของคำสั่งลูปในภาษาโปรแกรมส่วนใหญ่ -
ภาษาโปรแกรม Objective-C จัดเตรียมลูปประเภทต่อไปนี้เพื่อจัดการกับข้อกำหนดการวนซ้ำ คลิกลิงก์ต่อไปนี้เพื่อตรวจสอบรายละเอียด
ซีเนียร์ | ประเภทห่วงและคำอธิบาย |
---|---|
1 | ในขณะที่วนซ้ำ ทำซ้ำคำสั่งหรือกลุ่มของคำสั่งในขณะที่เงื่อนไขที่กำหนดเป็นจริง จะทดสอบเงื่อนไขก่อนที่จะดำเนินการร่างกายลูป |
2 | สำหรับห่วง เรียกใช้ลำดับของคำสั่งหลาย ๆ ครั้งและย่อโค้ดที่จัดการตัวแปรลูป |
3 | ทำ ... ในขณะที่วนซ้ำ เช่นเดียวกับคำสั่ง while ยกเว้นว่าจะทดสอบเงื่อนไขที่ส่วนท้ายของตัวห่วง |
4 | ลูปที่ซ้อนกัน คุณสามารถใช้ลูปอย่างน้อยหนึ่งลูปในอีกอันหนึ่งหรือทำ .. ในขณะที่ลูป |
คำสั่งควบคุมลูป
คำสั่งควบคุมแบบวนซ้ำเปลี่ยนการดำเนินการจากลำดับปกติ เมื่อการดำเนินการออกจากขอบเขตอ็อบเจ็กต์อัตโนมัติทั้งหมดที่สร้างขึ้นในขอบเขตนั้นจะถูกทำลาย
Objective-C สนับสนุนคำสั่งควบคุมต่อไปนี้ คลิกลิงก์ต่อไปนี้เพื่อตรวจสอบรายละเอียด
ซีเนียร์ | คำชี้แจงและคำอธิบายการควบคุม |
---|---|
1 | คำสั่งทำลาย ยุติไฟล์ loop หรือ switch คำสั่งและโอนการดำเนินการไปยังคำสั่งทันทีตามลูปหรือสวิตช์ |
2 | ดำเนินการต่อ ทำให้ลูปข้ามส่วนที่เหลือของร่างกายและทดสอบสภาพของมันใหม่ทันทีก่อนที่จะย้ำอีกครั้ง |
ห่วงไม่มีที่สิ้นสุด
ลูปจะกลายเป็นลูปไม่มีที่สิ้นสุดหากเงื่อนไขไม่เคยเป็นเท็จ forloop ถูกใช้เพื่อจุดประสงค์นี้ เนื่องจากไม่จำเป็นต้องใช้นิพจน์สามนิพจน์ที่สร้าง for loop คุณจึงสามารถสร้างการวนซ้ำแบบไม่มีที่สิ้นสุดได้โดยปล่อยให้นิพจน์เงื่อนไขว่างเปล่า
#import <Foundation/Foundation.h>
int main () {
for( ; ; ) {
NSLog(@"This loop will run forever.\n");
}
return 0;
}
เมื่อไม่มีนิพจน์เงื่อนไขจะถือว่าเป็นจริง คุณอาจมีการกำหนดค่าเริ่มต้นและนิพจน์ส่วนเพิ่ม แต่โปรแกรมเมอร์ Objective-C มักใช้โครงสร้าง for (;;) เพื่อแสดงถึงการวนซ้ำที่ไม่มีที่สิ้นสุด
โครงสร้างการตัดสินใจกำหนดให้โปรแกรมเมอร์ระบุเงื่อนไขอย่างน้อยหนึ่งเงื่อนไขที่จะประเมินหรือทดสอบโดยโปรแกรมพร้อมกับคำสั่งหรือคำสั่งที่จะดำเนินการหากเงื่อนไขถูกกำหนดให้เป็นจริงและเป็นทางเลือกที่จะดำเนินการคำสั่งอื่น ๆ หากเงื่อนไข ถูกกำหนดให้เป็นเท็จ
ต่อไปนี้เป็นรูปแบบทั่วไปของโครงสร้างการตัดสินใจทั่วไปที่พบในภาษาโปรแกรมส่วนใหญ่ -
ภาษาโปรแกรม Objective-C ถือว่าใด ๆ non-zero และ non-null ค่าเป็น trueและถ้าเป็นอย่างใดอย่างหนึ่ง zero หรือ nullจากนั้นจะถือว่าเป็น false มูลค่า.
ภาษาโปรแกรม Objective-C จัดเตรียมข้อความประกอบการตัดสินใจประเภทต่อไปนี้ คลิกลิงก์ต่อไปนี้เพื่อตรวจสอบรายละเอียด -
ซีเนียร์ | คำชี้แจงและคำอธิบาย |
---|---|
1 | ถ้าคำสั่ง อัน if statement ประกอบด้วยนิพจน์บูลีนตามด้วยหนึ่งคำสั่งขึ้นไป |
2 | if ... else คำสั่ง อัน if statement ตามด้วยตัวเลือกก็ได้ else statementซึ่งดำเนินการเมื่อนิพจน์บูลีนเป็นเท็จ |
3 | คำสั่ง if ซ้อนกัน คุณสามารถใช้ if หรือ else if คำสั่งภายในอื่น if หรือ else if คำสั่ง (s) |
4 | สลับคำสั่ง ก switch คำสั่งอนุญาตให้ทดสอบตัวแปรเพื่อความเท่าเทียมกับรายการค่า |
5 | คำสั่งสวิตช์ที่ซ้อนกัน คุณสามารถใช้ switch คำสั่งภายในอื่น switch คำสั่ง (s) |
เดอะ? : ผู้ปฏิบัติงาน
เราได้ครอบคลุม conditional operator ? : ในบทก่อนหน้าซึ่งสามารถใช้เพื่อแทนที่ if...elseงบ มีรูปแบบทั่วไปดังต่อไปนี้ -
Exp1 ? Exp2 : Exp3;
โดยที่ Exp1, Exp2 และ Exp3 เป็นนิพจน์ สังเกตการใช้และตำแหน่งของลำไส้ใหญ่
ค่าของ? นิพจน์ถูกกำหนดเช่นนี้: Exp1 ถูกประเมิน ถ้าเป็นจริง Exp2 จะถูกประเมินและกลายเป็นมูลค่าของทั้งหมด? นิพจน์. ถ้า Exp1 เป็นเท็จระบบจะประเมิน Exp3 และค่าของมันจะกลายเป็นค่าของนิพจน์
ฟังก์ชันคือกลุ่มของคำสั่งที่ทำงานร่วมกัน โปรแกรม Objective-C ทุกโปรแกรมมีฟังก์ชัน C หนึ่งฟังก์ชันซึ่งก็คือmain()และโปรแกรมที่ไม่สำคัญทั้งหมดสามารถกำหนดฟังก์ชันเพิ่มเติมได้
คุณสามารถแบ่งรหัสของคุณออกเป็นฟังก์ชันแยกกันได้ การแบ่งรหัสของคุณระหว่างฟังก์ชันต่างๆนั้นขึ้นอยู่กับคุณ แต่ในทางตรรกะแล้วการหารมักจะเป็นดังนั้นแต่ละฟังก์ชันจึงทำงานเฉพาะ
ฟังก์ชั่น declarationบอกคอมไพเลอร์เกี่ยวกับชื่อของฟังก์ชันชนิดการส่งคืนและพารามิเตอร์ ฟังก์ชั่นdefinition ให้ตัวจริงของฟังก์ชั่น
โดยทั่วไปใน Objective-C เราเรียกฟังก์ชันนี้ว่า method
เฟรมเวิร์กพื้นฐาน Objective-C มีวิธีการในตัวมากมายที่โปรแกรมของคุณสามารถเรียกใช้ได้ ตัวอย่างเช่นวิธีการappendString() เพื่อต่อท้ายสตริงเข้ากับสตริงอื่น
เมธอดเป็นที่รู้จักโดยใช้ชื่อต่างๆเช่นฟังก์ชันหรือรูทีนย่อยหรือโพรซีเดอร์เป็นต้น
การกำหนดวิธีการ
รูปแบบทั่วไปของนิยามวิธีการในภาษาโปรแกรม Objective-C มีดังนี้ -
- (return_type) method_name:( argumentType1 )argumentName1
joiningArgument2:( argumentType2 )argumentName2 ...
joiningArgumentn:( argumentTypen )argumentNamen {
body of the function
}
ความหมายวิธีการในวัตถุประสงค์การเขียนโปรแกรมภาษา C ประกอบด้วยส่วนหัววิธีการและร่างกายวิธีการ นี่คือส่วนทั้งหมดของวิธีการ -
Return Type- เมธอดอาจส่งคืนค่า return_typeคือชนิดข้อมูลของค่าที่ฟังก์ชันส่งกลับ วิธีการบางอย่างดำเนินการตามที่ต้องการโดยไม่ส่งคืนค่า ในกรณีนี้ return_type คือคีย์เวิร์ดvoid.
Method Name- นี่คือชื่อจริงของวิธีการ ชื่อเมธอดและรายการพารามิเตอร์ประกอบกันเป็นลายเซ็นเมธอด
Arguments- อาร์กิวเมนต์เป็นเหมือนตัวยึด เมื่อเรียกใช้ฟังก์ชันคุณจะส่งค่าไปยังอาร์กิวเมนต์ ค่านี้เรียกว่าพารามิเตอร์หรืออาร์กิวเมนต์จริง รายการพารามิเตอร์อ้างถึงประเภทลำดับและจำนวนอาร์กิวเมนต์ของวิธีการ อาร์กิวเมนต์เป็นทางเลือก นั่นคือวิธีการอาจไม่มีข้อโต้แย้ง
Joining Argument - การโต้แย้งการเข้าร่วมคือการทำให้อ่านง่ายขึ้นและทำให้ชัดเจนในขณะที่เรียกมัน
Method Body - เนื้อความของวิธีการประกอบด้วยชุดของคำสั่งที่กำหนดสิ่งที่วิธีการทำ
ตัวอย่าง
ต่อไปนี้เป็นซอร์สโค้ดสำหรับวิธีการที่เรียกว่า max(). วิธีนี้ใช้สองพารามิเตอร์ num1 และ num2 และส่งกลับค่าสูงสุดระหว่างสอง -
/* function returning the max between two numbers */
- (int) max:(int) num1 secondNumber:(int) num2 {
/* local variable declaration */
int result;
if (num1 > num2) {
result = num1;
} else {
result = num2;
}
return result;
}
วิธีการประกาศ
วิธีการ declarationบอกคอมไพเลอร์เกี่ยวกับชื่อฟังก์ชันและวิธีเรียกใช้เมธอด สามารถกำหนดเนื้อหาที่แท้จริงของฟังก์ชันแยกกันได้
การประกาศวิธีการมีส่วนต่างๆดังต่อไปนี้ -
- (return_type) function_name:( argumentType1 )argumentName1
joiningArgument2:( argumentType2 )argumentName2 ...
joiningArgumentn:( argumentTypen )argumentNamen;
สำหรับฟังก์ชันที่กำหนดไว้ด้านบน max () ต่อไปนี้คือการประกาศวิธีการ -
-(int) max:(int)num1 andNum2:(int)num2;
ต้องมีการประกาศเมธอดเมื่อคุณกำหนดเมธอดในซอร์สไฟล์หนึ่งและคุณเรียกใช้เมธอดนั้นในไฟล์อื่น ในกรณีนี้คุณควรประกาศฟังก์ชันที่ด้านบนของไฟล์ที่เรียกใช้ฟังก์ชัน
เรียกวิธีการ
ในขณะที่สร้างเมธอด Objective-C คุณให้คำจำกัดความของสิ่งที่ฟังก์ชันนี้ต้องทำ ในการใช้วิธีการคุณจะต้องเรียกใช้ฟังก์ชันนั้นเพื่อทำงานที่กำหนดไว้
เมื่อโปรแกรมเรียกใช้ฟังก์ชันการควบคุมโปรแกรมจะถูกโอนไปยังเมธอดที่เรียก เมธอดที่เรียกว่าทำงานที่กำหนดไว้และเมื่อคำสั่ง return ถูกเรียกใช้งานหรือเมื่อถึงวงเล็บปีกกาปิดฟังก์ชันสิ้นสุดจะส่งคืนการควบคุมโปรแกรมกลับไปที่โปรแกรมหลัก
ในการเรียกใช้เมธอดคุณเพียงแค่ส่งพารามิเตอร์ที่ต้องการพร้อมกับชื่อเมธอดและหาก method ส่งคืนค่าคุณก็สามารถจัดเก็บค่าที่ส่งคืนได้ ตัวอย่างเช่น -
#import <Foundation/Foundation.h>
@interface SampleClass:NSObject
/* method declaration */
- (int)max:(int)num1 andNum2:(int)num2;
@end
@implementation SampleClass
/* method returning the max between two numbers */
- (int)max:(int)num1 andNum2:(int)num2 {
/* local variable declaration */
int result;
if (num1 > num2) {
result = num1;
} else {
result = num2;
}
return result;
}
@end
int main () {
/* local variable definition */
int a = 100;
int b = 200;
int ret;
SampleClass *sampleClass = [[SampleClass alloc]init];
/* calling a method to get max value */
ret = [sampleClass max:a andNum2:b];
NSLog(@"Max value is : %d\n", ret );
return 0;
}
ฉันเก็บฟังก์ชัน max () ไว้พร้อมกับฟังก์ชัน main () และปฏิบัติตามซอร์สโค้ด ในขณะที่รันไฟล์ปฏิบัติการขั้นสุดท้ายจะให้ผลลัพธ์ดังนี้ -
2013-09-07 22:28:45.912 demo[26080] Max value is : 200
อาร์กิวเมนต์ของฟังก์ชัน
ถ้าฟังก์ชันจะใช้อาร์กิวเมนต์ฟังก์ชันจะต้องประกาศตัวแปรที่ยอมรับค่าของอาร์กิวเมนต์ ตัวแปรเหล่านี้เรียกว่าformal parameters ของฟังก์ชัน
พารามิเตอร์ที่เป็นทางการทำงานเหมือนกับตัวแปรท้องถิ่นอื่น ๆ ภายในฟังก์ชันและถูกสร้างขึ้นเมื่อเข้าสู่ฟังก์ชันและถูกทำลายเมื่อออก
ในขณะเรียกใช้ฟังก์ชันมีสองวิธีที่สามารถส่งผ่านอาร์กิวเมนต์ไปยังฟังก์ชัน -
ซีเนียร์ | ประเภทการโทรและคำอธิบาย |
---|---|
1 | โทรตามค่า วิธีนี้คัดลอกค่าที่แท้จริงของอาร์กิวเมนต์ลงในพารามิเตอร์ที่เป็นทางการของฟังก์ชัน ในกรณีนี้การเปลี่ยนแปลงที่เกิดขึ้นกับพารามิเตอร์ภายในฟังก์ชันจะไม่มีผลกับอาร์กิวเมนต์ |
2 | โทรตามข้อมูลอ้างอิง วิธีนี้คัดลอกที่อยู่ของอาร์กิวเมนต์ลงในพารามิเตอร์ที่เป็นทางการ ภายในฟังก์ชันนี้จะใช้แอดเดรสเพื่อเข้าถึงอาร์กิวเมนต์จริงที่ใช้ในการโทร ซึ่งหมายความว่าการเปลี่ยนแปลงที่เกิดขึ้นกับพารามิเตอร์มีผลต่ออาร์กิวเมนต์ |
โดยค่าเริ่มต้น Objective-C จะใช้ call by valueเพื่อส่งผ่านข้อโต้แย้ง โดยทั่วไปหมายความว่าโค้ดภายในฟังก์ชันไม่สามารถเปลี่ยนแปลงอาร์กิวเมนต์ที่ใช้เรียกฟังก์ชันได้และตัวอย่างที่กล่าวถึงข้างต้นในขณะที่เรียกฟังก์ชัน max () ก็ใช้วิธีการเดียวกัน
คลาส Objective-C กำหนดอ็อบเจ็กต์ที่รวมข้อมูลที่มีพฤติกรรมที่เกี่ยวข้อง บางครั้งมันก็สมเหตุสมผลที่จะเป็นตัวแทนของงานหรือหน่วยพฤติกรรมเดียวแทนที่จะเป็นวิธีการรวบรวม
Blocks เป็นคุณลักษณะระดับภาษาที่เพิ่มเข้าไปใน C, Objective-C และ C ++ ซึ่งช่วยให้คุณสามารถสร้างส่วนของโค้ดที่แตกต่างกันซึ่งสามารถส่งผ่านไปยังวิธีการหรือฟังก์ชันได้ราวกับว่าเป็นค่า บล็อกเป็นวัตถุ Objective-C ซึ่งหมายความว่าสามารถเพิ่มลงในคอลเล็กชันเช่น NSArray หรือ NSDictionary นอกจากนี้ยังมีความสามารถในการจับค่าจากขอบเขตการปิดล้อมทำให้คล้ายกับการปิดหรือแลมบ์ดาในภาษาโปรแกรมอื่น ๆ
ไวยากรณ์การประกาศบล็อกอย่างง่าย
returntype (^blockName)(argumentType);
การใช้งานบล็อกอย่างง่าย
returntype (^blockName)(argumentType)= ^{
};
นี่คือตัวอย่างง่ายๆ
void (^simpleBlock)(void) = ^{
NSLog(@"This is a block");
};
เราสามารถเรียกใช้บล็อกโดยใช้
simpleBlock();
บล็อกใช้อาร์กิวเมนต์และส่งคืนค่า
บล็อกยังสามารถรับอาร์กิวเมนต์และส่งคืนค่าได้เช่นเดียวกับวิธีการและฟังก์ชัน
นี่คือตัวอย่างง่ายๆในการใช้งานและเรียกใช้บล็อกที่มีอาร์กิวเมนต์และส่งคืนค่า
double (^multiplyTwoValues)(double, double) =
^(double firstValue, double secondValue) {
return firstValue * secondValue;
};
double result = multiplyTwoValues(2,4);
NSLog(@"The result is %f", result);
บล็อกโดยใช้นิยามประเภท
นี่คือตัวอย่างง่ายๆโดยใช้ typedef ในบล็อก โปรดสังเกตตัวอย่างนี้doesn't work บน online compilerสำหรับตอนนี้. ใช้XCode เพื่อทำงานเหมือนกัน
#import <Foundation/Foundation.h>
typedef void (^CompletionBlock)();
@interface SampleClass:NSObject
- (void)performActionWithCompletion:(CompletionBlock)completionBlock;
@end
@implementation SampleClass
- (void)performActionWithCompletion:(CompletionBlock)completionBlock {
NSLog(@"Action Performed");
completionBlock();
}
@end
int main() {
/* my first program in Objective-C */
SampleClass *sampleClass = [[SampleClass alloc]init];
[sampleClass performActionWithCompletion:^{
NSLog(@"Completion is called to intimate action is performed.");
}];
return 0;
}
ให้เรารวบรวมและดำเนินการมันจะให้ผลลัพธ์ดังต่อไปนี้ -
2013-09-10 08:13:57.155 demo[284:303] Action Performed
2013-09-10 08:13:57.157 demo[284:303] Completion is called to intimate action is performed.
บล็อกถูกใช้มากขึ้นในแอปพลิเคชัน iOS และ Mac OS X ดังนั้นการทำความเข้าใจการใช้งานบล็อกจึงสำคัญกว่า
ในภาษาโปรแกรม Objective-C เพื่อบันทึกชนิดข้อมูลพื้นฐานเช่น int, float, bool ในรูปแบบวัตถุ,
Objective-C มีวิธีการต่างๆในการทำงานกับ NSNumber และวิธีการที่สำคัญแสดงอยู่ในตารางต่อไปนี้
ซีเนียร์ | วิธีการและคำอธิบาย |
---|---|
1 | + (NSNumber *)numberWithBool:(BOOL)value สร้างและส่งคืนอ็อบเจ็กต์ NSNumber ที่มีค่าที่กำหนดโดยถือว่าเป็น BOOL |
2 | + (NSNumber *)numberWithChar:(char)value สร้างและส่งคืนอ็อบเจ็กต์ NSNumber ที่มีค่าที่กำหนดโดยถือว่าเป็นถ่านที่เซ็นชื่อ |
3 | + (NSNumber *)numberWithDouble:(double)value สร้างและส่งคืนอ็อบเจ็กต์ NSNumber ที่มีค่าที่กำหนดโดยถือว่าเป็นอ็อบเจ็กต์คู่ |
4 | + (NSNumber *)numberWithFloat:(float)value สร้างและส่งคืนอ็อบเจ็กต์ NSNumber ที่มีค่าที่กำหนดโดยถือว่าเป็นค่าลอย |
5 | + (NSNumber *)numberWithInt:(int)value สร้างและส่งคืนอ็อบเจ็กต์ NSNumber ที่มีค่าที่กำหนดโดยถือว่าเป็น int ที่ลงนาม |
6 | + (NSNumber *)numberWithInteger:(NSInteger)value สร้างและส่งคืนอ็อบเจ็กต์ NSNumber ที่มีค่าที่กำหนดโดยถือว่าเป็น NSInteger |
7 | - (BOOL)boolValue ส่งกลับค่าของเครื่องรับเป็น BOOL |
8 | - (char)charValue ส่งกลับค่าของผู้รับเป็นถ่าน |
9 | - (double)doubleValue ส่งกลับค่าของผู้รับเป็นคู่ |
10 | - (float)floatValue ส่งคืนค่าของผู้รับเป็นค่าลอย |
11 | - (NSInteger)integerValue ส่งกลับค่าของผู้รับเป็น NSInteger |
12 | - (int)intValue ส่งกลับค่าของผู้รับเป็น int |
13 | - (NSString *)stringValue ส่งคืนค่าของผู้รับเป็นสตริงที่มนุษย์อ่านได้ |
นี่คือตัวอย่างง่ายๆสำหรับการใช้ NSNumber ซึ่งคูณสองจำนวนและส่งคืนผลิตภัณฑ์
#import <Foundation/Foundation.h>
@interface SampleClass:NSObject
- (NSNumber *)multiplyA:(NSNumber *)a withB:(NSNumber *)b;
@end
@implementation SampleClass
- (NSNumber *)multiplyA:(NSNumber *)a withB:(NSNumber *)b {
float number1 = [a floatValue];
float number2 = [b floatValue];
float product = number1 * number2;
NSNumber *result = [NSNumber numberWithFloat:product];
return result;
}
@end
int main() {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
SampleClass *sampleClass = [[SampleClass alloc]init];
NSNumber *a = [NSNumber numberWithFloat:10.5];
NSNumber *b = [NSNumber numberWithFloat:10.0];
NSNumber *result = [sampleClass multiplyA:a withB:b];
NSString *resultString = [result stringValue];
NSLog(@"The product is %@",resultString);
[pool drain];
return 0;
}
ตอนนี้เมื่อเราคอมไพล์และรันโปรแกรมเราจะได้ผลลัพธ์ดังต่อไปนี้
2013-09-14 18:53:40.575 demo[16787] The product is 105
ภาษาโปรแกรม Objective-C จัดเตรียมโครงสร้างข้อมูลที่เรียกว่า the arrayซึ่งสามารถจัดเก็บคอลเลกชันตามลำดับขนาดคงที่ขององค์ประกอบประเภทเดียวกัน อาร์เรย์ใช้ในการจัดเก็บชุดข้อมูล แต่มักจะมีประโยชน์มากกว่าที่จะคิดว่าอาร์เรย์เป็นชุดของตัวแปรประเภทเดียวกัน
แทนที่จะประกาศตัวแปรเดี่ยวเช่น number0, number1, ... และ number99 คุณประกาศตัวแปรอาร์เรย์หนึ่งตัวเช่นตัวเลขและใช้ตัวเลข [0], ตัวเลข [1] และ ... , ตัวเลข [99] เพื่อแสดง ตัวแปรแต่ละตัว องค์ประกอบเฉพาะในอาร์เรย์ถูกเข้าถึงโดยดัชนี
อาร์เรย์ทั้งหมดประกอบด้วยตำแหน่งหน่วยความจำที่อยู่ติดกัน ที่อยู่ต่ำสุดสอดคล้องกับองค์ประกอบแรกและที่อยู่สูงสุดขององค์ประกอบสุดท้าย
การประกาศอาร์เรย์
ในการประกาศอาร์เรย์ใน Objective-C โปรแกรมเมอร์จะระบุประเภทขององค์ประกอบและจำนวนองค์ประกอบที่อาร์เรย์ต้องการดังนี้ -
type arrayName [ arraySize ];
สิ่งนี้เรียกว่าอาร์เรย์มิติเดียว arraySize ต้องเป็นค่าคงที่จำนวนเต็มมากกว่าศูนย์และ typeสามารถเป็นชนิดข้อมูล Objective-C ที่ถูกต้องได้ ตัวอย่างเช่นการประกาศอาร์เรย์ 10 องค์ประกอบที่เรียกว่าbalance ประเภท double ใช้คำสั่งนี้ -
double balance[10];
ตอนนี้ความสมดุลเป็นอาร์เรย์ตัวแปรซึ่งเพียงพอที่จะเก็บตัวเลขคู่ได้สูงสุด 10 ตัว
การเริ่มต้นอาร์เรย์
คุณสามารถเริ่มต้นอาร์เรย์ใน Objective-C ทีละรายการหรือใช้คำสั่งเดียวดังนี้ -
double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};
จำนวนค่าระหว่างวงเล็บปีกกา {} ต้องไม่เกินจำนวนองค์ประกอบที่เราประกาศสำหรับอาร์เรย์ระหว่างวงเล็บเหลี่ยม [] ต่อไปนี้เป็นตัวอย่างในการกำหนดองค์ประกอบเดียวของอาร์เรย์ -
หากคุณละเว้นขนาดของอาร์เรย์อาร์เรย์ที่ใหญ่พอที่จะรองรับการเริ่มต้นจะถูกสร้างขึ้น ดังนั้นถ้าคุณเขียน -
double balance[] = {1000.0, 2.0, 3.4, 17.0, 50.0};
คุณจะสร้างอาร์เรย์เหมือนกับที่คุณทำในตัวอย่างก่อนหน้านี้
balance[4] = 50.0;
คำสั่งข้างต้นกำหนดองค์ประกอบหมายเลข 5 ในอาร์เรย์เป็นค่า 50.0 อาร์เรย์ที่มีดัชนีที่ 4 จะเป็น 5 เช่นองค์ประกอบสุดท้ายเนื่องจากอาร์เรย์ทั้งหมดมี 0 เป็นดัชนีขององค์ประกอบแรกซึ่งเรียกอีกอย่างว่าดัชนีฐาน ต่อไปนี้คือการแสดงภาพของอาร์เรย์เดียวกันที่เรากล่าวถึงข้างต้น -
การเข้าถึงองค์ประกอบอาร์เรย์
องค์ประกอบถูกเข้าถึงโดยการสร้างดัชนีชื่ออาร์เรย์ ทำได้โดยการวางดัชนีขององค์ประกอบไว้ในวงเล็บเหลี่ยมหลังชื่อของอาร์เรย์ ตัวอย่างเช่น -
double salary = balance[9];
ข้อความข้างต้นจะนำองค์ประกอบที่ 10 จากอาร์เรย์และกำหนดค่าให้กับตัวแปรเงินเดือน ต่อไปนี้เป็นตัวอย่างซึ่งจะใช้แนวคิดทั้งสามที่กล่าวถึงข้างต้น ได้แก่ การประกาศการมอบหมายและการเข้าถึงอาร์เรย์ -
#import <Foundation/Foundation.h>
int main () {
int n[ 10 ]; /* n is an array of 10 integers */
int i,j;
/* initialize elements of array n to 0 */
for ( i = 0; i < 10; i++ ) {
n[ i ] = i + 100; /* set element at location i to i + 100 */
}
/* output each array element's value */
for (j = 0; j < 10; j++ ) {
NSLog(@"Element[%d] = %d\n", j, n[j] );
}
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-14 01:24:06.669 demo[16508] Element[0] = 100
2013-09-14 01:24:06.669 demo[16508] Element[1] = 101
2013-09-14 01:24:06.669 demo[16508] Element[2] = 102
2013-09-14 01:24:06.669 demo[16508] Element[3] = 103
2013-09-14 01:24:06.669 demo[16508] Element[4] = 104
2013-09-14 01:24:06.669 demo[16508] Element[5] = 105
2013-09-14 01:24:06.669 demo[16508] Element[6] = 106
2013-09-14 01:24:06.669 demo[16508] Element[7] = 107
2013-09-14 01:24:06.669 demo[16508] Element[8] = 108
2013-09-14 01:24:06.669 demo[16508] Element[9] = 109
Objective-C Arrays ในรายละเอียด
อาร์เรย์มีความสำคัญต่อ Objective-C และต้องการรายละเอียดเพิ่มเติมมากมาย มีแนวคิดสำคัญบางประการที่เกี่ยวข้องกับอาร์เรย์ซึ่งควรชัดเจนสำหรับโปรแกรมเมอร์ Objective-C -
ซีเนียร์ | แนวคิดและคำอธิบาย |
---|---|
1 | อาร์เรย์หลายมิติ Objective-C รองรับอาร์เรย์หลายมิติ รูปแบบที่ง่ายที่สุดของอาร์เรย์หลายมิติคืออาร์เรย์สองมิติ |
2 | การส่งอาร์เรย์ไปยังฟังก์ชัน คุณสามารถส่งผ่านไปยังฟังก์ชันตัวชี้ไปยังอาร์เรย์ได้โดยระบุชื่ออาร์เรย์โดยไม่มีดัชนี |
3 | ส่งคืนอาร์เรย์จากฟังก์ชัน Objective-C อนุญาตให้ฟังก์ชันส่งคืนอาร์เรย์ |
4 | ชี้ไปที่อาร์เรย์ คุณสามารถสร้างตัวชี้ไปยังองค์ประกอบแรกของอาร์เรย์ได้โดยระบุชื่ออาร์เรย์โดยไม่ต้องมีดัชนีใด ๆ |
ตัวชี้ใน Objective-C นั้นง่ายและสนุกในการเรียนรู้ งานการเขียนโปรแกรม Objective-C บางงานสามารถดำเนินการได้ง่ายขึ้นโดยใช้พอยน์เตอร์และงานอื่น ๆ เช่นการจัดสรรหน่วยความจำแบบไดนามิกจะไม่สามารถทำได้โดยไม่ใช้พอยน์เตอร์ ดังนั้นจึงจำเป็นต้องเรียนรู้พอยน์เตอร์เพื่อเป็นโปรแกรมเมอร์ Objective-C ที่สมบูรณ์แบบ มาเริ่มเรียนรู้กันในขั้นตอนง่ายๆ
ดังที่คุณทราบทุกตัวแปรคือตำแหน่งหน่วยความจำและตำแหน่งหน่วยความจำทุกแห่งจะมีที่อยู่ที่กำหนดไว้ซึ่งสามารถเข้าถึงได้โดยใช้ตัวดำเนินการเครื่องหมายและ (&) ซึ่งแสดงถึงที่อยู่ในหน่วยความจำ พิจารณาตัวอย่างต่อไปนี้ซึ่งจะพิมพ์ที่อยู่ของตัวแปรที่กำหนด -
#import <Foundation/Foundation.h>
int main () {
int var1;
char var2[10];
NSLog(@"Address of var1 variable: %x\n", &var1 );
NSLog(@"Address of var2 variable: %x\n", &var2 );
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานโค้ดจะให้ผลลัพธ์ดังนี้ -
2013-09-13 03:18:45.727 demo[17552] Address of var1 variable: 1c0843fc
2013-09-13 03:18:45.728 demo[17552] Address of var2 variable: 1c0843f0
คุณเข้าใจแล้วว่าที่อยู่หน่วยความจำคืออะไรและจะเข้าถึงได้อย่างไรฐานของแนวคิดจึงจบลง ตอนนี้ให้เราดูว่าอะไรคือตัวชี้
ตัวชี้คืออะไร?
ก pointerเป็นตัวแปรที่มีค่าเป็นที่อยู่ของตัวแปรอื่นเช่นที่อยู่โดยตรงของตำแหน่งหน่วยความจำ เช่นเดียวกับตัวแปรหรือค่าคงที่คุณต้องประกาศตัวชี้ก่อนจึงจะสามารถใช้เพื่อเก็บที่อยู่ตัวแปรได้ รูปแบบทั่วไปของการประกาศตัวแปรพอยน์เตอร์คือ -
type *var-name;
ที่นี่ typeเป็นประเภทฐานของตัวชี้ ต้องเป็นชนิดข้อมูล Objective-C ที่ถูกต้องและvar-nameคือชื่อของตัวแปรพอยน์เตอร์ เครื่องหมายดอกจัน * ที่คุณใช้ในการประกาศตัวชี้เป็นเครื่องหมายดอกจันเดียวกับที่คุณใช้ในการคูณ อย่างไรก็ตามในคำสั่งนี้จะใช้เครื่องหมายดอกจันเพื่อกำหนดตัวแปรเป็นตัวชี้ ต่อไปนี้เป็นการประกาศตัวชี้ที่ถูกต้อง -
int *ip; /* pointer to an integer */
double *dp; /* pointer to a double */
float *fp; /* pointer to a float */
char *ch /* pointer to a character */
ชนิดข้อมูลจริงของค่าของพอยน์เตอร์ทั้งหมดไม่ว่าจะเป็นจำนวนเต็มจำนวนทศนิยมอักขระหรืออื่น ๆ จะเหมือนกันเป็นเลขฐานสิบหกแบบยาวที่แสดงแอดเดรสหน่วยความจำ ความแตกต่างเพียงอย่างเดียวระหว่างพอยน์เตอร์ของชนิดข้อมูลที่แตกต่างกันคือชนิดข้อมูลของตัวแปรหรือค่าคงที่ที่ตัวชี้ชี้ไป
วิธีใช้พอยน์เตอร์
มีการดำเนินการที่สำคัญบางอย่างซึ่งเราจะดำเนินการด้วยความช่วยเหลือของพอยน์เตอร์บ่อยมาก (a) เรากำหนดตัวแปรตัวชี้ (b) กำหนดที่อยู่ของตัวแปรให้กับตัวชี้และ (c)ในที่สุดก็เข้าถึงค่าตามที่อยู่ที่มีอยู่ในตัวแปรตัวชี้ สิ่งนี้ทำได้โดยใช้ตัวดำเนินการยูนารี*ที่ส่งคืนค่าของตัวแปรที่อยู่ตามที่อยู่ที่ระบุโดยตัวถูกดำเนินการ ตัวอย่างต่อไปนี้ใช้ประโยชน์จากการดำเนินการเหล่านี้ -
#import <Foundation/Foundation.h>
int main () {
int var = 20; /* actual variable declaration */
int *ip; /* pointer variable declaration */
ip = &var; /* store address of var in pointer variable*/
NSLog(@"Address of var variable: %x\n", &var );
/* address stored in pointer variable */
NSLog(@"Address stored in ip variable: %x\n", ip );
/* access the value using the pointer */
NSLog(@"Value of *ip variable: %d\n", *ip );
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานโค้ดจะให้ผลลัพธ์ดังนี้ -
2013-09-13 03:20:21.873 demo[24179] Address of var variable: 337ed41c
2013-09-13 03:20:21.873 demo[24179] Address stored in ip variable: 337ed41c
2013-09-13 03:20:21.874 demo[24179] Value of *ip variable: 20
ตัวชี้ NULL ใน Objective-C
การกำหนดค่า NULL ให้กับตัวแปรพอยน์เตอร์เป็นแนวทางปฏิบัติที่ดีเสมอในกรณีที่คุณไม่มีแอดเดรสที่จะกำหนด สิ่งนี้ทำได้ในช่วงเวลาของการประกาศตัวแปร ตัวชี้ที่กำหนดเป็น NULL เรียกว่า anull ตัวชี้
ตัวชี้ NULL เป็นค่าคงที่ที่มีค่าเป็นศูนย์ที่กำหนดไว้ในไลบรารีมาตรฐานต่างๆ พิจารณาโปรแกรมต่อไปนี้ -
#import <Foundation/Foundation.h>
int main () {
int *ptr = NULL;
NSLog(@"The value of ptr is : %x\n", ptr );
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-13 03:21:19.447 demo[28027] The value of ptr is : 0
ในระบบปฏิบัติการส่วนใหญ่โปรแกรมไม่ได้รับอนุญาตให้เข้าถึงหน่วยความจำที่อยู่ 0 เนื่องจากหน่วยความจำนั้นสงวนไว้โดยระบบปฏิบัติการ อย่างไรก็ตามที่อยู่หน่วยความจำ 0 มีความสำคัญเป็นพิเศษ เป็นการส่งสัญญาณว่าตัวชี้ไม่ได้ตั้งใจให้ชี้ไปยังตำแหน่งหน่วยความจำที่สามารถเข้าถึงได้ แต่ตามแบบแผนถ้าตัวชี้มีค่า null (ศูนย์) จะถือว่าชี้ไปที่ความว่างเปล่า
ในการตรวจหาตัวชี้ค่าว่างคุณสามารถใช้คำสั่ง if ได้ดังนี้ -
if(ptr) /* succeeds if p is not null */
if(!ptr) /* succeeds if p is null */
Objective-C ตัวชี้ในรายละเอียด
พอยน์เตอร์มีแนวคิดมากมาย แต่ใช้งานง่ายและมีความสำคัญต่อการเขียนโปรแกรม Objective-C มาก มีแนวคิดตัวชี้ที่สำคัญต่อไปนี้ซึ่งควรชัดเจนสำหรับโปรแกรมเมอร์ Objective-C -
ซีเนียร์ | แนวคิดและคำอธิบาย |
---|---|
1 | Objective-C - ตัวชี้เลขคณิต มีตัวดำเนินการทางคณิตศาสตร์สี่ตัวที่สามารถใช้กับพอยน์เตอร์ได้: ++, -, +, - |
2 | Objective-C - อาร์เรย์ของพอยน์เตอร์ คุณสามารถกำหนดอาร์เรย์เพื่อเก็บพอยน์เตอร์ได้หลายตัว |
3 | Objective-C - ตัวชี้ไปที่ตัวชี้ Objective-C ช่วยให้คุณมีตัวชี้บนตัวชี้และอื่น ๆ |
4 | ส่งพอยน์เตอร์ไปยังฟังก์ชันใน Objective-C การส่งผ่านอาร์กิวเมนต์โดยการอ้างอิงหรือตามแอดเดรสทำให้อาร์กิวเมนต์ที่ส่งผ่านถูกเปลี่ยนในฟังก์ชันการโทรโดยฟังก์ชันที่เรียก |
5 | กลับตัวชี้จากฟังก์ชันใน Objective-C Objective-C อนุญาตให้ฟังก์ชันส่งกลับตัวชี้ไปยังตัวแปรโลคัลตัวแปรคงที่และหน่วยความจำที่จัดสรรแบบไดนามิกเช่นกัน |
สตริงในภาษาโปรแกรม Objective-C แสดงโดยใช้ NSString และคลาสย่อย NSMutableString มีหลายวิธีในการสร้างอ็อบเจ็กต์สตริง วิธีที่ง่ายที่สุดในการสร้างวัตถุสตริงคือการใช้โครงสร้าง Objective-C @ "... " -
NSString *greeting = @"Hello";
ตัวอย่างง่ายๆสำหรับการสร้างและพิมพ์สตริงแสดงอยู่ด้านล่าง
#import <Foundation/Foundation.h>
int main () {
NSString *greeting = @"Hello";
NSLog(@"Greeting message: %@\n", greeting );
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-11 01:21:39.922 demo[23926] Greeting message: Hello
Objective-C รองรับวิธีการต่างๆในการจัดการสตริง -
ซีเนียร์ | วิธีการและวัตถุประสงค์ |
---|---|
1 | - (NSString *)capitalizedString; ส่งคืนการแสดงตัวพิมพ์ใหญ่ของผู้รับ |
2 | - (unichar)characterAtIndex:(NSUInteger)index; ส่งกลับอักขระที่ตำแหน่งอาร์เรย์ที่กำหนด |
3 | - (double)doubleValue; ส่งคืนค่าทศนิยมของข้อความของผู้รับเป็นค่าคู่ |
4 | - (float)floatValue; ส่งคืนค่าทศนิยมของข้อความของผู้รับเป็นค่าทศนิยม |
5 | - (BOOL)hasPrefix:(NSString *)aString; ส่งคืนค่าบูลีนที่ระบุว่าสตริงที่กำหนดตรงกับอักขระเริ่มต้นของตัวรับหรือไม่ |
6 | - (BOOL)hasSuffix:(NSString *)aString; ส่งคืนค่าบูลีนที่ระบุว่าสตริงที่กำหนดตรงกับอักขระลงท้ายของผู้รับหรือไม่ |
7 | - (id)initWithFormat:(NSString *)format ...; ส่งคืนอ็อบเจ็กต์ NSString ที่เริ่มต้นโดยใช้สตริงรูปแบบที่กำหนดเป็นเทมเพลตซึ่งค่าอาร์กิวเมนต์ที่เหลือจะถูกแทนที่ |
8 | - (NSInteger)integerValue; ส่งคืนค่า NSInteger ของข้อความของผู้รับ |
9 | - (BOOL)isEqualToString:(NSString *)aString; ส่งคืนค่าบูลีนที่ระบุว่าสตริงที่กำหนดเท่ากับตัวรับหรือไม่โดยใช้การเปรียบเทียบตามตัวอักษร Unicode |
10 | - (NSUInteger)length; ส่งคืนจำนวนอักขระ Unicode ในเครื่องรับ |
11 | - (NSString *)lowercaseString; ส่งกลับการแสดงค่าที่ต่ำกว่าของผู้รับ |
12 | - (NSRange)rangeOfString:(NSString *)aString; ค้นหาและส่งคืนช่วงของการเกิดครั้งแรกของสตริงที่กำหนดภายในตัวรับ |
13 | - (NSString *)stringByAppendingFormat:(NSString *)format ...; ส่งคืนสตริงที่สร้างขึ้นโดยต่อท้ายสตริงที่สร้างจากสตริงรูปแบบที่กำหนดและอาร์กิวเมนต์ต่อไปนี้ให้กับผู้รับ |
14 | - (NSString *)stringByTrimmingCharactersInSet:(NSCharacterSet *)set; ส่งคืนสตริงใหม่ที่สร้างขึ้นโดยการลบออกจากปลายทั้งสองของอักขระตัวรับที่มีอยู่ในชุดอักขระที่กำหนด |
15 | - (NSString *)substringFromIndex:(NSUInteger)anIndex; ส่งคืนสตริงใหม่ที่มีอักขระของผู้รับจากสตริงที่ดัชนีที่กำหนดไปยังจุดสิ้นสุด |
ตัวอย่างต่อไปนี้ใช้ประโยชน์จากฟังก์ชันที่กล่าวถึงข้างต้น -
#import <Foundation/Foundation.h>
int main () {
NSString *str1 = @"Hello";
NSString *str2 = @"World";
NSString *str3;
int len ;
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
/* uppercase string */
str3 = [str2 uppercaseString];
NSLog(@"Uppercase String : %@\n", str3 );
/* concatenates str1 and str2 */
str3 = [str1 stringByAppendingFormat:@"World"];
NSLog(@"Concatenated string: %@\n", str3 );
/* total length of str3 after concatenation */
len = [str3 length];
NSLog(@"Length of Str3 : %d\n", len );
/* InitWithFormat */
str3 = [[NSString alloc] initWithFormat:@"%@ %@",str1,str2];
NSLog(@"Using initWithFormat: %@\n", str3 );
[pool drain];
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-11 01:15:45.069 demo[30378] Uppercase String : WORLD
2013-09-11 01:15:45.070 demo[30378] Concatenated string: HelloWorld
2013-09-11 01:15:45.070 demo[30378] Length of Str3 : 10
2013-09-11 01:15:45.070 demo[30378] Using initWithFormat: Hello World
คุณสามารถค้นหารายการวิธีการที่เกี่ยวข้องกับ Objective-C NSString ทั้งหมดได้ในNSString Class Reference
อาร์เรย์ Objective-C ช่วยให้คุณสามารถกำหนดประเภทของตัวแปรที่สามารถเก็บข้อมูลหลายรายการในประเภทเดียวกันได้ แต่ structure เป็นประเภทข้อมูลที่ผู้ใช้กำหนดเองที่มีอยู่ในการเขียนโปรแกรม Objective-C ซึ่งช่วยให้คุณสามารถรวมรายการข้อมูลประเภทต่างๆ
โครงสร้างใช้เพื่อแสดงบันทึกสมมติว่าคุณต้องการติดตามหนังสือของคุณในห้องสมุด คุณอาจต้องการติดตามคุณลักษณะต่อไปนี้เกี่ยวกับหนังสือแต่ละเล่ม -
- Title
- Author
- Subject
- รหัสหนังสือ
การกำหนดโครงสร้าง
ในการกำหนดโครงสร้างคุณต้องใช้ไฟล์ structคำให้การ. คำสั่ง struct กำหนดชนิดข้อมูลใหม่โดยมีสมาชิกมากกว่าหนึ่งคนสำหรับโปรแกรมของคุณ รูปแบบของคำสั่ง struct คือ -
struct [structure tag] {
member definition;
member definition;
...
member definition;
} [one or more structure variables];
structure tagเป็นทางเลือกและนิยามสมาชิกแต่ละตัวเป็นนิยามตัวแปรปกติเช่น int i; หรือลอยฉ; หรือนิยามตัวแปรอื่น ๆ ที่ถูกต้อง ในตอนท้ายของนิยามของโครงสร้างก่อนอัฒภาคสุดท้ายคุณสามารถระบุตัวแปรโครงสร้างอย่างน้อยหนึ่งตัวแปร แต่เป็นทางเลือก นี่คือวิธีที่คุณจะประกาศโครงสร้างหนังสือ -
struct Books {
NSString *title;
NSString *author;
NSString *subject;
int book_id;
} book;
การเข้าถึงสมาชิกโครงสร้าง
ในการเข้าถึงสมาชิกของโครงสร้างใด ๆ เราใช้ไฟล์ member access operator (.). ตัวดำเนินการเข้าถึงสมาชิกถูกเข้ารหัสเป็นช่วงเวลาระหว่างชื่อตัวแปรโครงสร้างและสมาชิกโครงสร้างที่เราต้องการเข้าถึง คุณจะใช้structคำหลักในการกำหนดตัวแปรประเภทโครงสร้าง ต่อไปนี้เป็นตัวอย่างเพื่ออธิบายการใช้โครงสร้าง -
#import <Foundation/Foundation.h>
struct Books {
NSString *title;
NSString *author;
NSString *subject;
int book_id;
};
int main() {
struct Books Book1; /* Declare Book1 of type Book */
struct Books Book2; /* Declare Book2 of type Book */
/* book 1 specification */
Book1.title = @"Objective-C Programming";
Book1.author = @"Nuha Ali";
Book1.subject = @"Objective-C Programming Tutorial";
Book1.book_id = 6495407;
/* book 2 specification */
Book2.title = @"Telecom Billing";
Book2.author = @"Zara Ali";
Book2.subject = @"Telecom Billing Tutorial";
Book2.book_id = 6495700;
/* print Book1 info */
NSLog(@"Book 1 title : %@\n", Book1.title);
NSLog(@"Book 1 author : %@\n", Book1.author);
NSLog(@"Book 1 subject : %@\n", Book1.subject);
NSLog(@"Book 1 book_id : %d\n", Book1.book_id);
/* print Book2 info */
NSLog(@"Book 2 title : %@\n", Book2.title);
NSLog(@"Book 2 author : %@\n", Book2.author);
NSLog(@"Book 2 subject : %@\n", Book2.subject);
NSLog(@"Book 2 book_id : %d\n", Book2.book_id);
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-14 04:20:07.947 demo[20591] Book 1 title : Objective-C Programming
2013-09-14 04:20:07.947 demo[20591] Book 1 author : Nuha Ali
2013-09-14 04:20:07.947 demo[20591] Book 1 subject : Objective-C Programming Tutorial
2013-09-14 04:20:07.947 demo[20591] Book 1 book_id : 6495407
2013-09-14 04:20:07.947 demo[20591] Book 2 title : Telecom Billing
2013-09-14 04:20:07.947 demo[20591] Book 2 author : Zara Ali
2013-09-14 04:20:07.947 demo[20591] Book 2 subject : Telecom Billing Tutorial
2013-09-14 04:20:07.947 demo[20591] Book 2 book_id : 6495700
โครงสร้างเป็นอาร์กิวเมนต์ของฟังก์ชัน
คุณสามารถส่งผ่านโครงสร้างเป็นอาร์กิวเมนต์ของฟังก์ชันในลักษณะที่คล้ายกันมากเมื่อคุณส่งผ่านตัวแปรหรือตัวชี้อื่น ๆ คุณจะเข้าถึงตัวแปรโครงสร้างในลักษณะเดียวกับที่คุณเข้าถึงในตัวอย่างข้างต้น -
#import <Foundation/Foundation.h>
struct Books {
NSString *title;
NSString *author;
NSString *subject;
int book_id;
};
@interface SampleClass:NSObject
/* function declaration */
- (void) printBook:( struct Books) book ;
@end
@implementation SampleClass
- (void) printBook:( struct Books) book {
NSLog(@"Book title : %@\n", book.title);
NSLog(@"Book author : %@\n", book.author);
NSLog(@"Book subject : %@\n", book.subject);
NSLog(@"Book book_id : %d\n", book.book_id);
}
@end
int main() {
struct Books Book1; /* Declare Book1 of type Book */
struct Books Book2; /* Declare Book2 of type Book */
/* book 1 specification */
Book1.title = @"Objective-C Programming";
Book1.author = @"Nuha Ali";
Book1.subject = @"Objective-C Programming Tutorial";
Book1.book_id = 6495407;
/* book 2 specification */
Book2.title = @"Telecom Billing";
Book2.author = @"Zara Ali";
Book2.subject = @"Telecom Billing Tutorial";
Book2.book_id = 6495700;
SampleClass *sampleClass = [[SampleClass alloc]init];
/* print Book1 info */
[sampleClass printBook: Book1];
/* Print Book2 info */
[sampleClass printBook: Book2];
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-14 04:34:45.725 demo[8060] Book title : Objective-C Programming
2013-09-14 04:34:45.725 demo[8060] Book author : Nuha Ali
2013-09-14 04:34:45.725 demo[8060] Book subject : Objective-C Programming Tutorial
2013-09-14 04:34:45.725 demo[8060] Book book_id : 6495407
2013-09-14 04:34:45.725 demo[8060] Book title : Telecom Billing
2013-09-14 04:34:45.725 demo[8060] Book author : Zara Ali
2013-09-14 04:34:45.725 demo[8060] Book subject : Telecom Billing Tutorial
2013-09-14 04:34:45.725 demo[8060] Book book_id : 6495700
ตัวชี้ไปที่โครงสร้าง
คุณสามารถกำหนดตัวชี้ไปยังโครงสร้างในลักษณะที่คล้ายกันมากเมื่อคุณกำหนดตัวชี้ไปยังตัวแปรอื่น ๆ ดังนี้ -
struct Books *struct_pointer;
ตอนนี้คุณสามารถจัดเก็บที่อยู่ของตัวแปรโครงสร้างในตัวแปรตัวชี้ที่กำหนดไว้ข้างต้น ในการค้นหาที่อยู่ของตัวแปรโครงสร้างให้วางเครื่องหมาย & ไว้หน้าชื่อโครงสร้างดังนี้ -
struct_pointer = &Book1;
ในการเข้าถึงสมาชิกของโครงสร้างโดยใช้ตัวชี้ไปยังโครงสร้างนั้นคุณต้องใช้ตัวดำเนินการ -> ดังต่อไปนี้ -
struct_pointer->title;
ให้เราเขียนตัวอย่างด้านบนอีกครั้งโดยใช้ตัวชี้โครงสร้างหวังว่านี่จะเป็นเรื่องง่ายสำหรับคุณที่จะเข้าใจแนวคิด -
#import <Foundation/Foundation.h>
struct Books {
NSString *title;
NSString *author;
NSString *subject;
int book_id;
};
@interface SampleClass:NSObject
/* function declaration */
- (void) printBook:( struct Books *) book ;
@end
@implementation SampleClass
- (void) printBook:( struct Books *) book {
NSLog(@"Book title : %@\n", book->title);
NSLog(@"Book author : %@\n", book->author);
NSLog(@"Book subject : %@\n", book->subject);
NSLog(@"Book book_id : %d\n", book->book_id);
}
@end
int main() {
struct Books Book1; /* Declare Book1 of type Book */
struct Books Book2; /* Declare Book2 of type Book */
/* book 1 specification */
Book1.title = @"Objective-C Programming";
Book1.author = @"Nuha Ali";
Book1.subject = @"Objective-C Programming Tutorial";
Book1.book_id = 6495407;
/* book 2 specification */
Book2.title = @"Telecom Billing";
Book2.author = @"Zara Ali";
Book2.subject = @"Telecom Billing Tutorial";
Book2.book_id = 6495700;
SampleClass *sampleClass = [[SampleClass alloc]init];
/* print Book1 info by passing address of Book1 */
[sampleClass printBook:&Book1];
/* print Book2 info by passing address of Book2 */
[sampleClass printBook:&Book2];
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-14 04:38:13.942 demo[20745] Book title : Objective-C Programming
2013-09-14 04:38:13.942 demo[20745] Book author : Nuha Ali
2013-09-14 04:38:13.942 demo[20745] Book subject : Objective-C Programming Tutorial
2013-09-14 04:38:13.942 demo[20745] Book book_id : 6495407
2013-09-14 04:38:13.942 demo[20745] Book title : Telecom Billing
2013-09-14 04:38:13.942 demo[20745] Book author : Zara Ali
2013-09-14 04:38:13.942 demo[20745] Book subject : Telecom Billing Tutorial
2013-09-14 04:38:13.942 demo[20745] Book book_id : 6495700
บิตฟิลด์
Bit Fields อนุญาตให้บรรจุข้อมูลในโครงสร้าง สิ่งนี้มีประโยชน์อย่างยิ่งเมื่อหน่วยความจำหรือที่เก็บข้อมูลอยู่ในระดับพรีเมียม ตัวอย่างทั่วไป -
บรรจุวัตถุหลายชิ้นลงในเครื่อง เช่นแฟล็ก 1 บิตสามารถบีบอัดได้
การอ่านรูปแบบไฟล์ภายนอก - รูปแบบไฟล์ที่ไม่ได้มาตรฐานสามารถอ่านได้เช่นจำนวนเต็ม 9 บิต
Objective-C ช่วยให้เราสามารถกำหนดโครงสร้างได้โดยใส่: bit length ไว้หลังตัวแปร ตัวอย่างเช่น -
struct packed_struct {
unsigned int f1:1;
unsigned int f2:1;
unsigned int f3:1;
unsigned int f4:1;
unsigned int type:4;
unsigned int my_int:9;
} pack;
ที่นี่ packing_struct ประกอบด้วยสมาชิก 6 คน: แฟล็ก 1 บิตสี่ตัว f1..f3 ประเภท 4 บิตและ my_int 9 บิต
Objective-C จะแพ็คฟิลด์บิตด้านบนให้กระชับที่สุดโดยอัตโนมัติโดยที่ความยาวสูงสุดของฟิลด์จะน้อยกว่าหรือเท่ากับความยาวคำจำนวนเต็มของคอมพิวเตอร์ หากไม่เป็นเช่นนั้นคอมไพเลอร์บางตัวอาจอนุญาตให้หน่วยความจำทับซ้อนกันสำหรับฟิลด์ในขณะที่อีกฟิลด์หนึ่งจะเก็บฟิลด์ถัดไปไว้ในคำถัดไป
Objective-C Preprocessorไม่ได้เป็นส่วนหนึ่งของคอมไพเลอร์ แต่เป็นขั้นตอนแยกต่างหากในกระบวนการคอมไพล์ ในแง่ที่เข้าใจง่าย Objective-C Preprocessor เป็นเพียงเครื่องมือทดแทนข้อความและสั่งให้คอมไพเลอร์ทำการประมวลผลล่วงหน้าที่จำเป็นก่อนการคอมไพล์จริง เราจะอ้างถึง Objective-C Preprocessor ว่า OCPP
คำสั่งพรีโปรเซสเซอร์ทั้งหมดเริ่มต้นด้วยสัญลักษณ์ปอนด์ (#) ต้องเป็นอักขระ nonblank ตัวแรกและเพื่อความสามารถในการอ่านคำสั่งพรีโปรเซสเซอร์ควรเริ่มต้นในคอลัมน์แรก ส่วนต่อไปนี้แสดงรายการคำสั่งก่อนตัวประมวลผลที่สำคัญทั้งหมด -
ซีเนียร์ | คำสั่งและคำอธิบาย |
---|---|
1 | #define แทนที่มาโครตัวประมวลผลล่วงหน้า |
2 | #include แทรกส่วนหัวเฉพาะจากไฟล์อื่น |
3 | #undef ไม่ได้กำหนดมาโครตัวประมวลผลล่วงหน้า |
4 | #ifdef ส่งคืนค่าจริงหากกำหนดมาโครนี้ |
5 | #ifndef ส่งคืนค่าจริงหากไม่ได้กำหนดมาโครนี้ |
6 | #if ทดสอบว่าเงื่อนไขเวลาคอมไพล์เป็นจริงหรือไม่ |
7 | #else ทางเลือกสำหรับ #if |
8 | #elif #else an #if ในหนึ่งคำสั่ง |
9 | #endif สิ้นสุดเงื่อนไขก่อนตัวประมวลผล |
10 | #error พิมพ์ข้อความแสดงข้อผิดพลาดบน stderr |
11 | #pragma ออกคำสั่งพิเศษไปยังคอมไพลเลอร์โดยใช้วิธีการมาตรฐาน |
ตัวอย่างตัวประมวลผลล่วงหน้า
วิเคราะห์ตัวอย่างต่อไปนี้เพื่อทำความเข้าใจคำสั่งต่างๆ
#define MAX_ARRAY_LENGTH 20
คำสั่งนี้บอกให้ OCPP แทนที่อินสแตนซ์ของ MAX_ARRAY_LENGTH ด้วย 20 ใช้#defineสำหรับค่าคงที่เพื่อเพิ่มความสามารถในการอ่าน
#import <Foundation/Foundation.h>
#include "myheader.h"
คำสั่งเหล่านี้บอกให้ OCPP ได้รับรากฐาน h จาก Foundation Frameworkและเพิ่มข้อความลงในไฟล์ต้นฉบับปัจจุบัน บรรทัดถัดไปบอกให้รับ OCPPmyheader.h จากโลคัลไดเร็กทอรีและเพิ่มเนื้อหาลงในซอร์สไฟล์ปัจจุบัน
#undef FILE_SIZE
#define FILE_SIZE 42
สิ่งนี้บอกให้ OCPP ยกเลิกการกำหนด FILE_SIZE ที่มีอยู่และกำหนดเป็น 42
#ifndef MESSAGE
#define MESSAGE "You wish!"
#endif
สิ่งนี้จะบอกให้ OCPP กำหนด MESSAGE ก็ต่อเมื่อยังไม่ได้กำหนด MESSAGE ไว้
#ifdef DEBUG
/* Your debugging statements here */
#endif
สิ่งนี้บอกให้ OCPP ดำเนินการตามคำสั่งที่แนบมาหากมีการกำหนด DEBUG สิ่งนี้มีประโยชน์หากคุณส่งแฟล็ก -DDEBUGไปยังคอมไพเลอร์ gcc ในขณะคอมไพล์ สิ่งนี้จะกำหนด DEBUG เพื่อให้คุณสามารถเปิดและปิดการดีบักได้ทันทีในระหว่างการคอมไพล์
มาโครที่กำหนดไว้ล่วงหน้า
ANSI C กำหนดมาโครจำนวนหนึ่ง แม้ว่าแต่ละมาโครจะพร้อมใช้งานสำหรับการเขียนโปรแกรมของคุณ แต่ก็ไม่ควรแก้ไขมาโครที่กำหนดไว้ล่วงหน้าโดยตรง
ซีเนียร์ | มาโครและคำอธิบาย |
---|---|
1 | __DATE__ วันที่ปัจจุบันเป็นอักขระลิเทอรัลในรูปแบบ "MMM DD YYYY" |
2 | __TIME__ เวลาปัจจุบันเป็นอักขระลิเทอรัลในรูปแบบ "HH: MM: SS" |
3 | __FILE__ ซึ่งมีชื่อไฟล์ปัจจุบันเป็นสตริงลิเทอรัล |
4 | __LINE__ ซึ่งประกอบด้วยหมายเลขบรรทัดปัจจุบันเป็นค่าคงที่ทศนิยม |
5 | __STDC__ กำหนดเป็น 1 เมื่อคอมไพเลอร์เป็นไปตามมาตรฐาน ANSI |
ลองดูตัวอย่างต่อไปนี้ -
#import <Foundation/Foundation.h>
int main() {
NSLog(@"File :%s\n", __FILE__ );
NSLog(@"Date :%s\n", __DATE__ );
NSLog(@"Time :%s\n", __TIME__ );
NSLog(@"Line :%d\n", __LINE__ );
NSLog(@"ANSI :%d\n", __STDC__ );
return 0;
}
เมื่อรหัสดังกล่าวอยู่ในไฟล์ main.m ถูกรวบรวมและดำเนินการจะให้ผลลัพธ์ดังต่อไปนี้ -
2013-09-14 04:46:14.859 demo[20683] File :main.m
2013-09-14 04:46:14.859 demo[20683] Date :Sep 14 2013
2013-09-14 04:46:14.859 demo[20683] Time :04:46:14
2013-09-14 04:46:14.859 demo[20683] Line :8
2013-09-14 04:46:14.859 demo[20683] ANSI :1
ตัวดำเนินการก่อนโปรเซสเซอร์
ตัวประมวลผลล่วงหน้า Objective-C มีตัวดำเนินการต่อไปนี้เพื่อช่วยคุณในการสร้างมาโคร -
ความต่อเนื่องของมาโคร (\)
โดยปกติมาโครจะต้องอยู่ในบรรทัดเดียว ตัวดำเนินการต่อเนื่องแมโครใช้เพื่อดำเนินการต่อมาโครที่ยาวเกินไปสำหรับบรรทัดเดียว ตัวอย่างเช่น -
#define message_for(a, b) \
NSLog(@#a " and " #b ": We love you!\n")
สตริง (#)
ตัวดำเนินการ stringize หรือ number-sign ('#') เมื่อใช้ภายในนิยามมาโครจะแปลงพารามิเตอร์มาโครเป็นค่าคงที่ของสตริง ตัวดำเนินการนี้สามารถใช้ได้เฉพาะในมาโครที่มีอาร์กิวเมนต์หรือรายการพารามิเตอร์ที่ระบุ ตัวอย่างเช่น -
#import <Foundation/Foundation.h>
#define message_for(a, b) \
NSLog(@#a " and " #b ": We love you!\n")
int main(void) {
message_for(Carole, Debra);
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-14 05:46:14.859 demo[20683] Carole and Debra: We love you!
การวางโทเค็น (##)
ตัวดำเนินการวางโทเค็น (##) ภายในนิยามมาโครรวมสองอาร์กิวเมนต์ อนุญาตให้โทเค็นสองโทเค็นที่แยกจากกันในนิยามมาโครรวมเป็นโทเค็นเดียว ตัวอย่างเช่น -
#import <Foundation/Foundation.h>
#define tokenpaster(n) NSLog (@"token" #n " = %d", token##n)
int main(void) {
int token34 = 40;
tokenpaster(34);
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-14 05:48:14.859 demo[20683] token34 = 40
มันเกิดขึ้นได้อย่างไรเนื่องจากตัวอย่างนี้ส่งผลให้เกิดผลลัพธ์จริงต่อไปนี้จากตัวประมวลผลล่วงหน้า -
NSLog (@"token34 = %d", token34);
ตัวอย่างนี้แสดงการต่อโทเค็น ## n เข้ากับโทเค็น 34 และที่นี่เราได้ใช้ทั้งสองอย่าง stringize และ token-pasting.
ตัวดำเนินการที่กำหนด ()
ตัวประมวลผลล่วงหน้า definedตัวดำเนินการถูกใช้ในนิพจน์ค่าคงที่เพื่อพิจารณาว่าตัวระบุถูกกำหนดโดยใช้ #define หรือไม่ หากมีการกำหนดตัวระบุที่ระบุไว้ค่าจะเป็นจริง (ไม่ใช่ศูนย์) หากไม่ได้กำหนดสัญลักษณ์ไว้ค่าจะเป็นเท็จ (ศูนย์) ระบุตัวดำเนินการดังต่อไปนี้ -
#import <Foundation/Foundation.h>
#if !defined (MESSAGE)
#define MESSAGE "You wish!"
#endif
int main(void) {
NSLog(@"Here is the message: %s\n", MESSAGE);
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-14 05:48:19.859 demo[20683] Here is the message: You wish!
มาโครที่กำหนดพารามิเตอร์
หนึ่งในฟังก์ชันที่มีประสิทธิภาพของ OCPP คือความสามารถในการจำลองฟังก์ชันโดยใช้มาโครที่กำหนดพารามิเตอร์ ตัวอย่างเช่นเราอาจมีรหัสเพื่อยกกำลังสองจำนวนดังนี้ -
int square(int x) {
return x * x;
}
เราสามารถเขียนโค้ดด้านบนโดยใช้มาโครได้ดังนี้ -
#define square(x) ((x) * (x))
ต้องกำหนดมาโครที่มีอาร์กิวเมนต์โดยใช้ #defineคำสั่งก่อนที่จะใช้งานได้ รายการอาร์กิวเมนต์อยู่ในวงเล็บและต้องตามด้วยชื่อแมโครทันที ไม่อนุญาตให้ใช้ช่องว่างระหว่างชื่อมาโครและวงเล็บเปิด ตัวอย่างเช่น -
#import <Foundation/Foundation.h>
#define MAX(x,y) ((x) > (y) ? (x) : (y))
int main(void) {
NSLog(@"Max between 20 and 10 is %d\n", MAX(10, 20));
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-14 05:52:15.859 demo[20683] Max between 20 and 10 is 20
ภาษาโปรแกรม Objective-C ให้คำสำคัญที่เรียกว่า typedefซึ่งคุณสามารถใช้เพื่อตั้งชื่อใหม่ได้ ต่อไปนี้เป็นตัวอย่างในการกำหนดคำศัพท์BYTE สำหรับตัวเลขหนึ่งไบต์ -
typedef unsigned char BYTE;
หลังจากนิยามประเภทนี้ตัวระบุ BYTE สามารถใช้เป็นตัวย่อสำหรับประเภทได้ unsigned char, for example:.
BYTE b1, b2;
ตามแบบแผนตัวอักษรพิมพ์ใหญ่จะใช้สำหรับคำจำกัดความเหล่านี้เพื่อเตือนผู้ใช้ว่าชื่อประเภทเป็นตัวย่อเชิงสัญลักษณ์ แต่คุณสามารถใช้ตัวพิมพ์เล็กได้ดังนี้ -
typedef unsigned char byte;
คุณสามารถใช้ได้ typedefเพื่อตั้งชื่อให้กับชนิดข้อมูลที่ผู้ใช้กำหนดเช่นกัน ตัวอย่างเช่นคุณสามารถใช้ typedef กับโครงสร้างเพื่อกำหนดชนิดข้อมูลใหม่จากนั้นใช้ชนิดข้อมูลนั้นเพื่อกำหนดตัวแปรโครงสร้างโดยตรงดังนี้ -
#import <Foundation/Foundation.h>
typedef struct Books {
NSString *title;
NSString *author;
NSString *subject;
int book_id;
} Book;
int main() {
Book book;
book.title = @"Objective-C Programming";
book.author = @"TutorialsPoint";
book.subject = @"Programming tutorial";
book.book_id = 100;
NSLog( @"Book title : %@\n", book.title);
NSLog( @"Book author : %@\n", book.author);
NSLog( @"Book subject : %@\n", book.subject);
NSLog( @"Book Id : %d\n", book.book_id);
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-12 12:21:53.745 demo[31183] Book title : Objective-C Programming
2013-09-12 12:21:53.745 demo[31183] Book author : TutorialsPoint
2013-09-12 12:21:53.745 demo[31183] Book subject : Programming tutorial
2013-09-12 12:21:53.745 demo[31183] Book Id : 100
typedef กับ #define
#define เป็นคำสั่ง Objective-C ซึ่งใช้เพื่อกำหนดนามแฝงสำหรับชนิดข้อมูลต่างๆที่คล้ายกับ typedef แต่มีความแตกต่างดังต่อไปนี้ -
typedef จำกัด เฉพาะการตั้งชื่อเชิงสัญลักษณ์ให้กับประเภทเท่านั้นในขณะที่ #define สามารถใช้เพื่อกำหนดนามแฝงสำหรับค่าได้เช่นคุณสามารถกำหนด 1 เป็น ONE เป็นต้น
typedef การตีความจะดำเนินการโดยคอมไพเลอร์โดยที่ #define คำสั่งถูกประมวลผลโดยพรีโปรเซสเซอร์
ต่อไปนี้เป็นการใช้ #define ที่ง่ายที่สุด -
#import <Foundation/Foundation.h>
#define TRUE 1
#define FALSE 0
int main( ) {
NSLog( @"Value of TRUE : %d\n", TRUE);
NSLog( @"Value of FALSE : %d\n", FALSE);
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-12 12:23:37.993 demo[5160] Value of TRUE : 1
2013-09-12 12:23:37.994 demo[5160] Value of FALSE : 0
การคัดเลือกประเภทเป็นวิธีการแปลงตัวแปรจากประเภทข้อมูลหนึ่งไปเป็นข้อมูลประเภทอื่น ตัวอย่างเช่นหากคุณต้องการเก็บค่า long เป็นจำนวนเต็มอย่างง่ายคุณสามารถพิมพ์ cast long เป็น int คุณสามารถแปลงค่าจากประเภทหนึ่งไปเป็นอีกประเภทหนึ่งได้อย่างชัดเจนโดยใช้ไฟล์cast operator ดังต่อไปนี้ -
(type_name) expression
ใน Objective-C โดยทั่วไปเราใช้ CGFloat ในการดำเนินการจุดลอยตัวซึ่งมาจากประเภทพื้นฐานของการลอยตัวในกรณีของ 32 บิตและสองเท่าในกรณีของ 64 บิต ลองพิจารณาตัวอย่างต่อไปนี้ที่ตัวดำเนินการ cast ทำให้การหารตัวแปรจำนวนเต็มหนึ่งตัวโดยอีกตัวแปรหนึ่งถูกดำเนินการเป็นการดำเนินการแบบทศนิยม -
#import <Foundation/Foundation.h>
int main() {
int sum = 17, count = 5;
CGFloat mean;
mean = (CGFloat) sum / count;
NSLog(@"Value of mean : %f\n", mean );
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-11 01:35:40.047 demo[20634] Value of mean : 3.400000
ควรสังเกตที่นี่ว่าตัวดำเนินการนักแสดงมีความสำคัญเหนือการหารดังนั้นค่าของ sum จะถูกแปลงเป็นประเภทก่อน double และสุดท้ายมันจะถูกหารด้วยจำนวนที่ให้ค่าสองเท่า
การแปลงประเภทสามารถเป็นนัยซึ่งดำเนินการโดยคอมไพเลอร์โดยอัตโนมัติหรือสามารถระบุอย่างชัดเจนผ่านการใช้ cast operator. ถือเป็นการฝึกการเขียนโปรแกรมที่ดีในการใช้ตัวดำเนินการแคสทุกครั้งที่จำเป็นต้องมีการแปลงประเภท
โปรโมชั่นจำนวนเต็ม
การส่งเสริมจำนวนเต็มคือกระบวนการที่ค่าของประเภทจำนวนเต็ม "น้อยกว่า" int หรือ unsigned int จะถูกแปลงเป็น int หรือ unsigned int. พิจารณาตัวอย่างของการเพิ่มอักขระใน int -
#import <Foundation/Foundation.h>
int main() {
int i = 17;
char c = 'c'; /* ascii value is 99 */
int sum;
sum = i + c;
NSLog(@"Value of sum : %d\n", sum );
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-11 01:38:28.492 demo[980] Value of sum : 116
ที่นี่ค่าของ sum จะมาเป็น 116 เนื่องจากคอมไพเลอร์กำลังทำการส่งเสริมจำนวนเต็มและแปลงค่าของ 'c' เป็น ascii ก่อนที่จะดำเนินการเพิ่มจริง
การแปลงเลขคณิตปกติ
usual arithmetic conversionsมีการดำเนินการโดยปริยายเพื่อโยนค่าของพวกเขาในประเภททั่วไป คอมไพลเลอร์ทำการเลื่อนขั้นจำนวนเต็มก่อนหากตัวถูกดำเนินการยังคงมีประเภทที่แตกต่างกันจากนั้นคอมไพเลอร์จะถูกแปลงเป็นประเภทที่ปรากฏสูงสุดในลำดับชั้นต่อไปนี้ -
การแปลงเลขคณิตตามปกติจะไม่ดำเนินการสำหรับตัวดำเนินการกำหนดหรือสำหรับตัวดำเนินการเชิงตรรกะ && และ || ให้เราใช้ตัวอย่างต่อไปนี้เพื่อทำความเข้าใจแนวคิด -
#import <Foundation/Foundation.h>
int main() {
int i = 17;
char c = 'c'; /* ascii value is 99 */
CGFloat sum;
sum = i + c;
NSLog(@"Value of sum : %f\n", sum );
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-11 01:41:39.192 demo[15351] Value of sum : 116.000000
ที่นี่เป็นเรื่องง่ายที่จะเข้าใจว่า c ตัวแรกถูกแปลงเป็นจำนวนเต็ม แต่เนื่องจากค่าสุดท้ายเป็นจำนวนทศนิยมดังนั้นการแปลงเลขคณิตตามปกติจึงใช้และคอมไพเลอร์จะแปลง i และ c เป็น float และเพิ่มเข้าด้วยกันเพื่อให้ได้ผลลัพธ์ที่เป็นทศนิยม
วิธี NSLog
ในการพิมพ์บันทึกเราใช้วิธี NSLog ในภาษาโปรแกรม Objective-C ซึ่งเราใช้จากตัวอย่าง Hello World
ให้เราดูรหัสง่ายๆที่จะพิมพ์คำว่า "Hello World" -
#import <Foundation/Foundation.h>
int main() {
NSLog(@"Hello, World! \n");
return 0;
}
ตอนนี้เมื่อเราคอมไพล์และรันโปรแกรมเราจะได้ผลลัพธ์ดังต่อไปนี้
2013-09-16 00:32:50.888 demo[16669] Hello, World!
การปิดบันทึกในแอพ Live
เนื่องจาก NSLogs ที่เราใช้ในแอปพลิเคชันของเรามันจะถูกพิมพ์ลงในบันทึกของอุปกรณ์และไม่เป็นการดีที่จะพิมพ์บันทึกในเวอร์ชันสด ดังนั้นเราจึงใช้คำจำกัดความประเภทสำหรับการพิมพ์บันทึกและเราสามารถใช้ได้ดังที่แสดงด้านล่าง
#import <Foundation/Foundation.h>
#if DEBUG == 0
#define DebugLog(...)
#elif DEBUG == 1
#define DebugLog(...) NSLog(__VA_ARGS__)
#endif
int main() {
DebugLog(@"Debug log, our custom addition gets \
printed during debug only" );
NSLog(@"NSLog gets printed always" );
return 0;
}
ตอนนี้เมื่อเราคอมไพล์และรันโปรแกรมในโหมด debug เราจะได้ผลลัพธ์ดังต่อไปนี้
2013-09-11 02:47:07.723 demo[618] Debug log, our custom addition gets printed during debug only
2013-09-11 02:47:07.723 demo[618] NSLog gets printed always
ตอนนี้เมื่อเราคอมไพล์และรันโปรแกรมในโหมดรีลีสเราจะได้ผลลัพธ์ดังต่อไปนี้
2013-09-11 02:47:45.248 demo[3158] NSLog gets printed always
ในการเขียนโปรแกรม Objective-C การจัดการข้อผิดพลาดมีให้กับคลาส NSError ที่มีอยู่ใน Foundation framework.
อ็อบเจ็กต์ NSError จะห่อหุ้มข้อมูลข้อผิดพลาดที่สมบูรณ์และขยายได้มากกว่าที่เป็นไปได้โดยใช้รหัสข้อผิดพลาดหรือสตริงข้อผิดพลาดเท่านั้น แอ็ตทริบิวต์หลักของอ็อบเจ็กต์ NSError คือโดเมนข้อผิดพลาด (แสดงด้วยสตริง) รหัสข้อผิดพลาดเฉพาะโดเมนและพจนานุกรมข้อมูลผู้ใช้ที่มีข้อมูลเฉพาะแอปพลิเคชัน
NSError
โปรแกรม Objective-C ใช้อ็อบเจ็กต์ NSError เพื่อถ่ายทอดข้อมูลเกี่ยวกับข้อผิดพลาดรันไทม์ที่ผู้ใช้ต้องได้รับแจ้ง ในกรณีส่วนใหญ่โปรแกรมจะแสดงข้อมูลข้อผิดพลาดนี้ในกล่องโต้ตอบหรือแผ่นงาน แต่อาจตีความข้อมูลและขอให้ผู้ใช้พยายามกู้คืนจากข้อผิดพลาดหรือพยายามแก้ไขข้อผิดพลาดด้วยตัวเอง
NSError Object ประกอบด้วย -
Domain - โดเมนข้อผิดพลาดสามารถเป็นหนึ่งในโดเมน NSError ที่กำหนดไว้ล่วงหน้าหรือสตริงที่กำหนดเองซึ่งอธิบายโดเมนที่กำหนดเองและโดเมนต้องไม่เป็นศูนย์
Code - รหัสข้อผิดพลาดสำหรับข้อผิดพลาด
User Info - พจนานุกรม userInfo สำหรับข้อผิดพลาดและ userInfo อาจเป็นศูนย์
ตัวอย่างต่อไปนี้แสดงวิธีสร้างข้อผิดพลาดแบบกำหนดเอง
NSString *domain = @"com.MyCompany.MyApplication.ErrorDomain";
NSString *desc = NSLocalizedString(@"Unable to complete the process", @"");
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : desc };
NSError *error = [NSError errorWithDomain:domain code:-101 userInfo:userInfo];
นี่คือรหัสที่สมบูรณ์ของตัวอย่างข้อผิดพลาดข้างต้นที่ส่งผ่านเป็นการอ้างอิงถึงตัวชี้ -
#import <Foundation/Foundation.h>
@interface SampleClass:NSObject
-(NSString *) getEmployeeNameForID:(int) id withError:(NSError **)errorPtr;
@end
@implementation SampleClass
-(NSString *) getEmployeeNameForID:(int) id withError:(NSError **)errorPtr {
if(id == 1) {
return @"Employee Test Name";
} else {
NSString *domain = @"com.MyCompany.MyApplication.ErrorDomain";
NSString *desc =@"Unable to complete the process";
NSDictionary *userInfo = [[NSDictionary alloc]
initWithObjectsAndKeys:desc,
@"NSLocalizedDescriptionKey",NULL];
*errorPtr = [NSError errorWithDomain:domain code:-101
userInfo:userInfo];
return @"";
}
}
@end
int main() {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
SampleClass *sampleClass = [[SampleClass alloc]init];
NSError *error = nil;
NSString *name1 = [sampleClass getEmployeeNameForID:1 withError:&error];
if(error) {
NSLog(@"Error finding Name1: %@",error);
} else {
NSLog(@"Name1: %@",name1);
}
error = nil;
NSString *name2 = [sampleClass getEmployeeNameForID:2 withError:&error];
if(error) {
NSLog(@"Error finding Name2: %@",error);
} else {
NSLog(@"Name2: %@",name2);
}
[pool drain];
return 0;
}
ในตัวอย่างข้างต้นเราจะส่งคืนชื่อหาก id เป็น 1 มิฉะนั้นเราจะตั้งค่าออบเจ็กต์ข้อผิดพลาดที่ผู้ใช้กำหนดเอง
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-14 18:01:00.809 demo[27632] Name1: Employee Test Name
2013-09-14 18:01:00.809 demo[27632] Error finding Name2: Unable to complete the process
เป็นไปได้ที่จะส่งผ่านค่าบางอย่างจากบรรทัดคำสั่งไปยังโปรแกรม Objective-C ของคุณเมื่อดำเนินการ ค่าเหล่านี้เรียกว่าcommand line arguments และหลายครั้งสิ่งเหล่านี้มีความสำคัญสำหรับโปรแกรมของคุณโดยเฉพาะอย่างยิ่งเมื่อคุณต้องการควบคุมโปรแกรมของคุณจากภายนอกแทนที่จะเข้ารหัสค่าเหล่านั้นอย่างหนักภายในโค้ด
อาร์กิวเมนต์บรรทัดคำสั่งถูกจัดการโดยใช้อาร์กิวเมนต์ของฟังก์ชัน main () โดยที่ argc หมายถึงจำนวนอาร์กิวเมนต์ที่ส่งผ่านและ argv[]คืออาร์เรย์ตัวชี้ซึ่งชี้ไปยังแต่ละอาร์กิวเมนต์ที่ส่งผ่านไปยังโปรแกรม ต่อไปนี้เป็นตัวอย่างง่ายๆซึ่งตรวจสอบว่ามีอาร์กิวเมนต์ใด ๆ จากบรรทัดคำสั่งและดำเนินการตามนั้น -
#import <Foundation/Foundation.h>
int main( int argc, char *argv[] ) {
if( argc == 2 ) {
NSLog(@"The argument supplied is %s\n", argv[1]);
} else if( argc > 2 ) {
NSLog(@"Too many arguments supplied.\n");
} else {
NSLog(@"One argument expected.\n");
}
}
เมื่อโค้ดด้านบนถูกคอมไพล์และดำเนินการด้วยอาร์กิวเมนต์เดียวให้พูดว่า "การทดสอบ" จะให้ผลลัพธ์ดังต่อไปนี้
2013-09-13 03:01:17.333 demo[7640] The argument supplied is testing
เมื่อโค้ดด้านบนถูกคอมไพล์และดำเนินการโดยมีอาร์กิวเมนต์สองตัวพูดว่า testing1 และ testing2 จะให้ผลลัพธ์ดังต่อไปนี้
2013-09-13 03:01:18.333 demo[7640] Too many arguments supplied.
เมื่อโค้ดด้านบนถูกคอมไพล์และดำเนินการโดยไม่ผ่านอาร์กิวเมนต์ใด ๆ จะให้ผลลัพธ์ดังต่อไปนี้
2013-09-13 03:01:18.333 demo[7640] One argument expected
ควรสังเกตว่า argv[0] ถือชื่อของโปรแกรมเองและ argv[1]เป็นตัวชี้ไปยังอาร์กิวเมนต์บรรทัดคำสั่งแรกที่ให้มาและ * argv [n] คืออาร์กิวเมนต์สุดท้าย หากไม่มีการระบุอาร์กิวเมนต์อาร์กิวเมนต์จะเป็นหนึ่งมิฉะนั้นหากคุณส่งอาร์กิวเมนต์หนึ่งอาร์กิวเมนต์argc ตั้งไว้ที่ 2
คุณส่งอาร์กิวเมนต์บรรทัดคำสั่งทั้งหมดที่คั่นด้วยช่องว่าง แต่ถ้าอาร์กิวเมนต์มีช่องว่างคุณสามารถส่งผ่านอาร์กิวเมนต์ดังกล่าวได้โดยใส่ไว้ในเครื่องหมายคำพูดคู่ "" หรือเครื่องหมายคำพูดเดี่ยว " ให้เราเขียนตัวอย่างข้างต้นอีกครั้งซึ่งเราจะพิมพ์ชื่อโปรแกรมและเรายังส่งอาร์กิวเมนต์บรรทัดคำสั่งโดยใส่เครื่องหมายคำพูดคู่ -
#import <Foundation/Foundation.h>
int main( int argc, char *argv[] ) {
NSLog(@"Program name %s\n", argv[0]);
if( argc == 2 ) {
NSLog(@"The argument supplied is %s\n", argv[1]);
} else if( argc > 2 ) {
NSLog(@"Too many arguments supplied.\n");
} else {
NSLog(@"One argument expected.\n");
}
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และดำเนินการด้วยอาร์กิวเมนต์เดียวที่คั่นด้วยช่องว่าง แต่ภายในเครื่องหมายคำพูดคู่พูดว่า "Testing1 Testing2" จะให้ผลลัพธ์ดังต่อไปนี้
2017-11-30 06:36:59.081 main[71010] Program name main
2017-11-30 06:36:59.082 main[71010] One argument expected.
วัตถุประสงค์หลักของการเขียนโปรแกรมภาษา Objective-C คือการเพิ่มการวางแนววัตถุให้กับภาษาโปรแกรม C และคลาสเป็นคุณสมบัติหลักของ Objective-C ที่สนับสนุนการเขียนโปรแกรมเชิงวัตถุและมักเรียกว่าชนิดที่ผู้ใช้กำหนดเอง
คลาสถูกใช้เพื่อระบุรูปแบบของอ็อบเจ็กต์และรวมการแทนข้อมูลและวิธีการจัดการข้อมูลนั้นเป็นแพ็กเกจเดียว ข้อมูลและวิธีการภายในคลาสเรียกว่าสมาชิกของคลาส
ลักษณะวัตถุประสงค์ -C
คลาสถูกกำหนดในสองส่วนที่แตกต่างกันคือ @interface และ @implementation.
เกือบทุกอย่างอยู่ในรูปของวัตถุ
วัตถุรับข้อความและวัตถุมักเรียกว่าตัวรับ
ออบเจ็กต์มีตัวแปรอินสแตนซ์
ออบเจ็กต์และตัวแปรอินสแตนซ์มีขอบเขต
คลาสซ่อนการใช้งานของออบเจ็กต์
คุณสมบัติถูกใช้เพื่อให้การเข้าถึงตัวแปรอินสแตนซ์คลาสในคลาสอื่น ๆ
นิยามคลาส Objective-C
เมื่อคุณกำหนดคลาสคุณจะกำหนดพิมพ์เขียวสำหรับชนิดข้อมูล สิ่งนี้ไม่ได้กำหนดข้อมูลใด ๆ แต่เป็นการกำหนดความหมายของชื่อคลาสนั่นคือสิ่งที่วัตถุของคลาสจะประกอบด้วยและสิ่งที่สามารถดำเนินการกับวัตถุดังกล่าวได้
นิยามคลาสเริ่มต้นด้วยคีย์เวิร์ด @interfaceตามด้วยชื่ออินเตอร์เฟส (คลาส); และตัวคลาสล้อมรอบด้วยวงเล็บปีกกาคู่หนึ่ง ใน Objective-C คลาสทั้งหมดมาจากคลาสพื้นฐานที่เรียกว่าNSObject. เป็นซูเปอร์คลาสของคลาส Objective-C ทั้งหมด มีวิธีการพื้นฐานเช่นการจัดสรรหน่วยความจำและการเริ่มต้น ตัวอย่างเช่นเรากำหนดประเภทข้อมูล Box โดยใช้คำสำคัญclass ดังต่อไปนี้ -
@interface Box:NSObject {
//Instance variables
double length; // Length of a box
double breadth; // Breadth of a box
}
@property(nonatomic, readwrite) double height; // Property
@end
ตัวแปรอินสแตนซ์เป็นแบบส่วนตัวและสามารถเข้าถึงได้ภายในการใช้งานคลาสเท่านั้น
การจัดสรรและเริ่มต้น Objective-C Objects
คลาสจัดเตรียมพิมพ์เขียวสำหรับอ็อบเจ็กต์ดังนั้นโดยพื้นฐานแล้วอ็อบเจ็กต์จะถูกสร้างขึ้นจากคลาส เราประกาศออบเจ็กต์ของคลาสด้วยการประกาศประเภทเดียวกันกับที่เราประกาศตัวแปรประเภทพื้นฐาน คำสั่งต่อไปนี้ประกาศสองวัตถุของคลาส Box -
Box box1 = [[Box alloc]init]; // Create box1 object of type Box
Box box2 = [[Box alloc]init]; // Create box2 object of type Box
ทั้งวัตถุ box1 และ box2 จะมีสำเนาข้อมูลของตัวเอง
การเข้าถึงสมาชิกข้อมูล
คุณสมบัติของอ็อบเจ็กต์ของคลาสสามารถเข้าถึงได้โดยใช้ตัวดำเนินการเข้าถึงสมาชิกโดยตรง (.) ให้เราลองใช้ตัวอย่างต่อไปนี้เพื่อทำให้ชัดเจน -
#import <Foundation/Foundation.h>
@interface Box:NSObject {
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
}
@property(nonatomic, readwrite) double height; // Property
-(double) volume;
@end
@implementation Box
@synthesize height;
-(id)init {
self = [super init];
length = 1.0;
breadth = 1.0;
return self;
}
-(double) volume {
return length*breadth*height;
}
@end
int main() {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Box *box1 = [[Box alloc]init]; // Create box1 object of type Box
Box *box2 = [[Box alloc]init]; // Create box2 object of type Box
double volume = 0.0; // Store the volume of a box here
// box 1 specification
box1.height = 5.0;
// box 2 specification
box2.height = 10.0;
// volume of box 1
volume = [box1 volume];
NSLog(@"Volume of Box1 : %f", volume);
// volume of box 2
volume = [box2 volume];
NSLog(@"Volume of Box2 : %f", volume);
[pool drain];
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-22 21:25:33.314 ClassAndObjects[387:303] Volume of Box1 : 5.000000
2013-09-22 21:25:33.316 ClassAndObjects[387:303] Volume of Box2 : 10.000000
คุณสมบัติ
คุณสมบัติถูกนำมาใช้ใน Objective-C เพื่อให้แน่ใจว่าตัวแปรอินสแตนซ์ของคลาสสามารถเข้าถึงได้ภายนอกคลาส
คุณสมบัติเริ่มต้นด้วย @propertyซึ่งเป็นคำหลัก
ตามด้วยตัวระบุการเข้าถึงซึ่งไม่ใช่อะตอมหรือปรมาณูอ่านเขียนหรืออ่านอย่างเดียวและแข็งแรงไม่ปลอดภัยไม่ปลอดภัยหรืออ่อนแอ สิ่งนี้จะแตกต่างกันไปตามประเภทของตัวแปร สำหรับตัวชี้ประเภทใด ๆ เราสามารถใช้ strong, unsafe_unretained หรืออ่อนแอ ในทำนองเดียวกันสำหรับประเภทอื่น ๆ เราสามารถใช้อ่านเขียนหรืออ่านอย่างเดียว
ตามด้วยประเภทข้อมูลของตัวแปร
ในที่สุดเรามีชื่อคุณสมบัติที่ปิดท้ายด้วยอัฒภาค
เราสามารถเพิ่มคำสั่งสังเคราะห์ในคลาสการนำไปใช้ แต่ใน XCode ล่าสุดส่วนการสังเคราะห์ได้รับการดูแลโดย XCode และคุณไม่จำเป็นต้องรวมคำสั่งสังเคราะห์
เป็นไปได้เฉพาะกับคุณสมบัติที่เราสามารถเข้าถึงตัวแปรอินสแตนซ์ของคลาสได้ จริงๆแล้วเมธอด getter และ setter ภายในถูกสร้างขึ้นสำหรับคุณสมบัติ
ตัวอย่างเช่นสมมติว่าเรามีคุณสมบัติ @property (nonatomic ,readonly ) BOOL isDone. ใต้ฝากระโปรงมีตัวตั้งและตัวรับที่สร้างขึ้นตามที่แสดงด้านล่าง
-(void)setIsDone(BOOL)isDone;
-(BOOL)isDone;
แนวคิดที่สำคัญที่สุดอย่างหนึ่งในการเขียนโปรแกรมเชิงวัตถุคือการถ่ายทอดทางพันธุกรรม การสืบทอดช่วยให้เราสามารถกำหนดคลาสในรูปแบบของคลาสอื่นซึ่งทำให้ง่ายต่อการสร้างและดูแลแอปพลิเคชัน นอกจากนี้ยังให้โอกาสในการนำฟังก์ชันโค้ดกลับมาใช้ซ้ำและใช้งานได้รวดเร็ว
เมื่อสร้างคลาสแทนที่จะเขียนสมาชิกข้อมูลและฟังก์ชันสมาชิกใหม่ทั้งหมดโปรแกรมเมอร์สามารถกำหนดได้ว่าคลาสใหม่ควรสืบทอดสมาชิกของคลาสที่มีอยู่ คลาสที่มีอยู่นี้เรียกว่าbase คลาสและคลาสใหม่เรียกว่า derived ชั้นเรียน.
แนวคิดเรื่องการถ่ายทอดทางพันธุกรรมใช้ is aความสัมพันธ์. ตัวอย่างเช่นสัตว์เลี้ยงลูกด้วยนม IS-A สุนัข IS-A สัตว์เลี้ยงลูกด้วยนมดังนั้นสุนัข IS-A เช่นกันและอื่น ๆ
ฐานและคลาสที่ได้รับ
Objective-C อนุญาตให้มีการสืบทอดหลายระดับเท่านั้นกล่าวคือสามารถมีคลาสพื้นฐานได้เพียงคลาสเดียว แต่อนุญาตให้มีการสืบทอดหลายระดับ คลาสทั้งหมดใน Objective-C มาจาก superclassNSObject.
@interface derived-class: base-class
พิจารณาคลาสพื้นฐาน Person และคลาสที่ได้รับมา Employee ดังต่อไปนี้ -
#import <Foundation/Foundation.h>
@interface Person : NSObject {
NSString *personName;
NSInteger personAge;
}
- (id)initWithName:(NSString *)name andAge:(NSInteger)age;
- (void)print;
@end
@implementation Person
- (id)initWithName:(NSString *)name andAge:(NSInteger)age {
personName = name;
personAge = age;
return self;
}
- (void)print {
NSLog(@"Name: %@", personName);
NSLog(@"Age: %ld", personAge);
}
@end
@interface Employee : Person {
NSString *employeeEducation;
}
- (id)initWithName:(NSString *)name andAge:(NSInteger)age
andEducation:(NSString *)education;
- (void)print;
@end
@implementation Employee
- (id)initWithName:(NSString *)name andAge:(NSInteger)age
andEducation: (NSString *)education {
personName = name;
personAge = age;
employeeEducation = education;
return self;
}
- (void)print {
NSLog(@"Name: %@", personName);
NSLog(@"Age: %ld", personAge);
NSLog(@"Education: %@", employeeEducation);
}
@end
int main(int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSLog(@"Base class Person Object");
Person *person = [[Person alloc]initWithName:@"Raj" andAge:5];
[person print];
NSLog(@"Inherited Class Employee Object");
Employee *employee = [[Employee alloc]initWithName:@"Raj"
andAge:5 andEducation:@"MBA"];
[employee print];
[pool drain];
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-22 21:20:09.842 Inheritance[349:303] Base class Person Object
2013-09-22 21:20:09.844 Inheritance[349:303] Name: Raj
2013-09-22 21:20:09.844 Inheritance[349:303] Age: 5
2013-09-22 21:20:09.845 Inheritance[349:303] Inherited Class Employee Object
2013-09-22 21:20:09.845 Inheritance[349:303] Name: Raj
2013-09-22 21:20:09.846 Inheritance[349:303] Age: 5
2013-09-22 21:20:09.846 Inheritance[349:303] Education: MBA
การควบคุมการเข้าถึงและการสืบทอด
คลาสที่ได้รับสามารถเข้าถึงสมาชิกส่วนตัวทั้งหมดของคลาสพื้นฐานได้หากกำหนดไว้ในคลาสอินเตอร์เฟส แต่ไม่สามารถเข้าถึงสมาชิกส่วนตัวที่กำหนดไว้ในไฟล์การนำไปใช้งานได้
เราสามารถสรุปประเภทการเข้าถึงต่างๆตามผู้ที่สามารถเข้าถึงได้ด้วยวิธีต่อไปนี้ -
คลาสที่ได้รับสืบทอดเมธอดคลาสพื้นฐานและตัวแปรทั้งหมดโดยมีข้อยกเว้นต่อไปนี้ -
ตัวแปรที่ประกาศในไฟล์การนำไปใช้งานด้วยความช่วยเหลือของส่วนขยายไม่สามารถเข้าถึงได้
ไม่สามารถเข้าถึงวิธีการที่ประกาศในไฟล์การนำไปใช้งานโดยใช้นามสกุลได้
ในกรณีที่คลาสที่สืบทอดมาใช้เมธอดในคลาสพื้นฐานเมธอดในคลาสที่ได้รับจะถูกเรียกใช้
คำ polymorphismหมายถึงมีหลายรูปแบบ โดยปกติความหลากหลายเกิดขึ้นเมื่อมีลำดับชั้นของคลาสและมีความสัมพันธ์กันโดยการถ่ายทอดทางพันธุกรรม
Objective-C polymorphism หมายความว่าการเรียกใช้ฟังก์ชันสมาชิกจะทำให้ฟังก์ชันที่แตกต่างกันถูกเรียกใช้ขึ้นอยู่กับประเภทของวัตถุที่เรียกใช้ฟังก์ชัน
ลองพิจารณาตัวอย่างเรามีคลาส Shape ที่ให้อินเทอร์เฟซพื้นฐานสำหรับรูปร่างทั้งหมด Square และ Rectangle ได้มาจาก Shape คลาสพื้นฐาน
เรามีวิธี printArea ที่จะแสดงเกี่ยวกับคุณสมบัติ OOP polymorphism.
#import <Foundation/Foundation.h>
@interface Shape : NSObject {
CGFloat area;
}
- (void)printArea;
- (void)calculateArea;
@end
@implementation Shape
- (void)printArea {
NSLog(@"The area is %f", area);
}
- (void)calculateArea {
}
@end
@interface Square : Shape {
CGFloat length;
}
- (id)initWithSide:(CGFloat)side;
- (void)calculateArea;
@end
@implementation Square
- (id)initWithSide:(CGFloat)side {
length = side;
return self;
}
- (void)calculateArea {
area = length * length;
}
- (void)printArea {
NSLog(@"The area of square is %f", area);
}
@end
@interface Rectangle : Shape {
CGFloat length;
CGFloat breadth;
}
- (id)initWithLength:(CGFloat)rLength andBreadth:(CGFloat)rBreadth;
@end
@implementation Rectangle
- (id)initWithLength:(CGFloat)rLength andBreadth:(CGFloat)rBreadth {
length = rLength;
breadth = rBreadth;
return self;
}
- (void)calculateArea {
area = length * breadth;
}
@end
int main(int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Shape *square = [[Square alloc]initWithSide:10.0];
[square calculateArea];
[square printArea];
Shape *rect = [[Rectangle alloc]
initWithLength:10.0 andBreadth:5.0];
[rect calculateArea];
[rect printArea];
[pool drain];
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-22 21:21:50.785 Polymorphism[358:303] The area of square is 100.000000
2013-09-22 21:21:50.786 Polymorphism[358:303] The area is 50.000000
ในตัวอย่างข้างต้นขึ้นอยู่กับความพร้อมใช้งานของวิธีการคำนวณพื้นที่และ printArea ไม่ว่าจะเป็นวิธีการในคลาสฐานหรือคลาสที่ได้รับที่ดำเนินการ
Polymorphism จัดการการสลับวิธีการระหว่างคลาสฐานและคลาสที่ได้รับโดยอาศัยวิธีการใช้งานของคลาสทั้งสอง
โปรแกรม Objective-C ทั้งหมดประกอบด้วยองค์ประกอบพื้นฐานสองประการต่อไปนี้ -
Program statements (code) - นี่คือส่วนหนึ่งของโปรแกรมที่ดำเนินการและเรียกว่าวิธีการ
Program data - ข้อมูลเป็นข้อมูลของโปรแกรมที่ได้รับผลกระทบจากการทำงานของโปรแกรม
การห่อหุ้มเป็นแนวคิดการเขียนโปรแกรมเชิงวัตถุที่รวมข้อมูลและฟังก์ชันที่จัดการข้อมูลเข้าด้วยกันและช่วยให้ทั้งสองปลอดภัยจากการรบกวนภายนอกและการใช้งานในทางที่ผิด การห่อหุ้มข้อมูลนำไปสู่แนวคิด OOP ที่สำคัญของdata hiding.
Data encapsulation เป็นกลไกในการรวมข้อมูลและฟังก์ชันที่ใช้และ data abstraction เป็นกลไกในการเปิดเผยเฉพาะอินเทอร์เฟซและซ่อนรายละเอียดการใช้งานจากผู้ใช้
Objective-C สนับสนุนคุณสมบัติของการห่อหุ้มและการซ่อนข้อมูลผ่านการสร้างชนิดที่ผู้ใช้กำหนดเรียกว่า classes. ตัวอย่างเช่น -
@interface Adder : NSObject {
NSInteger total;
}
- (id)initWithInitialNumber:(NSInteger)initialNumber;
- (void)addNumber:(NSInteger)newNumber;
- (NSInteger)getTotal;
@end
ผลรวมของตัวแปรเป็นแบบส่วนตัวและเราไม่สามารถเข้าถึงจากภายนอกคลาสได้ ซึ่งหมายความว่าสมาชิกคนอื่น ๆ ในคลาส Adder สามารถเข้าถึงได้เท่านั้นและไม่สามารถเข้าถึงได้จากส่วนอื่น ๆ ของโปรแกรมของคุณ นี่เป็นวิธีการห่อหุ้มวิธีหนึ่งที่ทำได้
วิธีการภายในไฟล์อินเตอร์เฟสสามารถเข้าถึงได้และเป็นแบบสาธารณะในขอบเขต
มีวิธีการส่วนตัวซึ่งเขียนด้วยความช่วยเหลือของ extensionsซึ่งเราจะเรียนรู้ในบทต่อ ๆ ไป
ตัวอย่างการห่อหุ้มข้อมูล
โปรแกรม Objective-C ใด ๆ ที่คุณใช้คลาสที่มีตัวแปรสมาชิกสาธารณะและส่วนตัวเป็นตัวอย่างของการห่อหุ้มข้อมูลและการแยกข้อมูล ลองพิจารณาตัวอย่างต่อไปนี้ -
#import <Foundation/Foundation.h>
@interface Adder : NSObject {
NSInteger total;
}
- (id)initWithInitialNumber:(NSInteger)initialNumber;
- (void)addNumber:(NSInteger)newNumber;
- (NSInteger)getTotal;
@end
@implementation Adder
-(id)initWithInitialNumber:(NSInteger)initialNumber {
total = initialNumber;
return self;
}
- (void)addNumber:(NSInteger)newNumber {
total = total + newNumber;
}
- (NSInteger)getTotal {
return total;
}
@end
int main(int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Adder *adder = [[Adder alloc]initWithInitialNumber:10];
[adder addNumber:5];
[adder addNumber:4];
NSLog(@"The total is %ld",[adder getTotal]);
[pool drain];
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
2013-09-22 21:17:30.485 DataEncapsulation[317:303] The total is 19
ชั้นเรียนด้านบนจะเพิ่มตัวเลขเข้าด้วยกันและส่งกลับผลรวม สมาชิกสาธารณะaddNum และ getTotal เป็นส่วนต่อประสานกับโลกภายนอกและผู้ใช้จำเป็นต้องรู้จักพวกเขาเพื่อใช้คลาส สมาชิกส่วนตัวtotal เป็นสิ่งที่ซ่อนตัวจากโลกภายนอก แต่จำเป็นสำหรับชั้นเรียนเพื่อให้ทำงานได้อย่างถูกต้อง
การออกแบบกลยุทธ์
พวกเราส่วนใหญ่ได้เรียนรู้จากประสบการณ์อันขมขื่นเพื่อให้สมาชิกชั้นเรียนเป็นส่วนตัวโดยปริยายเว้นแต่เราจำเป็นต้องเปิดเผยพวกเขาจริงๆ นั่นเป็นสิ่งที่ดีencapsulation.
สิ่งสำคัญคือต้องเข้าใจการห่อหุ้มข้อมูลเนื่องจากเป็นหนึ่งในคุณสมบัติหลักของภาษา Object-Oriented Programming (OOP) ทั้งหมดรวมถึง Objective-C
บางครั้งคุณอาจพบว่าต้องการขยายชั้นเรียนที่มีอยู่โดยเพิ่มพฤติกรรมที่มีประโยชน์ในบางสถานการณ์เท่านั้น ในการเพิ่มส่วนขยายดังกล่าวลงในคลาสที่มีอยู่ Objective-C จะให้categories และ extensions.
หากคุณต้องการเพิ่มวิธีการลงในคลาสที่มีอยู่บางทีเพื่อเพิ่มฟังก์ชันการทำงานเพื่อให้ง่ายต่อการทำบางสิ่งในแอปพลิเคชันของคุณเองวิธีที่ง่ายที่สุดคือการใช้หมวดหมู่
ไวยากรณ์ในการประกาศประเภทใช้คีย์เวิร์ด @interface เช่นเดียวกับคำอธิบายคลาส Objective-C มาตรฐาน แต่ไม่ได้ระบุการสืบทอดจากคลาสย่อย แต่จะระบุชื่อหมวดหมู่ในวงเล็บเช่นนี้ -
@interface ClassName (CategoryName)
@end
ลักษณะของหมวดหมู่
คุณสามารถประกาศหมวดหมู่สำหรับคลาสใดก็ได้แม้ว่าคุณจะไม่มีซอร์สโค้ดการติดตั้งดั้งเดิมก็ตาม
วิธีการใด ๆ ที่คุณประกาศในหมวดหมู่จะใช้ได้กับทุกอินสแตนซ์ของคลาสดั้งเดิมตลอดจนคลาสย่อยของคลาสดั้งเดิม
ในรันไทม์ไม่มีความแตกต่างระหว่างวิธีการที่เพิ่มโดยหมวดหมู่และวิธีการที่ใช้งานโดยคลาสดั้งเดิม
ตอนนี้เรามาดูตัวอย่างการใช้งานหมวดหมู่ มาเพิ่มหมวดหมู่ให้กับ Cocoa class NSString หมวดหมู่นี้จะช่วยให้เราสามารถเพิ่มวิธีการใหม่ getCopyRightString ซึ่งช่วยเราในการส่งคืนสตริงลิขสิทธิ์ ดังแสดงด้านล่าง
#import <Foundation/Foundation.h>
@interface NSString(MyAdditions)
+(NSString *)getCopyRightString;
@end
@implementation NSString(MyAdditions)
+(NSString *)getCopyRightString {
return @"Copyright TutorialsPoint.com 2013";
}
@end
int main(int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString *copyrightString = [NSString getCopyRightString];
NSLog(@"Accessing Category: %@",copyrightString);
[pool drain];
return 0;
}
ตอนนี้เมื่อเราคอมไพล์และรันโปรแกรมเราจะได้ผลลัพธ์ดังต่อไปนี้
2013-09-22 21:19:12.125 Categories[340:303] Accessing Category: Copyright TutorialsPoint.com 2013
แม้ว่าวิธีการใด ๆ ที่เพิ่มโดยหมวดหมู่จะสามารถใช้ได้กับทุกอินสแตนซ์ของคลาสและคลาสย่อยคุณจะต้องนำเข้าไฟล์ส่วนหัวของหมวดหมู่ในไฟล์ซอร์สโค้ดใด ๆ ที่คุณต้องการใช้วิธีการเพิ่มเติมมิฉะนั้นคุณจะพบ คำเตือนและข้อผิดพลาดของคอมไพเลอร์
ในตัวอย่างของเราเนื่องจากเรามีคลาสเดียวเราจึงไม่ได้รวมไฟล์ส่วนหัวใด ๆ ในกรณีเช่นนี้เราควรรวมไฟล์ส่วนหัวตามที่กล่าวไว้ข้างต้น
ก่อนที่จะเริ่มเกี่ยวกับการโพสท่าใน Objective-C ฉันขอแจ้งให้คุณทราบว่าการโพสท่าถูกประกาศเลิกใช้ใน Mac OS X 10.5 และไม่สามารถใช้งานได้หลังจากนั้น ดังนั้นสำหรับผู้ที่ไม่กังวลเกี่ยวกับวิธีการเลิกใช้งานเหล่านี้สามารถข้ามบทนี้ไปได้
Objective-C อนุญาตให้คลาสแทนที่คลาสอื่นทั้งหมดภายในโปรแกรม คลาสแทนที่กล่าวว่า "ก่อให้เกิด" คลาสเป้าหมาย
สำหรับเวอร์ชันที่รองรับการวางตัวข้อความทั้งหมดที่ส่งไปยังคลาสเป้าหมายจะได้รับคลาสการวางตัวแทน
NSObject มีเมธอด poseAsClass: ที่ช่วยให้เราสามารถแทนที่คลาสที่มีอยู่ตามที่กล่าวไว้ข้างต้น
ข้อ จำกัด ในการวางตัว
ชั้นเรียนสามารถจัดเป็นหนึ่งในซุปเปอร์คลาสทั้งทางตรงหรือทางอ้อมเท่านั้น
คลาสการวางตัวจะต้องไม่กำหนดตัวแปรอินสแตนซ์ใหม่ใด ๆ ที่ไม่อยู่ในคลาสเป้าหมาย (แม้ว่ามันอาจกำหนดหรือแทนที่เมธอด)
คลาสเป้าหมายอาจไม่ได้รับข้อความใด ๆ ก่อนการวางตัว
คลาสการวางตัวสามารถเรียกใช้เมธอดที่ถูกลบล้างผ่าน super ซึ่งรวมเอาการใช้คลาสเป้าหมาย
คลาสการวางตัวสามารถแทนที่วิธีการที่กำหนดไว้ในหมวดหมู่ได้
#import <Foundation/Foundation.h>
@interface MyString : NSString
@end
@implementation MyString
- (NSString *)stringByReplacingOccurrencesOfString:(NSString *)target
withString:(NSString *)replacement {
NSLog(@"The Target string is %@",target);
NSLog(@"The Replacement string is %@",replacement);
}
@end
int main() {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
[MyString poseAsClass:[NSString class]];
NSString *string = @"Test";
[string stringByReplacingOccurrencesOfString:@"a" withString:@"c"];
[pool drain];
return 0;
}
ตอนนี้เมื่อเราคอมไพล์และรันโปรแกรมใน Mac OS X รุ่นเก่า (V_10.5 หรือก่อนหน้า) เราจะได้ผลลัพธ์ดังต่อไปนี้
2013-09-22 21:23:46.829 Posing[372:303] The Target string is a
2013-09-22 21:23:46.830 Posing[372:303] The Replacement string is c
ในตัวอย่างข้างต้นเราเพียงแค่ทำให้วิธีการเดิมเป็นมลพิษด้วยการใช้งานของเราและสิ่งนี้จะได้รับผลกระทบตลอดการดำเนินการ NSString ด้วยวิธีการข้างต้น
ส่วนขยายคลาสมีความคล้ายคลึงกันกับหมวดหมู่ แต่สามารถเพิ่มลงในคลาสที่คุณมีซอร์สโค้ดในเวลาคอมไพล์เท่านั้น (คลาสจะคอมไพล์พร้อมกันกับส่วนขยายคลาส)
วิธีการที่ประกาศโดยส่วนขยายคลาสจะถูกนำไปใช้ในบล็อกการนำไปใช้งานสำหรับคลาสดั้งเดิมดังนั้นคุณจึงไม่สามารถประกาศส่วนขยายคลาสบนคลาสเฟรมเวิร์กเช่นคลาส Cocoa หรือ Cocoa Touch เช่น NSString
ส่วนขยายเป็นหมวดหมู่ที่ไม่มีชื่อหมวดหมู่ มักเรียกว่าanonymous categories.
ไวยากรณ์ในการประกาศส่วนขยายใช้คีย์เวิร์ด @interface เช่นเดียวกับคำอธิบายคลาส Objective-C มาตรฐาน แต่ไม่ได้ระบุการสืบทอดจากคลาสย่อย แต่เพียงแค่เพิ่มวงเล็บดังที่แสดงด้านล่าง -
@interface ClassName ()
@end
ลักษณะของส่วนขยาย
ไม่สามารถประกาศส่วนขยายสำหรับคลาสใด ๆ ได้เฉพาะคลาสที่เรามีการใช้งานซอร์สโค้ดดั้งเดิมเท่านั้น
ส่วนขยายกำลังเพิ่มเมธอดส่วนตัวและตัวแปรส่วนตัวที่เฉพาะเจาะจงสำหรับคลาสเท่านั้น
วิธีการหรือตัวแปรใด ๆ ที่ประกาศภายในส่วนขยายจะไม่สามารถเข้าถึงได้แม้แต่คลาสที่สืบทอดมา
ตัวอย่างส่วนขยาย
มาสร้างคลาส SampleClass ที่มีส่วนขยาย ในส่วนขยายขอมี internalID ตัวแปรส่วนตัว
จากนั้นให้มีเมธอด getExternalID ที่คืนค่า externalID หลังจากประมวลผล internalID
ตัวอย่างดังแสดงด้านล่างและสิ่งนี้จะใช้ไม่ได้กับคอมไพเลอร์ออนไลน์
#import <Foundation/Foundation.h>
@interface SampleClass : NSObject {
NSString *name;
}
- (void)setInternalID;
- (NSString *)getExternalID;
@end
@interface SampleClass() {
NSString *internalID;
}
@end
@implementation SampleClass
- (void)setInternalID {
internalID = [NSString stringWithFormat:
@"UNIQUEINTERNALKEY%dUNIQUEINTERNALKEY",arc4random()%100];
}
- (NSString *)getExternalID {
return [internalID stringByReplacingOccurrencesOfString:
@"UNIQUEINTERNALKEY" withString:@""];
}
@end
int main(int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
SampleClass *sampleClass = [[SampleClass alloc]init];
[sampleClass setInternalID];
NSLog(@"ExternalID: %@",[sampleClass getExternalID]);
[pool drain];
return 0;
}
ตอนนี้เมื่อเราคอมไพล์และรันโปรแกรมเราจะได้ผลลัพธ์ดังต่อไปนี้
2013-09-22 21:18:31.754 Extensions[331:303] ExternalID: 51
จากตัวอย่างข้างต้นเราจะเห็นว่า internalID ไม่ได้ส่งคืนโดยตรง เราจะลบ UNIQUEINTERNALKEY ที่นี่และทำให้เฉพาะค่าที่เหลือพร้อมใช้งานสำหรับเมธอด getExternalID เท่านั้น
ตัวอย่างข้างต้นใช้การดำเนินการแบบสตริง แต่อาจมีคุณสมบัติมากมายเช่นการเข้ารหัส / ถอดรหัสเป็นต้น
Objective-C ช่วยให้คุณกำหนดโปรโตคอลซึ่งประกาศวิธีการที่คาดว่าจะใช้สำหรับสถานการณ์เฉพาะ โปรโตคอลถูกนำไปใช้ในคลาสที่สอดคล้องกับโปรโตคอล
ตัวอย่างง่ายๆก็คือคลาสการจัดการ URL ของเครือข่ายซึ่งจะมีโปรโตคอลที่มีวิธีการเช่นเมธอดผู้ร่วมประชุม processCompleted ที่ข่มขู่คลาสการโทรเมื่อการดำเนินการดึง URL เครือข่ายสิ้นสุดลง
ไวยากรณ์ของโปรโตคอลแสดงอยู่ด้านล่าง
@protocol ProtocolName
@required
// list of required methods
@optional
// list of optional methods
@end
วิธีการภายใต้คำหลัก @required จะต้องนำไปใช้ในคลาสที่สอดคล้องกับโปรโตคอลและวิธีการภายใต้ @optional คำหลักเป็นทางเลือกในการใช้งาน
นี่คือไวยากรณ์สำหรับคลาสที่สอดคล้องกับโปรโตคอล
@interface MyClass : NSObject <MyProtocol>
...
@end
ซึ่งหมายความว่าอินสแตนซ์ใด ๆ ของ MyClass จะไม่เพียงตอบสนองต่อวิธีการที่ประกาศไว้โดยเฉพาะในอินเทอร์เฟซเท่านั้น แต่ MyClass ยังให้การใช้งานสำหรับวิธีการที่จำเป็นใน MyProtocol ไม่จำเป็นต้องประกาศเมธอดโปรโตคอลอีกครั้งในอินเทอร์เฟซคลาส - การนำโปรโตคอลมาใช้ก็เพียงพอแล้ว
หากคุณต้องการคลาสเพื่อใช้โปรโตคอลหลายตัวคุณสามารถระบุเป็นรายการที่คั่นด้วยจุลภาค เรามีวัตถุผู้รับมอบสิทธิ์ที่เก็บข้อมูลอ้างอิงของวัตถุการเรียกที่ใช้โปรโตคอล
ตัวอย่างแสดงด้านล่าง
#import <Foundation/Foundation.h>
@protocol PrintProtocolDelegate
- (void)processCompleted;
@end
@interface PrintClass :NSObject {
id delegate;
}
- (void) printDetails;
- (void) setDelegate:(id)newDelegate;
@end
@implementation PrintClass
- (void)printDetails {
NSLog(@"Printing Details");
[delegate processCompleted];
}
- (void) setDelegate:(id)newDelegate {
delegate = newDelegate;
}
@end
@interface SampleClass:NSObject<PrintProtocolDelegate>
- (void)startAction;
@end
@implementation SampleClass
- (void)startAction {
PrintClass *printClass = [[PrintClass alloc]init];
[printClass setDelegate:self];
[printClass printDetails];
}
-(void)processCompleted {
NSLog(@"Printing Process Completed");
}
@end
int main(int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
SampleClass *sampleClass = [[SampleClass alloc]init];
[sampleClass startAction];
[pool drain];
return 0;
}
ตอนนี้เมื่อเราคอมไพล์และรันโปรแกรมเราจะได้ผลลัพธ์ดังต่อไปนี้
2013-09-22 21:15:50.362 Protocols[275:303] Printing Details
2013-09-22 21:15:50.364 Protocols[275:303] Printing Process Completed
ในตัวอย่างข้างต้นเราได้เห็นวิธีการเรียกและดำเนินการเมธอด delgate เริ่มต้นด้วย startAction เมื่อกระบวนการเสร็จสิ้นกระบวนการเมธอดมอบหมายเสร็จสมบูรณ์ถูกเรียกเพื่อให้การดำเนินการเสร็จสมบูรณ์
ในแอป iOS หรือ Mac ใด ๆ เราจะไม่มีการติดตั้งโปรแกรมโดยไม่มีผู้รับมอบสิทธิ์ ดังนั้นสิ่งสำคัญคือเราต้องเข้าใจการใช้งานของผู้รับมอบสิทธิ์ อ็อบเจ็กต์ผู้รับมอบสิทธิ์ควรใช้ชนิดคุณสมบัติ unsafe_unretained เพื่อหลีกเลี่ยงการรั่วไหลของหน่วยความจำ
การเชื่อมโยงแบบไดนามิกกำลังกำหนดวิธีการเรียกใช้ในรันไทม์แทนที่จะเป็นเวลาคอมไพล์ การเชื่อมโยงแบบไดนามิกยังเรียกอีกอย่างว่าการเชื่อมโยงล่าช้า
ใน Objective-C วิธีการทั้งหมดจะได้รับการแก้ไขแบบไดนามิกที่รันไทม์ รหัสที่ถูกเรียกใช้งานถูกกำหนดโดยทั้งชื่อวิธีการ (ตัวเลือก) และวัตถุที่รับ
การผูกแบบไดนามิกทำให้เกิดความหลากหลาย ตัวอย่างเช่นพิจารณาคอลเล็กชันของวัตถุรวมทั้งสี่เหลี่ยมผืนผ้าและสี่เหลี่ยมจัตุรัส แต่ละอ็อบเจ็กต์มีการนำเมธอด printArea มาใช้
ในส่วนของรหัสต่อไปนี้รหัสจริงที่ควรดำเนินการโดยนิพจน์ [anObject printArea] ถูกกำหนดที่รันไทม์ ระบบรันไทม์ใช้ตัวเลือกสำหรับวิธีการรันเพื่อระบุเมธอดที่เหมาะสมในคลาสใด ๆ ของ anObject ที่กลายเป็น
ให้เราดูรหัสง่ายๆที่จะอธิบายการผูกแบบไดนามิก
#import <Foundation/Foundation.h>
@interface Square:NSObject {
float area;
}
- (void)calculateAreaOfSide:(CGFloat)side;
- (void)printArea;
@end
@implementation Square
- (void)calculateAreaOfSide:(CGFloat)side {
area = side * side;
}
- (void)printArea {
NSLog(@"The area of square is %f",area);
}
@end
@interface Rectangle:NSObject {
float area;
}
- (void)calculateAreaOfLength:(CGFloat)length andBreadth:(CGFloat)breadth;
- (void)printArea;
@end
@implementation Rectangle
- (void)calculateAreaOfLength:(CGFloat)length andBreadth:(CGFloat)breadth {
area = length * breadth;
}
- (void)printArea {
NSLog(@"The area of Rectangle is %f",area);
}
@end
int main() {
Square *square = [[Square alloc]init];
[square calculateAreaOfSide:10.0];
Rectangle *rectangle = [[Rectangle alloc]init];
[rectangle calculateAreaOfLength:10.0 andBreadth:5.0];
NSArray *shapes = [[NSArray alloc]initWithObjects: square, rectangle,nil];
id object1 = [shapes objectAtIndex:0];
[object1 printArea];
id object2 = [shapes objectAtIndex:1];
[object2 printArea];
return 0;
}
ตอนนี้เมื่อเราคอมไพล์และรันโปรแกรมเราจะได้ผลลัพธ์ดังต่อไปนี้
2013-09-28 07:42:29.821 demo[4916] The area of square is 100.000000
2013-09-28 07:42:29.821 demo[4916] The area of Rectangle is 50.000000
ดังที่คุณเห็นในตัวอย่างข้างต้นเมธอด printArea ถูกเลือกแบบไดนามิกในรันไทม์ เป็นตัวอย่างสำหรับการเชื่อมโยงแบบไดนามิกและมีประโยชน์มากในหลาย ๆ สถานการณ์เมื่อจัดการกับวัตถุประเภทเดียวกัน
เราสามารถสร้างคลาสย่อยภายในคลัสเตอร์คลาสที่กำหนดคลาสที่ฝังอ็อบเจ็กต์ไว้ภายในคลาสนั้น คลาสอ็อบเจ็กต์เหล่านี้เป็นอ็อบเจ็กต์แบบผสม
ดังนั้นคุณอาจสงสัยว่าคลัสเตอร์คลาสคืออะไร ก่อนอื่นเราจะดูว่าคลัสเตอร์คลาสคืออะไร
กลุ่มคลาส
คลัสเตอร์คลาสเป็นรูปแบบการออกแบบที่กรอบงานของมูลนิธิใช้ประโยชน์อย่างกว้างขวาง คลัสเตอร์คลาสจัดกลุ่มคลาสย่อยคอนกรีตส่วนตัวจำนวนหนึ่งภายใต้คลาสซูเปอร์นามธรรมสาธารณะ การจัดกลุ่มคลาสด้วยวิธีนี้ช่วยลดความซับซ้อนของสถาปัตยกรรมที่เปิดเผยต่อสาธารณะของเฟรมเวิร์กเชิงวัตถุโดยไม่ลดความสมบูรณ์ของฟังก์ชัน คลัสเตอร์คลาสเป็นไปตามรูปแบบการออกแบบโรงงานนามธรรม
เพื่อให้ง่ายแทนที่จะสร้างหลายคลาสสำหรับฟังก์ชันที่คล้ายกันเราจะสร้างคลาสเดียวที่จะดูแลการจัดการตามค่าของอินพุต
ตัวอย่างเช่นใน NSNumber เรามีกลุ่มคลาสมากมายเช่น char, int, bool และอื่น ๆ เราจัดกลุ่มทั้งหมดเป็นคลาสเดียวที่ดูแลจัดการการดำเนินการที่คล้ายกันในคลาสเดียว NSNumber รวมมูลค่าของชนิดดั้งเดิมเหล่านี้ไว้ในวัตถุ
แล้ววัตถุประกอบคืออะไร?
โดยการฝังวัตถุคลัสเตอร์ส่วนตัวในวัตถุที่เราออกแบบเองเราจะสร้างวัตถุผสม อ็อบเจ็กต์คอมโพสิตนี้สามารถพึ่งพาอ็อบเจ็กต์คลัสเตอร์สำหรับการทำงานพื้นฐานโดยสกัดกั้นเฉพาะข้อความที่อ็อบเจ็กต์คอมโพสิตต้องการจัดการในลักษณะเฉพาะ สถาปัตยกรรมนี้ช่วยลดจำนวนโค้ดที่เราต้องเขียนและช่วยให้คุณใช้ประโยชน์จากโค้ดที่ทดสอบโดย Foundation Framework ได้
นี่คือคำอธิบายในรูปต่อไปนี้
ออบเจ็กต์คอมโพสิตต้องประกาศตัวเองว่าเป็นคลาสย่อยของคลาสนามธรรมของคลัสเตอร์ ในฐานะคลาสย่อยต้องลบล้างเมธอดดั้งเดิมของซูเปอร์คลาส นอกจากนี้ยังสามารถแทนที่วิธีการที่ได้รับ แต่ไม่จำเป็นเนื่องจากวิธีการที่ได้รับนั้นทำงานผ่านวิธีดั้งเดิม
วิธีการนับของคลาส NSArray เป็นตัวอย่าง การดำเนินการของวัตถุแทรกแซงวิธีการที่มันลบล้างทำได้ง่ายเพียง -
- (unsigned)count {
return [embeddedObject count];
}
ในตัวอย่างข้างต้นวัตถุฝังตัวเป็นประเภท NSArray
ตัวอย่าง Composite Object
ตอนนี้เพื่อดูตัวอย่างที่สมบูรณ์ลองดูตัวอย่างจากเอกสารของ Apple ที่ให้ไว้ด้านล่าง
#import <Foundation/Foundation.h>
@interface ValidatingArray : NSMutableArray {
NSMutableArray *embeddedArray;
}
+ validatingArray;
- init;
- (unsigned)count;
- objectAtIndex:(unsigned)index;
- (void)addObject:object;
- (void)replaceObjectAtIndex:(unsigned)index withObject:object;
- (void)removeLastObject;
- (void)insertObject:object atIndex:(unsigned)index;
- (void)removeObjectAtIndex:(unsigned)index;
@end
@implementation ValidatingArray
- init {
self = [super init];
if (self) {
embeddedArray = [[NSMutableArray allocWithZone:[self zone]] init];
}
return self;
}
+ validatingArray {
return [[self alloc] init] ;
}
- (unsigned)count {
return [embeddedArray count];
}
- objectAtIndex:(unsigned)index {
return [embeddedArray objectAtIndex:index];
}
- (void)addObject:(id)object {
if (object != nil) {
[embeddedArray addObject:object];
}
}
- (void)replaceObjectAtIndex:(unsigned)index withObject:(id)object; {
if (index <[embeddedArray count] && object != nil) {
[embeddedArray replaceObjectAtIndex:index withObject:object];
}
}
- (void)removeLastObject; {
if ([embeddedArray count] > 0) {
[embeddedArray removeLastObject];
}
}
- (void)insertObject:(id)object atIndex:(unsigned)index; {
if (object != nil) {
[embeddedArray insertObject:object atIndex:index];
}
}
- (void)removeObjectAtIndex:(unsigned)index; {
if (index <[embeddedArray count]) {
[embeddedArray removeObjectAtIndex:index];
}
}
@end
int main() {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
ValidatingArray *validatingArray = [ValidatingArray validatingArray];
[validatingArray addObject:@"Object1"];
[validatingArray addObject:@"Object2"];
[validatingArray addObject:[NSNull null]];
[validatingArray removeObjectAtIndex:2];
NSString *aString = [validatingArray objectAtIndex:1];
NSLog(@"The value at Index 1 is %@",aString);
[pool drain];
return 0;
}
ตอนนี้เมื่อเราคอมไพล์และรันโปรแกรมเราจะได้ผลลัพธ์ดังต่อไปนี้
2013-09-28 22:03:54.294 demo[6247] The value at Index 1 is Object2
ในตัวอย่างข้างต้นเราจะเห็นว่าการตรวจสอบความถูกต้องของฟังก์ชันหนึ่งของอาร์เรย์ไม่อนุญาตให้เพิ่มวัตถุว่างที่จะนำไปสู่ความผิดพลาดในสถานการณ์ปกติ แต่อาร์เรย์ที่ตรวจสอบความถูกต้องของเราจะดูแลมัน ในทำนองเดียวกันแต่ละวิธีในการตรวจสอบความถูกต้องอาร์เรย์จะเพิ่มกระบวนการตรวจสอบความถูกต้องนอกเหนือจากลำดับการดำเนินการตามปกติ
หากคุณอ้างอิงเอกสารของ Apple คุณสามารถดูรายละเอียดของ Foundation framework ได้ตามที่ระบุด้านล่าง
กรอบของมูลนิธิกำหนดชั้นพื้นฐานของคลาส Objective-C นอกเหนือจากการจัดเตรียมชุดของคลาสอ็อบเจ็กต์ดั้งเดิมที่มีประโยชน์แล้วยังแนะนำกระบวนทัศน์ต่างๆที่กำหนดการทำงานที่ไม่ครอบคลุมโดยภาษา Objective-C กรอบของมูลนิธิได้รับการออกแบบโดยคำนึงถึงเป้าหมายเหล่านี้ -
จัดเตรียมคลาสยูทิลิตี้พื้นฐานชุดเล็ก ๆ
ทำให้การพัฒนาซอฟต์แวร์ง่ายขึ้นโดยนำเสนอข้อตกลงที่สอดคล้องกันสำหรับสิ่งต่างๆเช่นการจัดสรรตำแหน่ง
สนับสนุนสตริง Unicode การคงอยู่ของวัตถุและการกระจายวัตถุ
จัดระดับความเป็นอิสระของระบบปฏิบัติการเพื่อเพิ่มความสะดวกในการพกพา
เฟรมเวิร์กได้รับการพัฒนาโดย NeXTStep ซึ่ง Apple ได้มาและคลาสพื้นฐานเหล่านี้กลายเป็นส่วนหนึ่งของ MacOS X และ iOS
เนื่องจากได้รับการพัฒนาโดย NeXTStep จึงมีคำนำหน้าคลาสเป็น "NS"
เราใช้ Foundation Framework ในโปรแกรมตัวอย่างทั้งหมดของเราแล้ว แทบจะต้องใช้ Foundation Framework
โดยทั่วไปเราใช้สิ่งที่ต้องการ #import <Foundation/NSString.h> เพื่อนำเข้าคลาส Objective-C แต่เพื่อหลีกเลี่ยงการนำเข้าคลาสมากเกินไปจึงนำเข้าทั้งหมดใน #import <Foundation/Foundation.h>.
NSObject เป็นคลาสพื้นฐานของอ็อบเจ็กต์ทั้งหมดรวมถึงคลาสชุดพื้นฐาน มีวิธีการจัดการหน่วยความจำ นอกจากนี้ยังมีอินเทอร์เฟซพื้นฐานสำหรับระบบรันไทม์และความสามารถในการทำงานเป็นอ็อบเจ็กต์ Objective-C ไม่มีคลาสพื้นฐานใด ๆ และเป็นรูทสำหรับคลาสทั้งหมด
ชั้นเรียนพื้นฐานตามฟังก์ชันการทำงาน
ซีเนียร์ | ประเภทห่วงและคำอธิบาย |
---|---|
1 | การจัดเก็บข้อมูล NSArray, NSDictionary และ NSSet จัดเตรียมพื้นที่เก็บข้อมูลสำหรับ Objective-C ของคลาสใด ๆ |
2 | ข้อความและสตริง NSCharacterSet แสดงถึงการจัดกลุ่มอักขระต่างๆที่ใช้โดยคลาส NSString และ NSScanner คลาส NSString แสดงถึงสตริงข้อความและจัดเตรียมเมธอดในการค้นหารวมและเปรียบเทียบสตริง วัตถุ NSScanner ใช้เพื่อสแกนตัวเลขและคำจากวัตถุ NSString |
3 | วันที่และเวลา คลาส NSDate, NSTimeZone และ NSCalendar จะจัดเก็บเวลาและวันที่และแสดงข้อมูลตามปฏิทิน พวกเขาเสนอวิธีการคำนวณความแตกต่างของวันที่และเวลา ร่วมกับ NSLocale พวกเขามีวิธีการแสดงวันที่และเวลาในหลายรูปแบบและสำหรับการปรับเวลาและวันที่ตามสถานที่ในโลก |
4 | การจัดการข้อยกเว้น การจัดการข้อยกเว้นใช้เพื่อจัดการกับสถานการณ์ที่ไม่คาดคิดและมีให้ใน Objective-C พร้อม NSException |
5 | การจัดการไฟล์ การจัดการไฟล์ทำได้ด้วยความช่วยเหลือของคลาส NSFileManager |
6 | ระบบโหลด URL ชุดของคลาสและโปรโตคอลที่ให้การเข้าถึงอินเทอร์เน็ตโปรโตคอลทั่วไป |
การแจงนับอย่างรวดเร็วเป็นคุณลักษณะของ Objective-C ที่ช่วยในการแจกแจงผ่านคอลเลกชัน ดังนั้นเพื่อให้ทราบเกี่ยวกับการแจงนับอย่างรวดเร็วเราจำเป็นต้องรู้เกี่ยวกับการรวบรวมก่อนซึ่งจะอธิบายในส่วนต่อไปนี้
คอลเลกชันใน Objective-C
คอลเล็กชันเป็นโครงสร้างพื้นฐาน ใช้เพื่อยึดและจัดการวัตถุอื่น ๆ จุดประสงค์ทั้งหมดของคอลเลกชันคือเป็นวิธีการทั่วไปในการจัดเก็บและเรียกค้นวัตถุอย่างมีประสิทธิภาพ
คอลเลกชันมีหลายประเภท แม้ว่าพวกเขาทั้งหมดจะบรรลุวัตถุประสงค์เดียวกันในการสามารถถือวัตถุอื่น ๆ ได้ แต่ก็แตกต่างกันในวิธีการดึงวัตถุเป็นส่วนใหญ่ คอลเลกชันทั่วไปที่ใช้ใน Objective-C ได้แก่ -
- NSSet
- NSArray
- NSDictionary
- NSMutableSet
- NSMutableArray
- NSMutableDictionary
หากคุณต้องการทราบข้อมูลเพิ่มเติมเกี่ยวกับโครงสร้างเหล่านี้โปรดดูการจัดเก็บข้อมูลในมูลนิธิกรอบ
ไวยากรณ์การแจงนับอย่างรวดเร็ว
for (classType variable in collectionObject ) {
statements
}
นี่คือตัวอย่างสำหรับการแจงนับอย่างรวดเร็ว
#import <Foundation/Foundation.h>
int main() {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSArray *array = [[NSArray alloc]
initWithObjects:@"string1", @"string2",@"string3",nil];
for(NSString *aString in array) {
NSLog(@"Value: %@",aString);
}
[pool drain];
return 0;
}
ตอนนี้เมื่อเราคอมไพล์และรันโปรแกรมเราจะได้ผลลัพธ์ดังต่อไปนี้
2013-09-28 06:26:22.835 demo[7426] Value: string1
2013-09-28 06:26:22.836 demo[7426] Value: string2
2013-09-28 06:26:22.836 demo[7426] Value: string3
ดังที่คุณเห็นในผลลัพธ์แต่ละวัตถุในอาร์เรย์จะถูกพิมพ์ตามลำดับ
การแจงนับอย่างรวดเร็วย้อนกลับ
for (classType variable in [collectionObject reverseObjectEnumerator] ) {
statements
}
นี่คือตัวอย่างของ reverseObjectEnumerator ในการแจงนับอย่างรวดเร็ว
#import <Foundation/Foundation.h>
int main() {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSArray *array = [[NSArray alloc]
initWithObjects:@"string1", @"string2",@"string3",nil];
for(NSString *aString in [array reverseObjectEnumerator]) {
NSLog(@"Value: %@",aString);
}
[pool drain];
return 0;
}
ตอนนี้เมื่อเราคอมไพล์และรันโปรแกรมเราจะได้ผลลัพธ์ดังต่อไปนี้
2013-09-28 06:27:51.025 demo[12742] Value: string3
2013-09-28 06:27:51.025 demo[12742] Value: string2
2013-09-28 06:27:51.025 demo[12742] Value: string1
ดังที่คุณเห็นในผลลัพธ์แต่ละวัตถุในอาร์เรย์จะถูกพิมพ์ แต่ในลำดับย้อนกลับเมื่อเทียบกับการแจงนับเร็วปกติ
การจัดการหน่วยความจำเป็นกระบวนการที่สำคัญที่สุดกระบวนการหนึ่งในภาษาโปรแกรมใด ๆ เป็นกระบวนการที่หน่วยความจำของอ็อบเจ็กต์ถูกจัดสรรเมื่อจำเป็นและยกเลิกการจัดสรรเมื่อไม่ต้องการอีกต่อไป
การจัดการหน่วยความจำวัตถุเป็นเรื่องของประสิทธิภาพ หากแอปพลิเคชันไม่ปล่อยวัตถุที่ไม่จำเป็นออกไปรอยเท้าของหน่วยความจำจะเพิ่มขึ้นและประสิทธิภาพจะลดลง
เทคนิคการจัดการหน่วยความจำ Objective-C สามารถแบ่งออกเป็นสองประเภทอย่างกว้าง ๆ
- "Manual Retain-Release" หรือ MRR
- "การนับอ้างอิงอัตโนมัติ" หรือ ARC
"Manual Retain-Release" หรือ MRR
ใน MRR เราจัดการหน่วยความจำอย่างชัดเจนโดยการติดตามวัตถุด้วยตัวเราเอง สิ่งนี้ถูกนำไปใช้โดยใช้โมเดลที่เรียกว่าการนับอ้างอิงที่ NSObject คลาส Foundation จัดเตรียมร่วมกับสภาวะแวดล้อมรันไทม์
ข้อแตกต่างเพียงอย่างเดียวระหว่าง MRR และ ARC ก็คือเราจะจัดการการกักเก็บและการปลดปล่อยด้วยตนเองในขณะที่มันได้รับการดูแลโดยอัตโนมัติในภายหลัง
รูปต่อไปนี้แสดงถึงตัวอย่างของการจัดการหน่วยความจำใน Objective-C
วงจรชีวิตหน่วยความจำของวัตถุคลาส A แสดงในรูปด้านบน อย่างที่คุณเห็นจำนวนการเก็บรักษาจะแสดงอยู่ด้านล่างของวัตถุเมื่อจำนวนการคงที่ของวัตถุกลายเป็น 0 วัตถุจะถูกปลดปล่อยอย่างสมบูรณ์และหน่วยความจำจะถูกจัดสรรเพื่อให้วัตถุอื่นใช้
คลาส A อ็อบเจ็กต์ถูกสร้างขึ้นครั้งแรกโดยใช้วิธีการจัดสรร / init ที่มีอยู่ใน NSObject ตอนนี้จำนวนการรักษาจะกลายเป็น 1
ตอนนี้คลาส B ยังคงรักษาวัตถุของคลาส A ไว้และจำนวนที่คงไว้ของวัตถุคลาส A จะกลายเป็น 2
จากนั้นคลาส C จะสร้างสำเนาของวัตถุ ตอนนี้มันถูกสร้างขึ้นเป็นอินสแตนซ์อื่นของคลาส A ที่มีค่าเดียวกันสำหรับตัวแปรอินสแตนซ์ ที่นี่จำนวนการคงไว้คือ 1 และไม่ใช่จำนวนการคงไว้ของวัตถุดั้งเดิม นี่แสดงด้วยเส้นประในรูป
วัตถุที่คัดลอกจะถูกปลดปล่อยโดยคลาส C โดยใช้วิธีการปล่อยและจำนวนการคงไว้จะกลายเป็น 0 และด้วยเหตุนี้วัตถุจึงถูกทำลาย
ในกรณีของคลาส A ออบเจ็กต์เริ่มต้นจำนวนการคงไว้คือ 2 และจะต้องปล่อยออกมาสองครั้งจึงจะถูกทำลายได้ สิ่งนี้ทำได้โดยคำแถลงการเปิดตัวของคลาส A และคลาส B ซึ่งลดจำนวนการคงไว้เป็น 1 และ 0 ตามลำดับ สุดท้ายวัตถุนั้นถูกทำลาย
กฎพื้นฐาน MRR
เราเป็นเจ้าของวัตถุที่เราสร้างขึ้น: เราสร้างวัตถุโดยใช้วิธีการที่ชื่อขึ้นต้นด้วย "จัดสรร" "ใหม่" "สำเนา" หรือ "mutableCopy"
เราสามารถเป็นเจ้าของออบเจ็กต์ได้โดยใช้การเก็บรักษา: โดยปกติแล้วอ็อบเจ็กต์ที่ได้รับจะถูกรับประกันว่าจะยังคงถูกต้องภายในเมธอดที่ได้รับและเมธอดนั้นอาจส่งคืนอ็อบเจ็กต์ไปยังผู้เรียกใช้ เราใช้การเก็บรักษาในสองสถานการณ์ -
ในการใช้วิธีการเข้าถึงหรือวิธีการเริ่มต้นในการเป็นเจ้าของวัตถุที่เราต้องการจัดเก็บเป็นค่าคุณสมบัติ
เพื่อป้องกันไม่ให้วัตถุไม่ถูกต้องเนื่องจากเป็นผลข้างเคียงของการดำเนินการอื่น ๆ
เมื่อเราไม่ต้องการอีกต่อไปเราต้องสละความเป็นเจ้าของวัตถุที่เราเป็นเจ้าของ: เราสละสิทธิ์การเป็นเจ้าของวัตถุโดยการส่งข้อความเผยแพร่หรือข้อความปลดอัตโนมัติ ในคำศัพท์ Cocoa การสละความเป็นเจ้าของวัตถุจึงมักเรียกว่า "การปล่อย" วัตถุ
คุณต้องไม่ละทิ้งการเป็นเจ้าของวัตถุที่คุณไม่ได้เป็นเจ้าของ: นี่เป็นเพียงข้อพิสูจน์ของกฎนโยบายก่อนหน้านี้ที่ระบุไว้อย่างชัดเจน
#import <Foundation/Foundation.h>
@interface SampleClass:NSObject
- (void)sampleMethod;
@end
@implementation SampleClass
- (void)sampleMethod {
NSLog(@"Hello, World! \n");
}
- (void)dealloc {
NSLog(@"Object deallocated");
[super dealloc];
}
@end
int main() {
/* my first program in Objective-C */
SampleClass *sampleClass = [[SampleClass alloc]init];
[sampleClass sampleMethod];
NSLog(@"Retain Count after initial allocation: %d",
[sampleClass retainCount]);
[sampleClass retain];
NSLog(@"Retain Count after retain: %d", [sampleClass retainCount]);
[sampleClass release];
NSLog(@"Retain Count after release: %d", [sampleClass retainCount]);
[sampleClass release];
NSLog(@"SampleClass dealloc will be called before this");
// Should set the object to nil
sampleClass = nil;
return 0;
}
เมื่อเรารวบรวมโปรแกรมข้างต้นเราจะได้ผลลัพธ์ดังต่อไปนี้
2013-09-28 04:39:52.310 demo[8385] Hello, World!
2013-09-28 04:39:52.311 demo[8385] Retain Count after initial allocation: 1
2013-09-28 04:39:52.311 demo[8385] Retain Count after retain: 2
2013-09-28 04:39:52.311 demo[8385] Retain Count after release: 1
2013-09-28 04:39:52.311 demo[8385] Object deallocated
2013-09-28 04:39:52.311 demo[8385] SampleClass dealloc will be called before this
"การนับอ้างอิงอัตโนมัติ" หรือ ARC
ใน Automatic Reference Counting หรือ ARC ระบบจะใช้ระบบการนับอ้างอิงแบบเดียวกับ MRR แต่จะแทรกวิธีการจัดการหน่วยความจำที่เหมาะสมที่เรียกร้องให้เราในเวลาคอมไพล์ เราได้รับการสนับสนุนอย่างยิ่งให้ใช้ ARC สำหรับโครงการใหม่ หากเราใช้ ARC โดยทั่วไปไม่จำเป็นต้องเข้าใจการใช้งานพื้นฐานที่อธิบายไว้ในเอกสารนี้แม้ว่าจะมีประโยชน์ในบางสถานการณ์ก็ตาม สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ ARC โปรดดูการเปลี่ยนไปใช้ ARC Release Notes
ดังที่ได้กล่าวมาแล้วใน ARC เราไม่จำเป็นต้องเพิ่มวิธีการรีลีสและคงไว้เนื่องจากคอมไพเลอร์จะดูแล จริงๆแล้วกระบวนการพื้นฐานของ Objective-C ยังคงเหมือนเดิม ใช้การดำเนินการเก็บรักษาและรีลีสภายในทำให้นักพัฒนาสามารถเขียนโค้ดได้ง่ายขึ้นโดยไม่ต้องกังวลเกี่ยวกับการดำเนินการเหล่านี้ซึ่งจะช่วยลดทั้งจำนวนโค้ดที่เขียนและความเป็นไปได้ที่หน่วยความจำจะรั่วไหล
มีหลักการอื่นที่เรียกว่าการเก็บขยะซึ่งใช้ใน Mac OS-X พร้อมกับ MRR แต่เนื่องจากการเลิกใช้งานใน OS-X Mountain Lion จึงไม่ได้รับการกล่าวถึงพร้อมกับ MRR นอกจากนี้วัตถุ iOS ไม่เคยมีคุณสมบัติการเก็บขยะ และด้วย ARC ไม่มีการใช้การเก็บขยะใน OS-X ด้วย
นี่คือตัวอย่าง ARC ง่ายๆ โปรดทราบว่าสิ่งนี้จะใช้ไม่ได้กับคอมไพเลอร์ออนไลน์เนื่องจากไม่รองรับ ARC
#import <Foundation/Foundation.h>
@interface SampleClass:NSObject
- (void)sampleMethod;
@end
@implementation SampleClass
- (void)sampleMethod {
NSLog(@"Hello, World! \n");
}
- (void)dealloc {
NSLog(@"Object deallocated");
}
@end
int main() {
/* my first program in Objective-C */
@autoreleasepool {
SampleClass *sampleClass = [[SampleClass alloc]init];
[sampleClass sampleMethod];
sampleClass = nil;
}
return 0;
}
เมื่อเรารวบรวมโปรแกรมข้างต้นเราจะได้ผลลัพธ์ดังต่อไปนี้
2013-09-28 04:45:47.310 demo[8385] Hello, World!
2013-09-28 04:45:47.311 demo[8385] Object deallocated