Перейти до вмісту

Objective-C

Матеріал з K2 ERP Wiki Ukraine — База знань з автоматизації та санкцій в Україні

SEO title: Objective-C — мова програмування Apple, iOS, macOS, Cocoa, Cocoa Touch і legacy-розробка SEO description: Objective-C — Wiki-стаття про об’єктно-орієнтовану мову програмування на базі C, яка довгий час була основною мовою для розробки під Apple-платформи. Розглянуто історію Objective-C, синтаксис, класи, об’єкти, повідомлення, Foundation, Cocoa, Cocoa Touch, Xcode, ARC, memory management, categories, protocols, delegates, blocks, runtime, взаємодію зі Swift, переваги, обмеження і хороші практики. SEO keywords: Objective-C, мова програмування Objective-C, Objective-C programming language, Apple, iOS, macOS, Cocoa, Cocoa Touch, Foundation, Xcode, NSObject, message sending, Objective-C runtime, ARC, memory management, categories, protocols, delegates, blocks, Swift, UIKit, AppKit, legacy iOS, legacy macOS, програмування Alternative to: C для об’єктно-орієнтованої розробки під Apple; ранні підходи до macOS і iOS розробки; legacy Apple codebase без Swift; низькорівневий C-код без Cocoa-об’єктної моделі; ручне створення Apple UI без фреймворків; старі Objective-C/Cocoa проєкти, які поступово мігрують на Swift


Objective-C — це об’єктно-орієнтована мова програмування, побудована як розширення мови C. Вона довгий час була основною мовою для розробки застосунків під платформи Apple: macOS, iOS, iPadOS, watchOS і tvOS.

Objective-C тісно пов’язана з фреймворками Foundation, Cocoa, Cocoa Touch, AppKit, UIKit і середовищем розробки Xcode.

Основна ідея: Objective-C поєднує низькорівневі можливості C з динамічною об’єктною моделлю, message sending і фреймворками Apple.

Загальний опис

Objective-C є надмножиною C, тобто звичайний C-код може бути частиною Objective-C-програми. Це дозволило поєднати системне програмування, роботу з пам’яттю й об’єктно-орієнтовану модель, потрібну для графічних застосунків і фреймворків Apple.

Objective-C використовувалась для:

  • macOS-застосунків;
  • iOS-застосунків;
  • Cocoa-програм;
  • Cocoa Touch-програм;
  • UIKit-інтерфейсів;
  • AppKit-інтерфейсів;
  • системних бібліотек Apple;
  • legacy codebase;
  • інтеграції з C і C++;
  • плагінів;
  • SDK;
  • Objective-C runtime-розширень.

Перевага: Objective-C дала Apple-екосистемі потужну динамічну об’єктну модель поверх C і стала основою багатьох фреймворків macOS та iOS.

Історія Objective-C

Objective-C виникла як спроба поєднати C із об’єктно-орієнтованими ідеями Smalltalk. Мова стала важливою частиною NeXTSTEP, а пізніше — macOS після придбання NeXT компанією Apple.

До появи Swift саме Objective-C була основною мовою для розробників Apple-платформ.

Вона історично використовувалась у:

  • NeXTSTEP;
  • OPENSTEP;
  • macOS;
  • iOS;
  • Cocoa;
  • Cocoa Touch;
  • системних фреймворках Apple;
  • ранніх мобільних застосунках для iPhone і iPad.

Важливо: Objective-C залишається важливою для підтримки старих Apple-проєктів, навіть якщо нові проєкти часто пишуть на Swift.

Objective-C і C

Objective-C є розширенням C.

Це означає, що в Objective-C можна використовувати:

  • змінні C;
  • функції C;
  • структури C;
  • вказівники;
  • `malloc` і `free`;
  • header files;
  • препроцесор;
  • C-бібліотеки;
  • системні API;
  • низькорівневий код.

Приклад C-коду в Objective-C:

int add(int a, int b) {
    return a + b;
}

Суть зв’язку: Objective-C не замінює C, а додає до нього об’єкти, класи, повідомлення й runtime.

Перша програма на Objective-C

Простий приклад:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"Hello, world!");
    }
    return 0;
}

