iOS Mülakat Hazırlık 1 — Bellek yönetimi

Apr 28 2023
Bellek yönetimi, iOS röportajı sırasında en sık sorulan sorulardan biridir; referans döngüsü, güçlü/zayıf referans gibi temel kavramları iyi anladığınızı gösteremezseniz, bu büyük bir tehlike işaretidir. Bellek yönetimi ile ilgili her türlü soruya hazırlanmak için ARC perdesinin arkasındaki temel mekanizmayı anlamak çok önemlidir.

Bellek yönetimi, iOS röportajı sırasında en sık sorulan sorulardan biridir; referans döngüsü, güçlü/zayıf referans gibi temel kavramları iyi anladığınızı gösteremezseniz, bu büyük bir tehlike işaretidir. Bellek yönetimi ile ilgili her türlü soruya hazırlanmak için ARC perdesinin arkasındaki temel mekanizmayı anlamak çok önemlidir.

Görüşme soruları

  • ARC'nin Obj-C/Swift'te nasıl çalıştığını açıklayın
  • Bellek sızıntısına yol açabilecek yaygın durumlar nelerdir?
  • Referans döngüsünün meydana gelebileceği bazı yaygın senaryolar nelerdir?
  • Copy özelliğini ne zaman kullanmalısınız? Hatalardan kaçınmanıza nasıl yardımcı olur?
  • Sahipsiz(güvenli olmayan) ve zayıf referans arasındaki farkı açıklayabilir misiniz?

iOS uygulamasındaki bellek yönetimi, bir referans sayma modeline dayalıdır. Yeni bir nesne başlattığınızda, yığında bellek ayrılır ve referans sayısı 1'e ayarlanır. Daha fazla nesne ona güçlü referans ayarladıkça referans sayısı artar.

Aksine, sahip nesne güçlü referanstan vazgeçerse, referans sayısı 1 azalacaktır. Referans sayısı sıfır olduğunda, sonuç olarak bellek yok edilecektir.

ARC özelliği ile kod derlerken, derleyici oluşturduğunuz referansları alır ve temeldeki bellek yönetim mekanizmasına otomatik olarak çağrılar ekler .

Güçlü, Zayıf ve Sahipsiz

Otomatik Referans Sayımı'nın (ARC) kullanıma sunulmasıyla birlikte, bir nesneye referans verirken yalnızca sahiplik türünü belirtmemiz gerekir.

  • Güçlü başvurular — başvurulan nesnenin, başvuru geçerli olduğu sürece bellekte kalmasını sağlar.
  • Referans verilen bir nesnenin ömrü üzerinde hiçbir etkisi olmayan zayıf referanslar .
  • Sahipsiz referanslar — sahipsiz bir referans, zayıf referans gibi güçlü bir tutuş sağlamaz
  • Referans verilen nesne yeniden tahsis edildiğinde, zayıf referans sıfıra ayarlanırken, sahipsiz referans sarkan bir işaretçi olur ve ona bir mesaj göndermek bir çökmeye neden olur
  • Sahipsiz, diğer örnek aynı veya daha uzun ömre sahip olduğunda kullanılır
  • Sahipsiz referansın her zaman bir değere sahip olması beklenir, bu nedenle ARC bunu hiçbir zaman sıfır olarak ayarlamaz
  • nesneleri tutmak için güçlü kullanın — tutma anahtar sözcüğü eşanlamlı olsa da, bunun yerine güçlü kullanmak en iyisidir
  • nesneyi tutmadan yalnızca bir işaretçi istiyorsanız zayıf kullanın — koruma döngülerinden (yani delegelerden) kaçınmak için kullanışlıdır — nesne serbest bırakıldığında işaretçiyi otomatik olarak sıfırlar
  • primatlar için atamayı kullanın — tam olarak zayıf gibi, ancak serbest bırakıldığında nesneyi sıfırlamıyor (varsayılan olarak ayarlanmıştır)

ARC'nin arkasındaki referans kodlama hakkında iyi bir anlayışa sahipseniz, referans döngüsü fikrini kavramak gerçekten kolay olacaktır. İki nesne güçlü bir referans çemberi ile birbirine bağlıysa, başka güçlü referans olmasa bile birbirlerini canlı tutacaklardır.

Kapatma/Bloktaki Referans Döngüleri

Güçlü referans döngüsünün sunulabileceği yaygın durumlardan biri, kapatma/blok kullanımıdır. Bir sınıf örneğinin özelliğine bir kapatma/blok atarsanız ve bu kapatmanın/bloğun gövdesi örneği(self) yakalarsa, güçlü bir referans döngüsü oluşabilir. Bir özelliğe atamadan yeni bir blok oluşturursanız, bunun herhangi bir referans döngüsüne neden olmayacağını unutmayın.

- (void)configureBlock {
  // capture the weak reference to avoid the reference cycle
    XYZBlockKeeper * __weak weakSelf = self;

    self.block = ^{
    __strong typeof(self) strongSelf = weakSelf;
    if (strongSelf != nil) return;

        [strongSelf doSomething];   
    }
}

lazy var someClosure = { [weak self] in
    // closure body goes here
  guard let strongSelf = self else { return }
}

selfBir GCD kapanışında güçlü bir şekilde yakalama, asyncbir referans döngüsüne neden olmaz, ancak ömrünü uzatır Örneğinself. , bu arada kapatılmış bir görünüm denetleyicisinden bir ağ isteği yaparsanız, kapatma yine de çağrılır. Görünüm denetleyicisini zayıf bir şekilde yakalarsanız, olacaktır nil. Ancak, onu güçlü bir şekilde yakalarsanız, görünüm denetleyicisi, kapatma işini bitirene kadar canlı kalacaktır.

Objective-C'deki Özellikleri Kopyala

Uygulamada, NSString, NSArray gibi mutable versiyonu olan sınıflar için copy özelliğini kullanıyoruz. Mülkümüzün kendi kopyasını koruması için, orijinal değiştirilebilir değişken güncellendiğinde etkilenmeyecektir.

@interface XYZBadgeView : NSView

@property NSString *firstName;
@property NSString *lastName;

@end

// If you need to set a copy property's instance variable directly
- (id)initWithSomeOriginalString:(NSString *)aString {
    self = [super init];
    if (self) {
        _instanceVariableForCopyProperty = [aString copy];
    }
    return self;
}

- (void)example {
  NSMutableString *nameString = [NSMutableString stringWithString:@"John"];
  self.badgeView.firstName = nameString;
  
// If we don't create a copy then firstName will also be affected
  // Because it points to the same object as nameString
  [nameString appendString:@"ny"];
}