Obj-C Bellek Yönetimi

Bellek yönetimi, herhangi bir programlama dilinde en önemli süreçlerden biridir. Gerektiğinde nesnelerin belleğinin tahsis edildiği ve artık gerekmediğinde ayrıldıkları süreçtir.

Nesne belleğini yönetmek bir performans meselesidir; bir uygulama gereksiz nesneleri serbest bırakmazsa, bellek ayak izi büyür ve performansı düşer.

Objective-C Bellek yönetimi teknikleri genel olarak iki türe ayrılabilir.

  • "Manuel Tutma Bırakma" veya MRR
  • "Otomatik Referans Sayma" veya ARC

"Manuel Tutma Bırakma" veya MRR

MRR'de, nesneleri kendi başımıza takip ederek belleği açıkça yönetiriz. Bu, NSObject Foundation sınıfının çalışma zamanı ortamı ile birlikte sağladığı referans sayma olarak bilinen bir model kullanılarak uygulanır.

MRR ve ARC arasındaki tek fark, alıkoyma ve bırakma işleminin bizim tarafımızdan elle yapılırken, ikincisinde otomatik olarak halledilmesidir.

Aşağıdaki şekil, bellek yönetiminin Objective-C'de nasıl çalıştığına dair bir örneği temsil etmektedir.

A Sınıfı nesnenin bellek yaşam döngüsü yukarıdaki şekilde gösterilmektedir. Gördüğünüz gibi, tutma sayısı nesnenin altında gösterilir, bir nesnenin alıkoyma sayısı 0 olduğunda, nesne tamamen serbest bırakılır ve diğer nesnelerin kullanması için belleği serbest bırakılır.

A Sınıfı nesne ilk olarak NSObject'te bulunan tahsis / init yöntemi kullanılarak oluşturulur. Şimdi, tutma sayısı 1 olur.

Şimdi, B sınıfı, A Sınıfı Nesnesini korur ve A Sınıfı nesnesinin tutma sayısı 2 olur.

Daha sonra, C Sınıfı nesnenin bir kopyasını oluşturur. Şimdi, örnek değişkenleri için aynı değerlerle A Sınıfının başka bir örneği olarak oluşturulur. Burada tutma sayısı 1'dir ve orijinal nesnenin tutma sayısı değildir. Bu, şekildeki noktalı çizgi ile temsil edilmektedir.

Kopyalanan nesne, serbest bırakma yöntemi kullanılarak Sınıf C tarafından serbest bırakılır ve tutma sayısı 0 olur ve dolayısıyla nesne yok edilir.

İlk A Sınıfı Nesne durumunda, alıkoyma sayısı 2'dir ve imha edilmesi için iki kez serbest bırakılması gerekir. Bu, tutma sayısını sırasıyla 1 ve 0'a düşüren Sınıf A ve Sınıf B'nin serbest bırakma beyanları ile yapılır. Sonunda nesne yok edilir.

MRR Temel Kuralları

  • Oluşturduğumuz herhangi bir nesneye sahibiz: Adı "tahsis", "yeni", "kopya" veya "mutableCopy" ile başlayan bir yöntemi kullanarak bir nesne oluşturuyoruz.

  • Ret'i kullanarak bir nesnenin sahipliğini alabiliriz: Alınan bir nesnenin normalde alındığı yöntem dahilinde geçerliliğini koruması garanti edilir ve bu yöntem aynı zamanda nesneyi güvenli bir şekilde çağıran kişiye iade edebilir. Muhafazayı iki durumda kullanırız -

    • Bir erişimci yönteminin veya bir init yönteminin uygulanmasında, bir nesnenin sahipliğini almak için bir özellik değeri olarak depolamak istiyoruz.

    • Bir nesnenin başka bir işlemin yan etkisi olarak geçersiz kılınmasını önlemek için.

  • Artık ona ihtiyacımız kalmadığında, sahip olduğumuz bir nesnenin sahipliğini bırakmalıyız: Bir nesnenin sahipliğini, ona bir sürüm mesajı veya bir otomatik bırakma mesajı göndererek bırakırız. Cocoa terminolojisinde, bir nesnenin sahipliğinden vazgeçme bu nedenle tipik olarak bir nesneyi "serbest bırakmak" olarak adlandırılır.

  • Sahip olmadığınız bir nesnenin mülkiyetinden vazgeçmemelisiniz: Bu, açıkça ifade edilen önceki politika kurallarının yalnızca bir sonucudur.

#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;
}

Yukarıdaki programı derlediğimizde aşağıdaki çıktıyı alacağız.

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

"Otomatik Referans Sayma" veya ARC

Otomatik Referans Sayma veya ARC'de, sistem MRR ile aynı referans sayma sistemini kullanır, ancak uygun bellek yönetimi yöntemini bizim için derleme zamanında çağırır. Yeni projeler için ARC'yi kullanmamız şiddetle tavsiye edilir. ARC kullanırsak, bu belgede açıklanan temel uygulamayı anlamaya genellikle gerek kalmaz, ancak bazı durumlarda yardımcı olabilir. ARC hakkında daha fazla bilgi için bkz . ARC Sürüm Notlarına Geçiş.

Yukarıda belirtildiği gibi, ARC'de, derleyici tarafından halledileceği için sürüm ve tutma yöntemleri eklememiz gerekmez. Aslında, Objective-C'nin altında yatan süreç hala aynı. Saklama ve bırakma işlemlerini dahili olarak kullanır ve geliştiricinin bu işlemler hakkında endişelenmeden kod yazmasını kolaylaştırır, bu da hem yazılan kod miktarını hem de bellek sızıntısı olasılığını azaltır.

MRR ile birlikte Mac OS-X'te kullanılan çöp toplama adlı başka bir ilke vardı, ancak OS-X Mountain Lion'da kullanımdan kaldırıldığından beri MRR ile birlikte tartışılmadı. Ayrıca, iOS nesneleri hiçbir zaman çöp toplama özelliğine sahip değildi. Ve ARC ile, OS-X'te de çöp toplama kullanımı yoktur.

İşte basit bir ARC örneği. ARC'yi desteklemediği için bunun çevrimiçi derleyicide çalışmayacağını unutmayın.

#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;
}

Yukarıdaki programı derlediğimizde aşağıdaki çıktıyı alacağız.

2013-09-28 04:45:47.310 demo[8385] Hello, World!
2013-09-28 04:45:47.311 demo[8385] Object deallocated