У цьому прикладі:

  • `#import` підключає header file;
  • `Foundation/Foundation.h` підключає базові класи Foundation;
  • `@autoreleasepool` керує autoreleased об’єктами;
  • `NSLog` виводить повідомлення в лог;
  • `@"Hello, world!"` — Objective-C string literal.

Суть прикладу: Objective-C-програма може виглядати як C-програма, але використовувати об’єкти Foundation і спеціальний синтаксис Objective-C.

Xcode

Xcode — основне середовище розробки Apple для Objective-C, Swift, C, C++ і Apple-платформ.

Xcode використовується для:

  • написання коду;
  • збірки застосунків;
  • роботи з Interface Builder;
  • debugging;
  • profiling;
  • роботи з simulators;
  • підпису застосунків;
  • запуску тестів;
  • керування targets;
  • роботи з Apple SDK;
  • публікації застосунків.

Практична роль: Objective-C майже завжди розглядається разом із Xcode, Apple SDK і фреймворками Cocoa або Cocoa Touch.

Foundation

Foundation — базовий фреймворк Apple, який надає фундаментальні класи й типи.

Foundation містить:

  • `NSObject`;
  • `NSString`;
  • `NSArray`;
  • `NSDictionary`;
  • `NSNumber`;
  • `NSDate`;
  • `NSData`;
  • `NSError`;
  • `NSURL`;
  • `NSFileManager`;
  • `NSNotificationCenter`;
  • `NSOperation`;
  • `NSTimer`.

Приклад:

NSString *name = @"Alice";
NSArray *items = @[@"A", @"B", @"C"];

NSLog(@"Name: %@", name);
NSLog(@"Items: %@", items);

Практична роль: Foundation дає Objective-C базові об’єктні типи для рядків, колекцій, дат, файлів, URL і помилок.

Cocoa і Cocoa Touch

Cocoa — фреймворк для macOS-застосунків.

Cocoa Touch — фреймворк для iOS і пов’язаних мобільних платформ.

Cocoa пов’язаний із:

  • AppKit;
  • Foundation;
  • macOS UI;
  • desktop applications.

Cocoa Touch пов’язаний із:

  • UIKit;
  • Foundation;
  • iOS UI;
  • touch interaction;
  • mobile application lifecycle.

Суть Apple-фреймворків: Objective-C стала практичною мовою саме завдяки потужним фреймворкам Cocoa і Cocoa Touch.

AppKit

AppKit — фреймворк для створення графічних macOS-застосунків.

AppKit містить:

  • `NSApplication`;
  • `NSWindow`;
  • `NSView`;
  • `NSButton`;
  • `NSTextField`;
  • `NSMenu`;
  • `NSDocument`;
  • controller-класи для macOS UI.

Практична роль: AppKit — основа класичних desktop-застосунків macOS.

UIKit

UIKit — фреймворк для створення iOS і iPadOS-застосунків.

UIKit містить:

  • `UIApplication`;
  • `UIView`;
  • `UIViewController`;
  • `UIButton`;
  • `UILabel`;
  • `UITableView`;
  • `UICollectionView`;
  • `UINavigationController`;
  • `UITabBarController`;
  • gesture recognizers;
  • application lifecycle.

Приклад:

UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 50, 200, 40)];
label.text = @"Hello";
[self.view addSubview:label];

Практична роль: UIKit був головним фреймворком для створення iOS-інтерфейсів на Objective-C.

Класи

Клас в Objective-C зазвичай має два файли:

  • `.h` — interface;
  • `.m` — implementation.

Файл `User.h`:

#import <Foundation/Foundation.h>

@interface User : NSObject

@property (nonatomic, copy) NSString *name;

- (instancetype)initWithName:(NSString *)name;
- (NSString *)greeting;

@end

Файл `User.m`:

#import "User.h"

@implementation User

- (instancetype)initWithName:(NSString *)name {
    self = [super init];
    if (self) {
        _name = [name copy];
    }
    return self;
}

- (NSString *)greeting {
    return [NSString stringWithFormat:@"Hello, %@", self.name];
}

@end

Суть класу: Objective-C розділяє оголошення публічного інтерфейсу й реалізацію, що добре вписується в C-style header модель.

Об’єкти

Об’єкти в Objective-C зазвичай створюються через `alloc` і `init`.

Приклад:

