Objective-C: แก่นแท้ของภาษาและตำแหน่งในการพัฒนา iOS

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-02-09 เวลาอ่าน: 8 นาที

Objective-C เป็นภาษาโปรแกรมที่มีการจัดส่งข้อความแบบไดนามิก สร้างโดย Brad Cox ในช่วงทศวรรษ 1980 Apple เลือก Objective-C เป็นภาษาหลักสำหรับ NeXTSTEP และต่อมาสำหรับ iOS SDK Programming With Objective-C — บทนำเกี่ยวกับไวยากรณ์ข้อความและการจัดการหน่วยความจำ

ประเด็นสำคัญ

  • Objective-C — ซูเปอร์เซ็ตที่เข้มงวดของ C พร้อมไวยากรณ์ข้อความในวงเล็บเหลี่ยมและรันไทม์แบบไดนามิก
  • Message passing — การเรียกเมธอดผ่าน [object selector:argument] พร้อมการค้นหาการนำไปใช้แบบไดนามิกผ่าน objc_msgSend
  • Categories — กลไกการเพิ่มเมธอดให้กับคลาสที่มีอยู่โดยไม่ต้องสืบทอดและไม่ต้องเข้าถึงซอร์สโค้ด
  • Blocks — ฟังก์ชันนิรนามพร้อม Closure ซึ่งเป็นต้นแบบของ Swift closures
  • ARC vs MRC — การนับ reference โดยอัตโนมัติและด้วยตนเองเพื่อจัดการหน่วยความจำ

Objective-C คืออะไร

Objective-C เป็นภาษาโปรแกรมที่ขยาย C ด้วยความสามารถของการเขียนโปรแกรมเชิงวัตถุในสไตล์ Smalltalk โค้ด Objective-C ถูกคอมไพล์ผ่าน LLVM หรือ GCC เป็นโค้ดเครื่องดั้งเดิม โดยคงความเข้ากันได้ย้อนหลังอย่างสมบูรณ์กับ C — โค้ด C ใดๆ ก็ใช้ได้ใน Objective-C

Apple ซื้อ NeXT (พร้อมกับ Objective-C) ในปี 1997 ภาษาได้กลายเป็นรากฐานของ Cocoa และ Cocoa Touch — เฟรมเวิร์กสำหรับ macOS และ iOS ตั้งแต่ปี 2014 Apple ได้ส่งเสริม Swift ให้เป็นภาษาทดแทน แต่ Objective-C ยังคงมีความสำคัญอย่างยิ่งสำหรับโปรเจกต์เดิมและเฟรมเวิร์กระบบบางส่วน ตามข้อมูลของ Apple (WWDC 2024) ประมาณ 35% ของแอปใน App Store ยังคงมีโค้ด Objective-C

คุณสมบัติหลักคือ รันไทม์แบบไดนามิก แตกต่างจาก Swift ที่การเรียกเมธอดถูกแก้ไขในเวลาคอมไพล์ Objective-C ส่งข้อความในเวลารันไทม์ผ่านฟังก์ชัน objc_msgSend ซึ่งช่วยให้สามารถแทนที่เมธอดได้ทันที (method swizzling) เพิ่มคลาสแบบไดนามิก และใช้ forward invocation สำหรับ selector ที่ไม่มีอยู่

ไวยากรณ์: C + ส่วนขยายเชิงวัตถุ

โค้ด C ใดๆ ก็ใช้ได้ใน Objective-C ส่วนขยายเชิงวัตถุเพิ่มคลาส (@interface/@implementation) หมวดหมู่ โปรโตคอล (@protocol) และการกำหนดชนิดแบบไดนามิก (id) ไฟล์มีนามสกุล .m (การนำไปใช้) และ .h (ส่วนหัว)

ไวยากรณ์ข้อความและการจัดส่งแบบไดนามิก

ไวยากรณ์ข้อความ คือความแตกต่างหลักระหว่าง Objective-C และภาษาแบบ C แทนที่จะใช้ object.method(argument) จะใช้ [object method:argument] ข้อความแต่ละข้อความผ่าน objc_msgSend ซึ่งค้นหาการนำไปใช้ของเมธอดในรันไทม์แบบไดนามิก

objective-c
// ไวยากรณ์ข้อความพร้อมพารามิเตอร์ที่มีชื่อ
NSString *greeting = [NSString stringWithFormat:@"Hello, %@", name];

// ข้อความซ้อน
NSArray *sortedArray = [[array sortedArrayUsingSelector:@selector(compare:)] copy];

