Informazioni di base (definizione di classe contro un'istanza di classe)
Il concetto importante è la differenza tra una definizione di classe e un'istanza di classe.
La definizione di classe è il codice sorgente per la classe. Ad esempio ViewController.m
contiene la definizione per la classe myViewController
e AppDelegate.m
contiene la definizione per la classe AppDelegate
. L'altra classe menzionata nella tua domanda è UIApplication
. Questa è una classe definita dal sistema, cioè non hai il codice sorgente per quella classe.
A un'istanza di classe è un blocco di memoria sull'heap e un puntatore a tale memoria. Un'istanza di classe è in genere creato con una riga di codice come questo
myClass *foo = [[myClass alloc] init];
noti che alloc
riserve spazio sul mucchio per la classe, e quindi init
imposta i valori iniziali per le variabili/proprietà della classe. Un puntatore all'istanza viene quindi archiviato in foo
.
Quando l'applicazione viene avviata, la seguente sequenza di eventi si verifica (grosso modo):
- il sistema crea un'istanza della classe UIApplication
- il puntatore all'istanza UIApplication è memorizzato da qualche parte in un variabile di sistema
- il sistema crea un'istanza della classe AppDelegate
- il puntatore alla AppDelegate viene memorizzato in una variabile denominata
delegate
nel caso UIApplication
- il sistema crea un'istanza della classe MyViewController
- il puntatore alla classe MyViewController è memorizzato da qualche parte
Lo stoccaggio del puntatore per MyViewController è dove le cose si fanno disordinato. La classe AppDelegate ha una proprietà UIWindow chiamata window
. (Puoi vederlo in AppDelegate.h.) Se l'app ha solo un controller di visualizzazione, il puntatore a quel controller di visualizzazione viene archiviato nella proprietà window.rootViewController
. Ma se l'app ha più controller di vista (sotto un UINavigationController o un UITabBarController) le cose si complicano.
Il codice di spaghetti soluzione
Quindi il problema che si faccia è questa: quando il sistema chiama il metodo applicationDidEnterBackground
, come si fa a ottenere il puntatore al controller della vista? Bene, tecnicamente, il delegato dell'app ha un puntatore al controller della vista da qualche parte sotto la proprietà window
, ma non esiste un modo semplice per ottenere quel puntatore (supponendo che l'app abbia più di un controller di visualizzazione).
L'altro thread ha suggerito un approccio al codice spaghetti al problema. (Si noti che l'approccio spaghetti code è stato suggerito solo perché l'OP in questo altro thread non ha voluto fare le cose in modo corretto con le notifiche.) Ecco come funziona il codice di spaghetti
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.myViewController = self;
Questo codice recupera il puntatore alla UIApplication istanza creata dal sistema, quindi esegue una query sulla proprietà delegate
per ottenere un puntatore all'istanza AppDelegate. Il puntatore a self
, che è un puntatore all'istanza MyViewController, viene quindi archiviato in una proprietà in AppDelegate.
Il puntatore all'istanza MyViewController può quindi essere utilizzato quando il sistema chiama applicationDidEnterBackground
.
La soluzione corretta
La soluzione corretta è quella di utilizzare le notifiche (come nella risposta di kkumpavat)
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
}
- (void)didEnterBackground
{
NSLog(@"Entering background now");
}
-(void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
con le notifiche, non si memorizzare i puntatori ridondanti per i controller di vista, e si non devi capire dove il sistema ha memorizzato il puntatore al tuo controller di visualizzazione. Chiamando addObserver
per il UIApplicationDidEnterBackgroundNotification
stai dicendo al sistema di chiamare direttamente il metodo didEnterBackground
del controller di visualizzazione.
Grazie mille! Risposta molto completa! –