คู่มือฉบับย่อ 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