2012-10-25 10 views
8

Myślę, że zbliżam się do zrozumienia how Mono GC and ObjC ref counting live together.Dlaczego MonoTouch GC nie może zabić zarządzanych obiektów za pomocą refcount> 1?

Jak to działa jest to, że gdy rodzimy obiekt posiada licznik odniesienia 1, nie zapobiegają zarządzanej instancji z coraz śmieci zebrane. Gdy liczba odwołań wzrośnie powyżej 1, zapobiegamy odzyskiwaniu odpadów przez zarządzaną instancję.

Dzieje się tak dlatego, że obiekt zarządzany może zawierać stan użytkownika. W przypadku obiektów zarządzanych, które są odbiciem lustrzanym odpowiedniego natywnego obiektu (takiego jak zarządzana instancja UIView), MonoTouch wie, że instancja nie może zawierać żadnego stanu, więc gdy tylko żaden zarządzany kod nie odwoła się do zarządzanej instancji, GC może go zebrać. Jeśli zarządzana instancja jest wymagana na późniejszym etapie, po prostu tworzymy nową.

Więc jeśli tworzę CustomButton że dziedziczy UIButton, dodaj go jako podrzędny do mojego View, niech zarządzanego poślizg referencyjnej z zakresu, a następnie uruchomić GC, to udałoCustomButton nadal nie będzie kwalifikował się do kolekcji .

Dlaczego nie można go odebrać? Oczywiście, mógł on zarządzać właściwościami stanu jak np. , ale jeśli nie ma linku do niego z zarządzanych obiektów, kogo to obchodzi ten stan? Równie dobrze może zniknąć, dlaczego nie?

Mam na myśli jeden z możliwych powodów: subskrybowanie zdarzeń CustomButton nie utrzyma go przy życiu dla GC, więc gdy obiekt zostanie zebrany, zdarzenia przestaną strzelać. Może to spowodować nieoczekiwane zachowanie.

Czy to prawda? Czy istnieją inne powody, dla których utrzymany obiekt jest żywy, nawet jeśli nikt go nie łączy?

Odpowiedz

6

Dlaczego nie można go odebrać? Oczywiście mógł on zarządzać właściwościami stanu, ale jeśli nie ma linku do niego z zarządzanych obiektów, kogo to obchodzi ten stan? Równie dobrze może zniknąć, dlaczego nie?

Kod macierzysty może zawierać odniesienia do obiektu, co może spowodować ponowne pojawienie się obiektu w kodzie zarządzanym później.

wierzę przykładowy kod będzie zilustrować, co by się stało:

class MyView : UIView { 
    public string ImportantSecret; 
} 

class AppDelegate : UIApplicationDelegate { 
    UIViewController vc; 
    public override bool FinishedLaunching (UIApplication app, 
              NSDictionary options) 
    { 
     var myView = new MyView(); 
     myView.ImportantSecret = "MonoTouchRocks"; 

     vc = new UIViewController(); 
     vc.View = new UIView(); 
     vc.View.AddSubView (myView); 

     // When this method returns the only place where myView is referenced 
     // is from inside the *native* Subviews collection. 

     BeginInvokeOnMainThread (() => 
     { 
      Console.WriteLine (((MyView) vc.Subviews [0]).ImportantSecret); 
      // If the MyView instance was garbage collected and recreated 
      // automatically at this point, ImportantSecret would be null. 
     }); 
    } 
} 

Ważne: ten kod jest tylko do zilustrowania dlaczego GC nie może zbierać zarządzanych obiektów, które mogą mieć stan. Ta konkretna próbka właściwie nie zapomni ważnego sekretu, ponieważ tablica Subviews jest automatycznie buforowana w kodzie zarządzanym - ale nie jest to generalnie prawdą.

+0

Wreszcie dostaję! Twoje wsparcie tutaj było niezbędne. –

+1

Uwielbiam twoje dwa pytania i świetne odpowiedzi Rolfa - nauczyłem się czegoś nowego :-) –

+0

Bawiłem się z tym. Co się stanie, jeśli zmienna myView zostanie utworzona w bloku używającym? Narzędzie Instrumenty wskazuje, że instancje zostaną zwolnione. Czuje się bardzo niezręcznie, ale nie mogę zidentyfikować i problemów w zachowaniu kodu. Myśli? @rolf –

Powiązane problemy