User *user = [[User alloc] initWithName:@"Alice"];
NSLog(@"%@", [user greeting]);

У цьому прикладі:

  • `User *user` — змінна-вказівник на об’єкт;
  • `alloc` виділяє пам’ять;
  • `initWithName:` ініціалізує об’єкт;
  • `[user greeting]` надсилає повідомлення об’єкту.

Важливо: Objective-C-об’єкти зазвичай передаються як вказівники, тому синтаксис `*` є нормальним для роботи з об’єктами.

Message sending

Objective-C використовує модель message sending.

Замість виклику методу у стилі:

object.method(argument)

Objective-C використовує:

[object methodWithArgument:argument];

Приклад:

NSString *text = @"hello";
NSString *upper = [text uppercaseString];

NSLog(@"%@", upper);

Суть message sending: Objective-C не просто викликає функцію, а надсилає повідомлення об’єкту через runtime.

Методи

Методи в Objective-C бувають:

  • instance methods — починаються з `-`;
  • class methods — починаються з `+`.

Приклад:

- (NSString *)fullName {
    return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}

+ (instancetype)defaultUser {
    return [[self alloc] init];
}

Метод із параметрами:

- (void)setName:(NSString *)name age:(NSInteger)age {
    self.name = name;
    self.age = age;
}

Практична роль: назви методів Objective-C часто читаються як фрази, що робить API довшими, але зрозумілими.

Properties

Property описує доступ до даних об’єкта.

Приклад:

@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, strong) NSArray *items;
@property (nonatomic, weak) id delegate;

Поширені атрибути:

  • `strong`;
  • `weak`;
  • `copy`;
  • `assign`;
  • `nonatomic`;
  • `atomic`;
  • `readonly`;
  • `readwrite`.

Практична роль: properties автоматизують getters і setters, а також описують правила memory management.

Strong, weak, copy і assign

Атрибути property важливі для керування пам’яттю.

Атрибут Значення
strong Об’єкт утримується власником
weak Слабке посилання, яке не утримує об’єкт
copy Об’єкт копіюється під час присвоєння
assign Просте присвоєння, часто для primitive types

Важливо: неправильний вибір `strong`, `weak`, `copy` або `assign` може спричинити memory leaks, dangling references або неочікувану зміну mutable-об’єктів.

NSObject

NSObject — базовий клас для більшості Objective-C-класів у Foundation і Cocoa.

NSObject надає:

  • базову об’єктну поведінку;
  • runtime-інтеграцію;
  • `isEqual`;
  • `hash`;
  • `description`;
  • memory management support;
  • introspection;
  • message dispatch;
  • key-value coding support у відповідних контекстах.

Практична роль: NSObject є фундаментом більшості класичних Objective-C API в Apple-екосистемі.

NSString

NSString — основний immutable-рядок у Objective-C.

Приклад:

NSString *name = @"Alice";
NSString *message = [NSString stringWithFormat:@"Hello, %@", name];

NSLog(@"%@", message);

Mutable-версія:

NSMutableString *text = [NSMutableString stringWithString:@"Hello"];
[text appendString:@", world"];

Практична роль: NSString і NSMutableString є базовими класами для роботи з текстом у Objective-C.

NSArray

NSArray — immutable-масив об’єктів.

Приклад:

NSArray *items = @[@"A", @"B", @"C"];

NSLog(@"%@", items[0]);

Mutable-версія:

NSMutableArray *items = [NSMutableArray array];
[items addObject:@"A"];
[items addObject:@"B"];

Увага: NSArray зберігає об’єкти, а не primitive values напряму. Для чисел часто використовують NSNumber.

NSDictionary

NSDictionary — key-value колекція.

Приклад:

NSDictionary *user = @{
    @"name": @"Alice",
    @"age": @25
};

NSLog(@"%@", user[@"name"]);

Mutable-версія:

NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[@"status"] = @"active";

Практична роль: NSDictionary часто використовується для конфігурацій, JSON-подібних структур і key-value даних.

NSNumber

NSNumber — wrapper для числових primitive values.

Приклад:

NSNumber *age = @25;
NSNumber *price = @19.99;
NSNumber *active = @YES;

NSLog(@"%@", age);

Суть NSNumber: Objective-C-колекції зберігають об’єкти, тому primitive values потрібно обгортати в NSNumber.

