Objective-C

Objective-Cについて

投稿日:2018年3月12日 更新日:

 

イニシャライザ
  • Objectiv-cにはコンストラクターがありません。
  • その代わり、オブジェクトをインスタンス化した場合は、直後に init メッセージを送信しなければなりません。 この作業は自動的なものではなく、明示的にメッセージから呼び出さなければなりません。
  • 一般的には次のように記述されています。[[クラス名 alloc] init]。initメソッドの戻り値は、初期化を済ませたクラスインスタンスです。
  • init メソッドをオーバーライドすることで初期化処理を追加することができます。init メソッドをオーバーライドする場合は、スパークラスの init メソッドを呼び出す必要がある。
  • init メソッドは引数を受け取ることができません。引数が必要な場合は init メソッドとは異なるイニシャライザを作成する。指定イニシャライザと呼びます。指定イニシャライザは、習慣的に initWith から開始する引数を受けるメソッドとなります。
  • サブクラスでスーパークラスの指定イニシャライザをオーバーライドした場合、必ずスーパークラスの指定イニシャライザを呼び出す必要があります。1つのクラスが複数のイニシャライザを持つ場合は、その中の1つのイニシャライザだけが上位クラスの「init」を呼び出すようにして、ほかのイニシャライザは、「init」を呼んだ初期化メソッドを呼ぶようにする。
  • コンビニエンスコンストラクタ

 

インスタンス変数
  • インスタンスごとに違った値を保持する変数。通常クラス自身の外からアクセスされることはない
  • 以前は.hの@interfaceに記述していたが、いまは.mの@implementationに書くのが主流

 

メソッド
  • 引数が3つの場合の定義  - (戻り値の型)メッセージ式のメソッド名:(引数の型)引数1 ラベル:(引数の型)引数2 ラベル:(引数の型)引数3
  • ラベルは省略可能
  • 第一引数にラベルを付与することはできない
  • 引数はラベルの有無に関わらず,定義した順に指定しなければならない
  • 第一引数の前にあるのは 「メソッド名」 ではなく 「第一引数の説明」 だと解釈する
  • 戻り値の前に「マイナス(-)」がある場合は、インスタンスメソッドであることを示しています。「プラス(+)」を指定すると、クラスメソッドになります。
  • ラベルはメソッド名の一部。メッセージ式のメソッド名と引数のラベルを全て繋いだものが、Objective-Cが認識するメソッド名となる。

 

プロパティ
  • インスタンス変数にアクセス指定子を付けて宣言することで、インスタンス自身ではないオブジェクトからもアクセスできるようになる。
  • .hで宣言する際、@synthesize propertyName; と記述。特に指定がなければ、値の設定が可能なプロパティのインスタンス変数は 「_propertyName」という名前になる。Objective-Cでプロパティを宣言すると、暗黙的にインスタンス変数が自動生成されます。
  • インスタンス変数として別名を指定したい場合は、.mの@implementationに @synthesize propertyName = instanceVariableName; のように=に続けて指定する。

 

プロパティ属性
所有属性 strong

オーナーシップを持つ(参照カウントがincrementされる)

オブジェクト型のプロパティで指定可能。オブジェクトを強い参照で保持する。勝手にメモリから解放されてしまわないようにする

weak

オーナーシップを持たない(参照カウントがincrementされない)。オブジェクトが解放されるとnilを返す様になる。

オブジェクト型のプロパティで指定可能。オブジェクトを弱い参照で保持する。メモリから解放されてしまう場合がある。その場合はnilが代入される。

copy

コピーに対してオーナーシップを持つ(setterに渡されたオブジェクトのコピーを作るため、元のオブジェクトとは違うオブジェクトを持つ)

オブジェクト型のプロパティで指定可能。オブジェクトを強い参照で保持することはstrongと同様だが、保持するインスタンスは受け取ったインスタンスをコピーしたものになる。

unsafe_unretained retain(strongと同じ意味)せずに参照を持つ。weakが無い時代に使われた。今となっては歴史的経緯で残ってるだけのやつで、使っちゃダメ。
assign

intやBOOLみたいなプリミティブな値を保持する際に使われる。単純な代入を意味していて、オブジェクトに対して指定すると単なる参照の代入なので要はunsafe_unretainedとかと同じ。これもオブジェクトに対しては使っちゃダメ。

NSIntegerやBOOLなどプリミティブな型のプロパティに指定

