В чем разница между управлением памятью в Objective-C и Swift?

Ответ

Objective-C исторически использовал ручное управление памятью (MRC), где программист вызывал retain, release, autorelease. Позже был введен Automatic Reference Counting (ARC), который автоматически вставляет эти вызовы, но все еще основан на подсчете ссылок для объектов (reference types).

Swift использует более современный и оптимизированный ARC, который эффективно работает как с reference-типами (классы), так и с value-типами (структуры, перечисления). Swift предоставляет более безопасные и четкие механизмы для предотвращения циклов сильных ссылок.

Ключевые отличия:

  1. Оптимизация: Swift ARC более агрессивно оптимизирован компилятором (например, может размещать объекты в стеке).
  2. Value types: В Swift ARC управляет памятью для value-типов, которые используют механизм Copy-on-Write.
  3. Безопасность ссылок: Swift предоставляет weak (опциональная слабая ссылка) и unowned (неопциональная, но с гарантией существования объекта). В Objective-C есть __weak и менее безопасный __unsafe_unretained.
  4. Мост в C: Objective-C часто требует явного использования квалификаторов, таких как __bridge, __autoreleasing.

Пример weak-ссылки:

// Swift
class Person {
    weak var apartment: Apartment?
}
// Objective-C
@interface Person : NSObject
@property (weak) Apartment *apartment;
@end

Ответ 18+ 🔞

Ну, вот смотри, как оно было, блядь. Раньше, в Objective-C, мы сами, как последние идиоты, ручками памятью управляли. retain, release, autorelease — вот эта вся хуйня. Каждый чих — подотри, каждый объект — отпусти. Пиздец, а не жизнь.

Потом придумали ARC — Automatic Reference Counting. Ну, вроде как, отпустили нас, грешных, на волю. Компилятор сам эти вызовы вставляет. Но основа-то всё та же, старая, как говно мамонта — подсчёт ссылок для объектов, то есть для классов. Всё ещё можно накосячить и устроить цикл сильных ссылок, чтобы память потекла, как из дырявого ведра.

А потом пришёл Swift, со своим новым, подкачанным ARC. И тут, ёпта, началось. Он не только с классами работает, но и со структурами, и с перечислениями — со всеми этими value-типами. И работает он так хитро, что мозг сломать можно. Например, Copy-on-Write — пока ты объект не трогаешь, он не копируется, а как только начинаешь менять — бац, и уже новый. Экономия, блядь, на каждом шагу.

Чем они, сука, отличаются, если коротко:

  1. Оптимизация. Swift ARC — это как спорткар, а Objective-C ARC — как жигули с турбиной. Компилятор Swift такой умный, что может объект в стек запихнуть, если видит, что так быстрее. В Objective-C такого, блядь, не было.
  2. Value types. В Objective-C про них нихуя не слышали, там всё через NSObject и классы. А в Swift — пожалуйста, структуры, перечисления, и ARC за ними тоже присматривает, но по-своему, умному.
  3. Безопасность ссылок. Тут вроде всё похоже, но в Swift чётче. Есть weak — слабая ссылка, которая становится nil, если объект умер. А есть unowned — это когда ты говоришь: «Да он точно жив, я ж его знаю!». Но если он всё-таки помер, а ты к нему через unowned полез — получишь краш, и будешь сидеть и думать, какой же ты мудак. В Objective-C __weak — это аналог weak, а __unsafe_unretained — это как unowned, только ещё опаснее, потому что может указать на освобождённую память и устроить пиздец.
  4. Мост в C. Objective-C, старый пердун, постоянно требует этих __bridge, __autoreleasing, когда с чистым C общаешься. В Swift с этим попроще, но тоже свои заморочки есть.

Вот, смотри, как слабую ссылку объявляют, чтобы циклов не было:

// Swift
class Person {
    weak var apartment: Apartment? // Смотри, weak! Чтобы не держал намертво.
}
// Objective-C
@interface Person : NSObject
@property (weak) Apartment *apartment; // Тот же weak, только синтаксис другой, блядь.
@end

Вот и вся разница, если в двух словах. Swift взял старую, проверенную идею и сделал её быстрее, умнее и для большего количества типов. Но суть-то, блядь, одна — считай ссылки и вовремя убирай за собой, а то опять всё упадёт.