Literals

Objective-C підтримує literals для частини Foundation-типів.

Приклади:

NSString *text = @"Hello";
NSNumber *number = @42;
NSArray *array = @[@"A", @"B"];
NSDictionary *dict = @{@"name": @"Alice"};

Перевага literals: вони роблять Objective-C-код коротшим і читабельнішим під час роботи з Foundation-типами.

Categories

Category дозволяє додавати методи до існуючого класу без створення subclass.

Приклад:

@interface NSString (Reversed)

- (NSString *)reversedString;

@end

@implementation NSString (Reversed)

- (NSString *)reversedString {
    NSMutableString *result = [NSMutableString string];

    for (NSInteger i = self.length - 1; i >= 0; i--) {
        [result appendFormat:@"%C", [self characterAtIndex:i]];
    }

    return result;
}

@end

Важливо: categories зручні для розширення класів, але конфлікти імен методів можуть створювати неочевидну поведінку.

Protocols

Protocol описує набір методів, які клас може реалізувати.

Приклад:

@protocol Logger

- (void)logMessage:(NSString *)message;

@end

Клас реалізує protocol:

@interface ConsoleLogger : NSObject <Logger>
@end

@implementation ConsoleLogger

- (void)logMessage:(NSString *)message {
    NSLog(@"%@", message);
}

@end

Суть protocol: protocol дозволяє описати контракт без прив’язки до конкретного класу.

Delegates

Delegate — поширений патерн в Objective-C і Cocoa.

Delegate дозволяє одному об’єкту передавати іншому об’єкту частину відповідальності або повідомляти про події.

Приклад ідеї:

@property (nonatomic, weak) id<MyViewDelegate> delegate;

Delegate часто використовується в:

  • UIKit;
  • AppKit;
  • table views;
  • collection views;
  • text fields;
  • navigation;
  • custom components;
  • event handling.

Практична роль: delegates дозволяють будувати гнучку взаємодію між об’єктами без жорсткої прив’язки класів.

Blocks

Blocks — це замикання в Objective-C, тобто фрагменти коду, які можна передавати як значення.

Приклад:

void (^completion)(NSString *) = ^(NSString *message) {
    NSLog(@"%@", message);
};

completion(@"Done");

Blocks використовуються для:

  • callbacks;
  • async operations;
  • completion handlers;
  • animations;
  • enumeration;
  • networking;
  • event handling.

Практична роль: blocks стали важливою частиною сучасного Objective-C API, особливо для асинхронного коду.

Memory management

У Objective-C історично було ручне керування пам’яттю через reference counting:

  • `retain`;
  • `release`;
  • `autorelease`;
  • `dealloc`.

Пізніше з’явився ARC — Automatic Reference Counting.

Важливо: у старому Objective-C-коді можна зустріти manual memory management, але сучасні проєкти зазвичай використовують ARC.

ARC

ARC або Automatic Reference Counting — механізм автоматичного додавання retain/release на етапі компіляції.

ARC допомагає:

  • зменшити кількість ручного memory management;
  • уникнути частини leaks;
  • спростити Objective-C-код;
  • краще працювати з properties;
  • зменшити ризик double release.

Але ARC не вирішує всі проблеми.

Наприклад, strong reference cycle все ще можливий.

Перевага ARC: програмісту не потрібно вручну писати retain і release для більшості звичайних об’єктів.

Retain cycle

Retain cycle виникає, коли два або більше об’єкти сильно утримують один одного.

Приклад ризику:

self.completion = ^{
    [self doSomething];
};

Якщо `self` утримує block, а block утримує `self`, може виникнути цикл.

Типове рішення:

__weak typeof(self) weakSelf = self;

self.completion = ^{
    [weakSelf doSomething];
};

Критично: ARC не захищає автоматично від retain cycles. Blocks, delegates і strong references потрібно перевіряти уважно.

Autorelease pool

Autorelease pool керує об’єктами, які мають бути звільнені пізніше.

Приклад:

@autoreleasepool {
    NSString *text = [NSString stringWithFormat:@"Hello"];
    NSLog(@"%@", text);
}

Autorelease pool особливо важливий для:

  • command-line Objective-C;
  • background loops;
  • manual memory-sensitive sections;
  • старого коду;
  • місць із великою кількістю тимчасових об’єктів.

Увага: у довгих циклах іноді потрібно створювати власний autorelease pool, щоб тимчасові об’єкти не накопичувалися занадто довго.

Objective-C runtime

Objective-C runtime — це динамічна система, яка відповідає за класи, методи, message sending, introspection і динамічну поведінку.

Runtime дозволяє:

  • надсилати повідомлення;
  • перевіряти клас об’єкта;
  • додавати методи;
  • swizzling;
  • reflection;
  • dynamic dispatch;
  • працювати з selectors;
  • змінювати поведінку під час виконання.

Суть runtime: Objective-C є динамічнішою мовою, ніж C++ або Java, тому багато рішень приймаються під час виконання.

Selectors

Selector — це ідентифікатор методу в Objective-C runtime.

Приклад:

SEL selector = @selector(viewDidLoad);

Використання:

if ([object respondsToSelector:@selector(doWork)]) {
    [object performSelector:@selector(doWork)];
}

Практична роль: selectors використовуються runtime, target-action, delegates і багатьма Cocoa-механізмами.

Target-action

Target-action — патерн, який широко використовується в UIKit і AppKit.

Приклад:

[button addTarget:self
           action:@selector(buttonTapped:)
 forControlEvents:UIControlEventTouchUpInside];

Метод:

- (void)buttonTapped:(id)sender {
    NSLog(@"Button tapped");
}

Практична роль: target-action дозволяє UI-компоненту повідомляти об’єкт про подію.

KVC

Key-Value Coding або KVC дозволяє доступ до властивостей через рядкові ключі.

Приклад:

[user setValue:@"Alice" forKey:@"name"];
NSString *name = [user valueForKey:@"name"];

KVC використовується в:

  • Cocoa bindings;
  • serialization;
  • runtime-driven code;
  • dynamic data mapping;
  • frameworks.

Важливо: KVC потужний, але помилки в рядкових ключах часто знаходяться лише під час виконання.

KVO

Key-Value Observing або KVO дозволяє спостерігати за змінами властивостей.

KVO використовується для:

  • bindings;
  • UI updates;
  • model observation;
  • reactive-like patterns;
  • legacy Cocoa-механізмів.

Увага: KVO може бути складним у підтримці, тому в сучасному коді часто використовують зрозуміліші механізми спостереження або Swift-підходи.

NSError

NSError — стандартний клас для опису помилок у Cocoa API.

Приклад:

NSError *error = nil;
NSString *content = [NSString stringWithContentsOfFile:path
                                              encoding:NSUTF8StringEncoding
                                                 error:&error];

if (content == nil) {
    NSLog(@"Error: %@", error.localizedDescription);
}

Практична роль: багато Objective-C API повертають результат і заповнюють `NSError **`, якщо сталася помилка.

Exceptions

Objective-C має exceptions, але в Cocoa вони зазвичай не використовуються для звичайної обробки помилок.

Приклад:

@try {
    // risky code
}
@catch (NSException *exception) {
    NSLog(@"Exception: %@", exception);
}
@finally {
    NSLog(@"Done");
}

Важливо: у Cocoa-style коді звичайні помилки часто передаються через `NSError`, а exceptions використовуються для виняткових ситуацій.

Nullability

Objective-C підтримує nullability annotations, які допомагають описувати, чи може значення бути `nil`.

Приклад:

- (nullable User *)findUserById:(NSString *)userId;
- (nonnull NSString *)displayName;

Поширені annotations:

  • `nullable`;
  • `nonnull`;
  • `null_unspecified`;
  • `null_resettable`.

Практична роль: nullability annotations особливо важливі для взаємодії Objective-C зі Swift.

Generics в Objective-C

Objective-C має lightweight generics для колекцій.

Приклад:

NSArray<NSString *> *names = @[@"Alice", @"Bob"];
NSDictionary<NSString *, NSNumber *> *scores = @{
    @"Alice": @10,
    @"Bob": @20
};

Практична роль: lightweight generics покращують type hints і Swift-інтеграцію, але не є такими строгими, як generics у Swift або Java.

Swift і Objective-C

Swift поступово став основною мовою нової розробки в Apple-екосистемі, але Objective-C залишається важливою через legacy code і системні API.

Objective-C і Swift можуть взаємодіяти.

Типові сценарії:

  • Swift викликає Objective-C-код;
  • Objective-C викликає Swift-код через generated header;
  • поступова міграція старого проєкту;
  • використання Objective-C SDK у Swift;
  • змішаний codebase.

Перевага сумісності: Apple дозволила поступово переходити з Objective-C на Swift без повного переписування застосунків.

Bridging header

Bridging header використовується, щоб Swift-код міг бачити Objective-C headers.

Приклад:

#import "User.h"
#import "LegacyService.h"

Після цього Swift може використовувати ці класи.

Практична роль: bridging header є ключовим інструментом поступової міграції Objective-C-проєкту на Swift.

Objective-C++

Objective-C++ дозволяє змішувати Objective-C і C++ в одному файлі з розширенням `.mm`.

Використовується для:

  • інтеграції C++ libraries;
  • game engines;
  • multimedia;
  • high-performance modules;
  • cross-platform code;
  • legacy systems;
  • native wrappers.

Увага: Objective-C++ дуже потужний, але може ускладнити build, memory management і межі між мовами.

Storyboards і Interface Builder

Objective-C-застосунки часто створювали UI через Interface Builder, XIB або Storyboards.

Це дозволяло:

  • створювати екрани візуально;
  • підключати outlets;
  • підключати actions;
  • налаштовувати constraints;
  • працювати з UIKit/AppKit;
  • зв’язувати UI з Objective-C-кодом.

Приклад outlet:

@property (nonatomic, weak) IBOutlet UILabel *titleLabel;

Приклад action:

- (IBAction)buttonTapped:(id)sender {
    self.titleLabel.text = @"Tapped";
}

Практична роль: IBOutlet і IBAction зв’язують візуальний інтерфейс із Objective-C-кодом.

MVC в Cocoa

Cocoa і Cocoa Touch історично використовують патерн MVC.

Типові ролі:

  • Model — дані й бізнес-логіка;
  • View — UI;
  • Controller — зв’язок між Model і View.

У iOS часто використовувалися `UIViewController`, `UITableViewController`, `UINavigationController`.

Важливо: у великих Objective-C iOS-проєктах контролери могли ставати занадто великими, тому команди використовували додаткові архітектурні підходи.

Objective-C і SwiftUI

SwiftUI орієнтований на Swift, а не Objective-C. Тому Objective-C частіше зустрічається в UIKit/AppKit legacy-проєктах.

У сучасних Apple-проєктах можливі варіанти:

  • старий UIKit-код на Objective-C;
  • новий Swift-код;
  • поступова міграція екранів;
  • SwiftUI для нових частин;
  • bridging між Objective-C і Swift;
  • Objective-C для legacy SDK або бібліотек.

Практична порада: Objective-C зазвичай не обирають для нових SwiftUI-проєктів, але вона важлива для підтримки старого UIKit/AppKit-коду.

Objective-C runtime і swizzling

Method swizzling — це заміна реалізації методу під час виконання через Objective-C runtime.

Swizzling використовують для:

  • debugging;
  • analytics;
  • testing;
  • framework hooks;
  • legacy patches;
  • instrumentation.

Критично: method swizzling може створювати дуже неочевидну поведінку. Його потрібно використовувати лише там, де без цього справді не обійтися.

Objective-C і Apple legacy

Objective-C залишається важливою мовою через величезну кількість старого коду.

Legacy Objective-C може містити:

  • старі iOS-застосунки;
  • macOS-застосунки;
  • внутрішні SDK;
  • системні бібліотеки;
  • Objective-C categories;
  • UIKit/AppKit code;
  • manual memory management;
  • Objective-C++;
  • старі build settings;
  • mixed Swift/Objective-C codebase.

Практична роль: знання Objective-C корисне для підтримки, міграції й розуміння старих Apple-проєктів.

Objective-C і C++

Objective-C і C++ можна змішувати через Objective-C++.

Критерій Objective-C C++
Об’єктна модель Динамічна, message sending Статична/компіляторна, virtual dispatch
Runtime Сильний Objective-C runtime Менш динамічний runtime
Пам’ять ARC або manual reference counting RAII, smart pointers, manual control
Типовий Apple use case Cocoa, UIKit, AppKit Engines, libraries, high-performance modules

Висновок: Objective-C добре підходить для Apple API, а C++ — для cross-platform core, engine logic і продуктивних бібліотек.

Objective-C і Swift

Критерій Objective-C Swift
Стиль C-based, dynamic runtime, message sending Сучасна статично типізована мова Apple
Безпека Більше runtime-ризиків і nil-поведінки Сильніша типобезпека, Optionals
Нові проєкти Рідше Частіше
Legacy Дуже важливий Використовується для нової розробки й міграції
UI UIKit/AppKit legacy SwiftUI, UIKit, AppKit

Висновок: Swift є основним вибором для нової Apple-розробки, а Objective-C залишається важливою для legacy, runtime і старих фреймворків.

Objective-C і C

Критерій Objective-C C
Основа Розширення C Базова системна мова
Об’єкти Є класи й message sending Немає вбудованої ООП
Runtime Динамічний Objective-C runtime Мінімальний runtime
Apple UI Cocoa, UIKit, AppKit Не основний рівень для UI
Низький рівень Може використовувати C напряму Повний контроль низького рівня

Висновок: Objective-C додає до C об’єкти й Apple-фреймворки, але зберігає доступ до C-коду.

Переваги Objective-C

Основні переваги Objective-C:

  • сумісність із C;
  • динамічний runtime;
  • message sending;
  • зріла Cocoa/Cocoa Touch екосистема;
  • велика legacy-база Apple;
  • можливість взаємодії зі Swift;
  • categories;
  • protocols;
  • delegates;
  • blocks;
  • runtime introspection;
  • Objective-C++;
  • велика кількість старих прикладів і SDK;
  • гнучкість у runtime.

Головна перевага: Objective-C дає доступ до старої й зрілої Apple-екосистеми, а також дозволяє підтримувати й поступово мігрувати великі legacy-проєкти.

Обмеження Objective-C

Objective-C має обмеження.

Можливі проблеми:

  • складніший синтаксис для новачків;
  • менша безпека типів, ніж у Swift;
  • runtime-помилки;
  • nil може приховувати проблеми;
  • довші назви методів;
  • header/implementation розділення;
  • manual memory management у старому коді;
  • retain cycles навіть з ARC;
  • складність mixed codebase;
  • менше нових навчальних матеріалів;
  • нові Apple API часто орієнтовані на Swift.

Помилка: вважати Objective-C застарілою настільки, що її не потрібно знати. Для підтримки Apple legacy-коду вона все ще може бути дуже важливою.

Коли варто використовувати Objective-C

Objective-C доречно використовувати, коли потрібно:

  • підтримувати старий iOS або macOS codebase;
  • працювати з legacy SDK;
  • писати bridge до старого Objective-C API;
  • інтегруватися з C або C++;
  • підтримувати Objective-C categories;
  • працювати з runtime;
  • поступово мігрувати застосунок на Swift;
  • виправляти UIKit/AppKit legacy-код;
  • працювати з Objective-C++.

Практична порада: Objective-C найчастіше варто вивчати для підтримки, міграції й розуміння існуючих Apple-проєктів.

Коли Objective-C може бути невдалим вибором

Objective-C зазвичай не є найкращим вибором для:

  • нових SwiftUI-застосунків;
  • нових iOS-проєктів без legacy-вимог;
  • команд, які повністю працюють на Swift;
  • застосунків, де потрібна сильна сучасна типобезпека;
  • навчання Apple-розробки з нуля;
  • нових cross-platform mobile apps;
  • проєктів, де немає залежності від Objective-C legacy.

Важливо: для нової Apple-розробки зазвичай логічніше обирати Swift, а Objective-C залишати для legacy, інтеграцій і спеціальних сценаріїв.

Безпека Objective-C-коду

Objective-C-код потребує уважної перевірки безпеки.

Потрібно контролювати:

  • memory management;
  • retain cycles;
  • weak references;
  • небезпечні C API;
  • buffer overflow у C-коді;
  • unsafe casts;
  • KVC/KVO помилки;
  • runtime swizzling;
  • injection у string-based API;
  • file access;
  • Keychain usage;
  • networking security;
  • secrets;
  • logging sensitive data.

Критично: Objective-C може поєднувати високорівневий Cocoa-код із низькорівневим C-кодом, тому security review має враховувати обидва рівні.

Приватність даних

Apple-застосунки часто працюють із персональними даними, тому privacy важлива.

Потрібно контролювати:

  • доступ до контактів;
  • геолокацію;
  • фото;
  • камеру;
  • мікрофон;
  • push tokens;
  • Keychain;
  • user defaults;
  • crash logs;
  • analytics;
  • network requests;
  • локальні файли;
  • permissions;
  • App Store privacy requirements.

Правило: Objective-C-застосунок має запитувати лише ті дозволи й дані, які реально потрібні для функції користувача.

Хороші практики Objective-C

Рекомендовано:

  • використовувати ARC;
  • правильно вибирати `strong`, `weak`, `copy`;
  • уникати retain cycles;
  • використовувати `weak` для delegates;
  • додавати nullability annotations;
  • використовувати lightweight generics;
  • не зловживати method swizzling;
  • тримати categories невеликими;
  • не приховувати бізнес-логіку в runtime-магії;
  • писати зрозумілі method names;
  • перевіряти `NSError`;
  • не ігнорувати warnings;
  • писати tests;
  • поступово мігрувати критичні частини на Swift, якщо це має сенс.

Головне правило: хороший Objective-C-код має бути явним, акуратним із пам’яттю, добре анотованим для Swift і без зайвої runtime-магії.

Типові помилки початківців

Поширені помилки:

  • плутанина між `strong`, `weak`, `copy`;
  • retain cycles у blocks;
  • strong delegate;
  • неправильне використання `assign` для об’єктів;
  • відсутність nullability annotations;
  • ігнорування `NSError`;
  • неправильні selectors;
  • помилки в KVC-ключах;
  • надмірне swizzling;
  • плутанина між C strings і NSString;
  • забуті imports;
  • неправильна робота з mutable і immutable колекціями;
  • змішування Swift і Objective-C без чітких меж.

Небезпека: Objective-C-код може компілюватися, але падати під час виконання через runtime-помилки, неправильні selectors або nil/типові проблеми.

Приклади задач на Objective-C

Створення рядка

NSString *name = @"Alice";
NSString *message = [NSString stringWithFormat:@"Hello, %@", name];

NSLog(@"%@", message);

Робота з масивом

NSArray<NSString *> *items = @[@"A", @"B", @"C"];

for (NSString *item in items) {
    NSLog(@"%@", item);
}

Delegate property

@property (nonatomic, weak) id<MyServiceDelegate> delegate;

Block callback

- (void)loadDataWithCompletion:(void (^)(NSArray *items, NSError *error))completion {
    NSArray *items = @[@"A", @"B"];

    if (completion) {
        completion(items, nil);
    }
}

Weak self у block

__weak typeof(self) weakSelf = self;

self.completion = ^{
    [weakSelf updateUI];
};

Підказка: в Objective-C-прикладах важливо дивитися не лише на синтаксис, а й на ownership, nil, properties, ARC і runtime-поведінку.

Джерела

  • Apple Developer Documentation.
  • Objective-C Runtime Programming Guide.
  • Programming with Objective-C.
  • Cocoa Fundamentals Guide.
  • Foundation Framework Reference.
  • UIKit Documentation.
  • AppKit Documentation.
  • Xcode Documentation.
  • Swift and Objective-C Interoperability Documentation.
  • Advanced Memory Management Programming Guide.

Висновок

Objective-C — це об’єктно-орієнтована мова на базі C, яка багато років була основною мовою Apple-розробки. Вона дала екосистемі Apple динамічний runtime, message sending, Cocoa, Cocoa Touch, UIKit, AppKit і велику кількість legacy-коду.

Сьогодні Objective-C найчастіше важлива для підтримки старих iOS/macOS-проєктів, роботи з legacy SDK, інтеграції зі Swift, Objective-C++ і розуміння Apple runtime. Для нової розробки частіше використовують Swift, але Objective-C залишається важливою мовою для професійної роботи з Apple-екосистемою.

Головна думка: Objective-C — це мова Apple legacy, Cocoa runtime і глибокої сумісності з C. Вона вже не є типовим вибором для нових проєктів, але залишається важливою для підтримки, міграції й розуміння старих Apple-систем.

Див. також

Тематичні мітки