retain strongと同じ。完全に歴史的経緯で残ってるだけなのでやっぱり使っちゃダメ。
スレッドセーフ(アトミック) atomic

プロパティをスレッドセーフにする(複数のスレッドが同時並行的に実行しても問題が発生しないこと)。プロパティに複数の処理が同時にアクセスしても”lock”、”unlock”機能が働き、一つずつしか処理されない。getter と setter が排他的に実行されるようになり、値の書き込みに複数のメモリ操作命令が必要な型(構造体など)が中間状態で読み出されることがなくなる

aonatomic スレッドセーフにしない。nonatomicを指定すると「このアクセサメソッドは同時に実行されることはないから、ロックしなくていい」ということをコンパイラに示していることになる。
アクセス制御 readonly 読み取り専用にする
readwrite 読み書き可能にする
アクセサー名の指定 getter= ゲッターの名前を自分で指定
setter= セッターの名前を自分で指定

 

strong/weekの使い分け

 

 

 

atomic/nonatomicの使い分け
  • できる限り nonatomic を指定する
  • 参照型: メモリアドレスのみの書き込みなので、常にnonatomicでよい
  • プリミティブ型: int, BOOL等ワンステップでの書き込みが可能: 常にnonatomicでよい
  • プリミティブ型: 単一のスレッドからしかアクセスされない: 設計に気をつけつつnonatomic推奨
  • プリミティブ型: 複数のスレッドからのアクセスがあり、long,構造体などサイズの大きい値: atomic推奨

 

クラス拡張
  • 実装ファイル(.mファイル)の方で@interfaceを宣言する。
  • ヘッダに公開したくないプライベートメソッドやインスタンス変数を隠蔽する記述が可能になる。
  • C++でいうところのpimplイディオム的なものだと考える。
 
変数のスコープ定義について
  • Objective-Cではアクセス権に関するコンパイラディレクティブ(@〜)を使う事でインスタンス変数のアクセス権をコントロールする
  • @private クラス外部からはアクセスできません。完全に隠蔽された状態です。インスタンス変数をクラス内だけで利用する場合に指定します。
  • @protected クラス内部およびサブクラス内であればアクセスできます。デフォルトではこれが指定されています。
  • @public クラス外部からも自由にアクセスできます。完全に公開された状態です。

 
インスタンス変数の宣言場所
  • ヘッダファイル(.hファイル)内の @interface に記述。.hファイル内に隠蔽したいインスタンス情報が記述されるので、推奨していない記述方法。
  • 実装ファイル(.mファイル)内の @interface に記述(クラス拡張)。StoryboardとOutletの接続を行う場合に記述する方法。実装ファイル(.mファイル)内の @:implementation でも可能だが、@:implementation に記述すると、Storyboardの当該箇所にこのインスタンス名がすぐには表示されない問題がある。そのため、実装ファイル(.mファイル)内の @interface に記述する。
  • 実装ファイル(.mファイル)内の @:implementation に記述。隠蔽したいインスタンス変数の宣言を記述する。
 
プロパティとメソッドのスコープ
  • Objective-Cでは、他のクラスからプロパティへのアクセスやメソッドの呼び出しを行えるようにするために、それらの宣言をヘッダーファイルに記載します。
  • ヘッダーファイルに宣言されたプロパティやメソッドは全て他のクラスから参照できる状態(Public)されてしまいます。
  • Objective-Cにはプロパティやメソッドを非公開にするための言語的機能がありません。
  • プライベートで宣言したい場合は、クラス拡張機能で実装ファイルで宣言を行い、疑似的に非公開(Private)にすることが可能です。

 

 

参照させて頂いたページ

Objective-Cでの「プロパティ」「インスタンス変数」「ローカル変数」の違い

インスタンス変数と@propertyと@synthesizeを理解する    

Objective-Cでは、インスタンス変数をどこに宣言するのが正しいのか?

Objective-Cのクラスやプロパティ、特徴的なメソッドの使い方

Objective-Cのクラスやプロパティ、特徴的なメソッドの使い方 (3/3)

Objective-C のプロパティ属性のガイドライン

 

 

スポンサーリンク

スポンサーリンク

-Objective-C

執筆者:

関連記事

Objective-Cについて(続)

  セレクタ Objective-C コンパイラは、メソッドを特定する名前をコンパイル時に内部表現に変換します。 この、メソッドの内部表現をセレクタと呼び、メッセージの送受信の裏側では、このセレクタが ...