// การตรวจสอบชนิดผ่าน introspection
if ([object isKindOfClass:[UIView class]]) {
    UIView *view = (UIView *)object;
    view.backgroundColor = [UIColor redColor];
}

การจัดส่งแบบไดนามิก ช่วยให้สามารถแทนที่เมธอดในรันไทม์ (method swizzling) — เทคนิคที่ทรงพลังแต่เสี่ยง ตัวอย่างเช่น เฟรมเวิร์กอย่าง AFNetworking และ Aspects ใช้ swizzling เพื่อสกัดกั้นการเรียก URLSession Apple เตือน: swizzling อาจทำให้เฟรมเวิร์กระบบเสียหายหากใช้ไม่ถูกต้อง

หมวดหมู่และส่วนขยายคลาส

หมวดหมู่ คือคุณสมบัติพิเศษของ Objective-C ที่ช่วยให้เพิ่มเมธอดให้กับคลาสที่มีอยู่ (รวมถึงคลาสระบบอย่าง NSString และ UIView) โดยไม่ต้องสืบทอดและไม่ต้องเข้าถึงซอร์สโค้ด หมวดหมู่ประกาศผ่าน @interface ClassName (CategoryName)

objective-c
// ไฟล์ UIColor+Hex.h — หมวดหมู่สำหรับ UIColor
@interface UIColor (Hex)
+ (instancetype)colorWithHex:NSUIntegerhex;
@end

// ไฟล์ UIColor+Hex.m — การนำไปใช้
@implementation UIColor (Hex)
+ (instancetype)colorWithHex:NSUIntegerhex {
    CGFloat r = ((hex >> 16) & 0xFF) / 255.0;
    CGFloat g = ((hex >> 8) & 0xFF) / 255.0;
    CGFloat b = (hex & 0xFF) / 255.0;
    return [self colorWithRed:r green:g blue:b alpha:1.0];
}
@end

ส่วนขยาย (Class Extension) เป็นหมวดหมู่ชนิดพิเศษที่ประกาศในไฟล์ .m โดยไม่มีชื่อ: @interface ClassName () แตกต่างจากหมวดหมู่ ส่วนขยายสามารถเพิ่มไม่เพียงเมธอด แต่ยังรวมถึง ivar (ตัวแปรอินสแตนซ์) และคุณสมบัติ ส่วนขยายใช้เพื่อซ่อน API ภายในจากโมดูลภายนอก

บล็อก (Blocks) — ฟังก์ชันนิรนามพร้อม Closure

บล็อก คือฟังก์ชันนิรนามใน Objective-C ที่จับตัวแปรจากขอบเขตภายนอก ไวยากรณ์บล็อก: ^(int x) { return x * 2; } บล็อกใช้ใน UIKit สำหรับตัวจัดการ callback ใน Grand Central Dispatch สำหรับงานแบบอะซิงโครนัส และในคอลเลกชัน NSArray/NSDictionary สำหรับการดำเนินการเชิงฟังก์ชัน

objective-c
// การประกาศชนิดบล็อก
typedef void (^CompletionBlock)(BOOL success, NSError *error);

// บล็อกเป็นพารามิเตอร์
- (void)fetchDataWithCompletion:(CompletionBlock)completion {
    __weak typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        BOOL result = [weakSelf processData];
        if (completion) {
            completion(result, nil);
        }
    });
}

การจัดการหน่วยความจำ ในบล็อกมีความสำคัญอย่างยิ่ง บล็อกจับ self ด้วย reference ที่แข็งแกร่ง ทำให้เกิด retain cycle เมื่อใช้โดยตรง วิธีแก้คือ __weak typeof(self) weakSelf = self ตามด้วยการตรวจสอบภายในบล็อก ปัญหานี้แก้ไขได้อย่างสมบูรณ์ใน Swift ผ่าน capture lists [weak self]

ARC และ MRC: การจัดการหน่วยความจำ

Objective-C พัฒนาจาก MRC (Manual Reference Counting) ไปเป็น ARC (Automatic Reference Counting) ใน MRC นักพัฒนาเรียกด้วยตนเอง retain (เพิ่มตัวนับ) release (ลด) และ autorelease (ปล่อยแบบรอเลื่อน) ข้อผิดพลาดในการเรียกเหล่านี้นำไปสู่การรั่วไหลของหน่วยความจำหรือการค้างเนื่องจากพอยน์เตอร์ที่angling

การดำเนินการMRCARC
การสร้างออบเจ็กต์[[Object alloc] init][[Object alloc] init]
การถือ reference[object retain]อัตโนมัติ
การปล่อย[object release]อัตโนมัติ
การปล่อยอัตโนมัติ[object autorelease]อัตโนมัติ (ไม่จำเป็น)
Reference แบบอ่อน__weak ไม่มี__weak (nil อัตโนมัติ)

