2016-06-03 17 views
1

Beschreibung + Probe + Erläuterung: (Sie können auf die Frage Abschnitt überspringen)Objective-C dynamische Implementierung

Ich mag würde eine Objektinstanz machen, die von verschiedenen Implementierungen realisiert werden kann, hängt davon ab, eine Zustand (der Internetstatus).

Einfache Erklärung

@interface LoginController : NSObject 

/** The currently logged-in User. Nil if not logged-in yet. */ 
@property (strong, nonatomic) User *currentUser; 

// Singleton object 
+ (instancetype)shareInstance; 

/** Abstract methods, will do nothing if call directly. Use inheritance implements (Online/Offline) instead. */ 
- (User *)loginByEmail:(NSString *)email password:(NSString *)pwd; 

@end 

@interface LoginControllerOnline : LoginController 
// Login will call request to server. 
@end 

@interface LoginControllerOffline : LoginController 
// Login will check data in coredata. 
@end 

Der Login-Methode des LoginController eigentlich nichts zu tun (return nil). Stattdessen überschreibt die geerbte Klasse (online/offline) die Methode der Eltern Login mit unterschiedlichen Implementierungen (wie in den Kommentaren)

Und dann habe ich einen Manager zu definieren, welche Klasse im Einsatz sein sollte:

@implement InternetManager 

+ (LoginController *)loginController 
{ 
    return [self hasInternet] ? [LoginControllerOnline shareInstance] : [LoginControllerOffline shareInstance]; 
} 

+ (BOOL)hasInternet 
{ 
    // Check with Reachability. 
} 

@end 

Diese Arbeit. Aber es ist nicht der Mechanismus, den ich gerne erreichen würde.

  1. Dieser Mittelwert I 2 Instanzen geerbt LoginController anstelle von 1.
  2. Wenn internetStatus Änderung offline-online, würde ich online erneut anmelden möchten (zu Sitzungs-/oauthToken zu bekommen ...). Aber, werde ich viele Dinge zu tun haben (Kopie Benutzer, beispielsweise ändern, überprüfen beibehalten ...), bevor ich tatsächlich von Login aufrufen können online

FRAGE:

Gibt es eine Möglichkeit für ich, um nur eine Instanz von LoginController zu erstellen, die die gleichen Eigenschaften (User) halten, aber kann verschiedene (dynamische) Implementierungen (Online/Offline) haben?

Update-Frage:

Zitat von Apple Dynamic typing:

Die isa Zeiger:

Jedes Objekt hat eine isa Instanzvariable, dass die Klasse des Objekts identifiziert. Die Laufzeit verwendet diesen Zeiger auf ermitteln die tatsächliche Klasse des Objekts, wenn es erforderlich ist.

Also, gibt es eine Möglichkeit für mich, diese isa pointer einer Objektinstanz zu ändern?

Antwort

3

Es klingt wie das eigentliche Problem ist, dass Sie diese Dinge direkten primären Besitz von Staat gegeben haben, die Sie eigentlich nicht wollen, dass sie besitzen - ausklammern. Es gibt kein Kopieren, nur geben Sie jedem eine Instanz der Sache, die Marshals bei -init sate und erlauben Sie ihnen, damit zu sprechen.

Dann tun Sie einfach die normale Programmierung, wenn Sie entweder das eine oder das andere auf der Grundlage einer Bedingung tun wollen: Verwenden Sie eine if Anweisung.

Also, ich denke nicht, die Verwendung der dynamischen Laufzeit ist angemessen.Aber akademisch vorausgesetzt, ein Interesse:

Wenn Sie wirklich müssen, verwenden Sie object_setClass, die "die Klasse eines Objekts", beantwortet Ihre tatsächliche Frage. Offensichtlich muss der Speicher kompatibel sein, daher sollten Ihre Unterklassen wahrscheinlich keine Eigenschaften oder Instanzvariablen deklarieren.

Eine allgemein diskutierte Alternative für diesen allgemeinen Bereich ist das Ändern der Klasse einer vorhandenen Instanz, aber das Ändern der Methoden, die ein Mitglied der Klasse sind. Sie hätten also zwei alternative Implementierungen von -loginByEmail:password: und legen fest, welche die Antwort auf diesen Selektor war. Aber es gibt wirklich keinen Vorteil gegenüber der Verwendung eines if, wenn Sie Zugriff auf den Quellcode haben und eine Reihe von Nachteilen rund um seine im Allgemeinen indirekte, undurchsichtige Natur. Das Ganze wird normalerweise als Swizzling bezeichnet. class_replaceMethod ist die Schlüsselkomponente, aber nur nach Swizzling suchen.