Learn iPhone, iOS, Objective-c, Swift, cocos2dx, Unity and ….?

iOSやAndroid開発でのエラー解決法や便利tipsのメモ

RSS Feed

Objective-C – Singleton(シングルトン)クラスの実装 –

0 Comments
Posted by Kuro on 2013/03/02

スポンサードリンク

Objectiv-Cでシングルトンクラスを作成するときの作法を調べてみました。

Apple公式Documentを参考にした実装

まずはAppleの公式Documentを参考にして実装してみます。
https://developer.apple.com/jp/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/chapter_3_section_10.html

そのままだと、releaseをオーバーライドしている箇所で以下のような警告が出ます。

“Warning: Conflicting distributed object modifiers on return type in implementation of ‘release'”

戻り値の型にonewayを追加すると解決しました。

親クラスのメソッドがonewayを指定している場合、子クラスでも同様の指定にする必要があるようです。
Xcode4.2以前はコンパイラーのチェックが緩かったので警告が出なかっただけだそうです。
参考サイト:http://stackoverflow.com/questions/7379470/singleton-release-method-produces-warning

onewayの意味なのですが、メソッドが非同期メッセージとして扱われるだとかなんとかだそうです。
参考サイト:http://d.hatena.ne.jp/Kazzz/20120116/p1

@synchronizedは複数スレッドからアクセスされた場合でもシングルトン状態を維持できるようにするためのキーワードです。

sharedManager内でインスタンスを代入しないのは[[SingletonClass alloc] init]という呼び方をされてもシングルトン状態が保たれるようにするためです。
allocメソッドは内部でallocWithZoneを呼びメモリ領域を確保します。
このメソッドをオーバーライドすることでシングルトンを強制させることができます。

あとはretainやreleaseもオーバーライドして何もしないようにします。

dispatch_onceを使用した実装

iOS4から追加されたGCD(Grand Central Dispatch)という機能のひとつであるdispatch_onceを使ってみます。

dispatch_onceのブロック内での処理はアプリケーションのライフタイムで一度しか呼ばれないことが保証されます。
また、@synchronizedと同様に複数スレッドからアクセスされた場合でもシングルトン状態を維持でき、こちらのほうが処理が速いです。

参考サイト:
http://objective-audio.jp/2009/09/grand-central-dispatch-block.html
http://cocoasamurai.blogspot.jp/2011/04/singletons-your-doing-them-wrong.html

ARC環境での実装

ARCの場合はretainやreleaseを気にする必要がありません。
Creating iOS 5 Apps: Develop and Designで紹介されていた方法がもっとも簡潔だったのでこれを参考にサンプルコードを書いてみました。

この実装方法の特徴は外部からinitメソッドが呼ばれたらエラーになるようにしていることです。
こうすることでsharedManagerを呼ばずにインスタンスを生成してしまうことを防いでいます。

動作確認用コード

3種類の実装方法を紹介しましたが、それぞれsharedManagerを通さずに[[SingletonTest alloc] init];と呼び出してしまったときの対処法が違います。

C++やJavaはコンストラクタをprivateにすることができるのですが、Objective-CではできないのでallocWithZoneまたはinitをオーバーライドすることで対処しています。

nilを返すかSingletonのインスタンスを返すかエラーにするかの違いです。

呼んでほしくない方法で呼ばれてしまったのならそれと分かるようなメッセージを付けてエラーを返してあげるのが親切でしょうか。

cocos2dのSingleton (追記)

cocos2dのCCDirectorクラスを見てみると、allocメソッドをオーバーライドして2度目の呼び出しにはエラーを吐くようにしていました。

release等が呼ばれたときの処理は特に書かれていませんでした。
ちなみにallocWithZoneを使えば一応インスタンスの生成はできてしまいます。

スポンサードリンク


You can leave a comment, or trackback from your own site.

0 Comments

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

Pingbacks / Trackbacks

スポンサードリンク

Popular Posts