ARC ถูกนำมาใช้ใน Xcode 4.2 และ LLVM 3.0 (2011) คอมไพเลอร์แทรก retain/release โดยอัตโนมัติในเวลาคอมไพล์โดยวิเคราะห์อายุของออบเจ็กต์ ARC ไม่ใช่ garbage collection — เป็นการวิเคราะห์แบบสถิตพร้อมการแทรกอัตโนมัติ ARC ของ Objective-C เข้ากันได้กับ ARC ของ Swift: ทั้งสองใช้ระบบนับ reference เดียวกันในระดับรันไทม์

การทำงานร่วมกับ Swift ผ่าน Bridging Header

การใช้ Objective-C และ Swift ร่วมกันในโปรเจกต์เดียวเป็นแนวปฏิบัติทั่วไปสำหรับโปรเจกต์เดิม Apple จัดเตรียม Bridging Header — ไฟล์ที่สร้างโดยอัตโนมัติซึ่ง Swift มองเห็นคลาส Objective-C และ Objective-C มองเห็นคลาส Swift ที่สืบทอดจาก NSObject

objective-c
// ProjectName-Bridging-Header.h
// Swift เห็นส่วนหัวเหล่านี้โดยอัตโนมัติ
#import "LegacyManager.h"
#import "NetworkClient.h"
#import "DataStore.h"

การย้ายจาก Objective-C ไปยัง Swift เป็นกระบวนการแบบค่อยเป็นค่อยไป ไฟล์ใหม่เขียนด้วย Swift ไฟล์เก่าถูกปรับโครงสร้างทีละน้อย Bridging Header ถูกสร้างโดยอัตโนมัติเมื่อเพิ่มไฟล์ Swift แรกในโปรเจกต์ Objective-C สำหรับการมองเห็นย้อนกลับ (ObjC → Swift) Xcode สร้างไฟล์ <ProjectName>-Swift.h ที่มีประกาศ @interface สำหรับคลาส Swift ที่ทำเครื่องหมายด้วย @objc

swift
// คลาส Swift ที่มองเห็นได้จาก Objective-C
@objc class SwiftRouter: NSObject {
    @objc func navigateToProfile(userId: Int) {
        // การนำไปใช้
    }
}

ข้อจำกัด: ชนิดค่า (value type) ของ Swift (struct, enum) ไม่สามารถมองเห็นได้โดยตรงจาก Objective-C — ต้องห่อในคลาสที่มี @objc Generics ของ Swift สามารถเข้าถึงได้อย่างจำกัดจาก Objective-C แนวทางที่แนะนำคือเขียนโค้ดใหม่ใน Swift และปรับโครงสร้างโค้ด Objective-C ที่มีอยู่เมื่อเปลี่ยนฟังก์ชันการทำงานที่เกี่ยวข้องเท่านั้น

รันไทม์และ Method Swizzling ใน Objective-C

ข้อได้เปรียบหลักของ Objective-C เหนือ Swift คือ การเข้าถึงรันไทม์อย่างเต็มที่ Method swizzling การแทนที่การนำไปใช้ของเมธอดในรันไทม์ ช่วยให้แทนที่เมธอดของระบบโดยไม่ต้องสืบทอด ไลบรารีอย่าง Aspects และ JRSwizzle ใช้ความสามารถนี้สำหรับ AOP (การเขียนโปรแกรมเชิงด้าน) — การตรวจสอบ การวิเคราะห์ และการบันทึก

Forward invocation เป็นคุณสมบัติรันไทม์อีกอย่าง: หากออบเจ็กต์ไม่ตอบสนองต่อ selector ระบบจะเรียก forwardInvocation: ซึ่งช่วยให้ส่งต่อข้อความไปยังออบเจ็กต์อื่น นี่คือพื้นฐานของรูปแบบ Proxy ใน Objective-C (NSProxy) ซึ่งใช้สำหรับการเริ่มต้นแบบขี้เกียจและออบเจ็กต์แบบกระจาย

Apple แนะนำให้ลดการใช้เทคนิครันไทม์ในโค้ดใหม่ โดยเลือกใช้การกำหนดชนิดแบบสถิตของ Swift อย่างไรก็ตาม ในโปรเจกต์เดิม ความรู้เกี่ยวกับ objc_msgSend, method_exchangeImplementations และ objc_getAssociatedObject เป็นสิ่งจำเป็นสำหรับการบำรุงรักษาฐานโค้ดที่มีอยู่

คุณสมบัติและ Key-Value Observing

