シングルトンを書くのは初めてで、現在のiOSプロジェクトではシングルトンを使用する必要があります。要件の1つは、それを殺すことができるということです。これはシングルトンの設計に反することは知っていますが、これは実行する必要がある/実行できることですか?
7 に答える
もちろん可能ですが、作成して不要なときにリリースできるオブジェクトを探している場合は、通常のオブジェクトのように聞こえます。:)
一般的に、シングルトンは独自のライフサイクルを制御します。ここでは、2つの要件(1つはシングルトンを使用すること、2つは自由にリリースできること)、および両方があなたのケースで意味をなす理由について詳しく説明しない限り、一方的な議論を行うことになります。
シングルトンが本質的に一意である他のリソース(ファイルリソースやネットワーク接続など)をラップしていることが原因である可能性があります。これが当てはまる場合、通常、シングルトンはそのリソースの「マネージャー」であり、シングルトンのインターフェースを介してそのリソースの制御を公開します。
または、シングルトンオブジェクトが大量のメモリ(ある種のバッファ)を保持しているためである可能性があり、必要に応じてそれがフラッシュされることを確認する必要があります。この場合、必要に応じてメモリを作成および解放する各メソッドについて賢くすることができます。または、シングルトンにメモリ不足システムの通知をリッスンさせて適切に動作させることができます。
基本的に、シングルトンオブジェクト自体をリリースすることが本当に理にかなっているケースを構築するのは難しいでしょう。単一の基本オブジェクトはメモリ内でほんの一握りのバイトしか使用せず、ぶらぶらして誰も傷つけません。
これはシングルトンの設計に反することを私は知っています
また、Objective-Cの通常のメモリ管理パターンにも反します。通常、オブジェクトは、破壊されないように別のオブジェクトを保持し、オブジェクトを解放してオブジェクトを破壊できるようにします。ただし、オブジェクトを明示的に破棄することは、他のオブジェクトが行うことではありません。
オブジェクトAがシングルトンクラスSの共有インスタンスS1を取得するとどうなるかを考えてください。AがS1を保持している場合、クラスメソッドがSを解放し、共有インスタンスを指すグローバル変数をnilに設定しても、S1は存在し続けます。クラスが後で新しい共有インスタンスS2を作成すると、Sの2つのインスタンス、つまりS1とS2が存在します。これは、最初にシングルトンを定義するプロパティに違反します。
-retain
この問題は、オーバーライドしてスウィズリングすることで回避できる可能性がありますが-release
、そもそも存在してはならない問題を解決するには、非常に複雑に思えます。
考えられる代替策は、共有オブジェクトを破棄するのではなく、リセットすることです。必要に応じて、すべての属性を既知の(おそらく無効な)状態に設定してから、クラスメソッドで共有オブジェクトを再初期化することができます。共有オブジェクトを使用している可能性のあるオブジェクトに対するこれらすべての影響に注意してください。
私がこれまでに書いたほぼすべてのシングルトン(完全にUI中心のコントローラーを除く)は、シングルトンではないようにリファクタリングされることになります。毎日。独身。1。
したがって、私はシングルトンを書くのをやめました。通常のクラスと同じように、インスタンスで状態を維持するクラスを作成し、他のインスタンスから分離して作成します。通知が多い場合は、常にself
通知オブジェクトとして渡されます。彼らには代表者がいます。それらは内部状態を維持します。彼らは真にグローバルな状態の外のグローバルを避けます。
そして、多くの場合、私のアプリにはそのクラスのインスタンスが1つだけ存在する可能性があります。その1つのインスタンスはシングルトンのように機能し、実際、アプリのデリゲートまたはクラスメソッド(名前が付けられることもあります)を介して、それを取得するための便利な方法を作成することもできますsharedInstance
。
このクラスには、通常2つに分割される分解コードが含まれています。後で復元するために現在の状態を保持するコードと、インスタンスに関連付けられたリソースを解放するコード。
シングルトンのように便利です。必要に応じて複数のインスタンス化を行う準備ができています。
もちろん問題ありません。新しいクラスメソッドを提供します:[MyClass killSingleton]; このメソッドはシングルトンを解放し、その内部参照をnilに設定します。次に誰かが[MyClasssharedSingleton]を尋ねたとき、あなたはそれを作成する前に行ったのと同じステップを実行します。
編集:実際には、昔はそのようなルーチンがrelease
セレクターをオーバーライドし、離れることを拒否する可能性がありました。したがって、以下の最初のコメントが示すように、これは静的スコープを持つオブジェクトです-オブジェクトの保持カウントを1に保つ静的変数を通じて存続します。ただし、新しいクラスメソッドを追加してそのivar(ARCの下)を削除し、それを解放することで、目的の結果が得られます。静的オブジェクトのインスタンス化と解放の制御は、クラスメソッドを介して完全に行われるため、保守とデバッグが簡単です。
シングルトンの概念に反しますが、ARCベースのプロジェクトでは次の方法で実装できます。
//ARC
@interface Singleton : NSObject
+ (Singleton *)sharedInstance;
+ (void)selfDestruct;
@end
@implementation Singleton
static Singleton *sharedInstance = nil;
+ (Singleton *)sharedInstance {
if (sharedInstance == nil) {
sharedInstance = [[Singleton alloc] init];
}
return sharedInstance;
}
+ (void) selfDestruct {
sharedInstance = nil;
}
@end
//This can be implemented using bool variable. If bool no create new instance.
@interface Singleton : NSObject
+ (Singleton *)sharedInstance;
@end
@implementation Singleton
static Singleton *sharedInstance = nil;
+ (Singleton *)sharedInstance {
if (!keepInstance) {
sharedInstance = [[Singleton alloc] init];
keepInstance = YES;
}
return sharedInstance;
}
@end
シングルトンをクリアする必要があったので、次のことを行うことになりました。
- (void)deleteSingleton{
@synchronized(self) {
if (sharedConfigSingletone != nil) {
sharedConfigSingletone = nil;
}
}
}
それが役に立てば幸い。