Objective-C รองรับ คุณสมบัติ ในรูปแบบน้ำตาลเชิงไวยากรณ์เหนือ ivar พร้อม getter/setter ตัวปรับแต่ง atomic/nonatomic, strong/weak/copy, readonly/readwrite และ assign/retain กำหนดพฤติกรรมหน่วยความจำและความปลอดภัยของเธรด Key-Value Observing (KVO) เป็นกลไกการสังเกตการเปลี่ยนแปลงคุณสมบัติที่สร้างในรันไทม์: ออบเจ็กต์ใดๆ สามารถสมัครรับการเปลี่ยนแปลงคุณสมบัติของออบเจ็กต์อื่นผ่าน addObserver

คำถามที่พบบ่อย

ไวยากรณ์ข้อความใน Objective-C คืออะไร

การเรียกเมธอดมีลักษณะเป็น [object selector:argument] ข้อความผ่าน objc_msgSend ซึ่งค้นหาการนำไปใช้ในรันไทม์แบบไดนามิก Selector คือชื่อเมธอด (@selector(methodName)) ไม่ใช่พอยน์เตอร์ฟังก์ชัน ซึ่งช่วยให้ swizzling และ forward invocation

หมวดหมู่ (Categories) แตกต่างจากส่วนขยาย (Extensions) อย่างไร

หมวดหมู่ (@interface ClassName (Name)) เพิ่มเมธอดให้กับคลาสใดๆ (รวมถึงคลาสระบบ) โดยไม่ต้องสืบทอด ส่วนขยาย (@interface ClassName ()) ประกาศในไฟล์ .m และสามารถเพิ่มคุณสมบัติและ ivars หมวดหมู่ไม่สามารถเพิ่ม ivars ได้ แต่ส่วนขยายสามารถเพิ่มได้

บล็อก (Blocks) ใน Objective-C คืออะไร

บล็อกคือฟังก์ชันนิรนามที่มีไวยากรณ์ ^(พารามิเตอร์) { เนื้อหา } จับตัวแปรจากบริบท คล้ายกับ lambda ใน C++ และ closure ใน Swift ต้องใช้ __weak เพื่อป้องกัน retain cycles เมื่อจับ self ใช้ใน UIKit, GCD และ Foundation

ความแตกต่างระหว่าง ARC และ MRC คืออะไร

MRC คือการนับ reference ด้วยตนเอง: โปรแกรมเมอร์เรียก retain, release, autorelease ARC คืออัตโนมัติ: คอมไพเลอร์แทรก retain/release ตามการวิเคราะห์แบบสถิต ARC ไม่ใช่ GC — ออบเจ็กต์ถูกปล่อยทันทีเมื่อตัวนับถึงศูนย์ ARC รองรับตัวปรับแต่ง __weak และ __strong

สามารถใช้ Objective-C และ Swift ในโปรเจกต์เดียวกันได้หรือไม่

ได้ ผ่าน Bridging Header Swift มองเห็น Objective-C ผ่านส่วนหัวนี้ Objective-C มองเห็น Swift ผ่าน <ProjectName>-Swift.h คลาส Swift ต้องสืบทอดจาก NSObject และทำเครื่องหมายด้วย @objc struct และ enum ของ Swift ไม่สามารถมองเห็นได้โดยตรงโดย Objective-C

สรุป

  • Objective-C — ซูเปอร์เซ็ตที่เข้มงวดของ C พร้อมรันไทม์แบบไดนามิกและไวยากรณ์ข้อความสำหรับ Cocoa/Cocoa Touch
  • Message passing — การเรียกผ่าน [object method] พร้อมการจัดส่งแบบไดนามิกผ่าน objc_msgSend และความสามารถ swizzling
  • หมวดหมู่ — การเพิ่มเมธอดให้กับคลาสที่มีอยู่โดยไม่ต้องสืบทอด รวมถึงคลาสระบบของ Apple
  • บล็อก — ฟังก์ชันนิรนามพร้อม Closure ที่ต้องใช้ __weak เพื่อป้องกัน retain cycles
  • ARC vs MRC — วิวัฒนาการจากการ retain/release ด้วยตนเองไปสู่การนับ reference อัตโนมัติผ่านคอมไพเลอร์
  • Bridging Header — กลไกให้ Swift และ Objective-C ทำงานร่วมกันในโปรเจกต์เดียวสำหรับการย้ายแบบค่อยเป็นค่อยไป
  • ความสำคัญแบบเดิม — ประมาณ 35% ของแอป App Store มีโค้ด Objective-C ที่ต้องการการบำรุงรักษา

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม