woshidan's loose leaf

ぼんやり勉強しています。

Objective-Cの基礎を少しまじめに復習した

一週間経って忘れているところがかなりあったので、二回目の予習前に復習しました。
そして、無名カテゴリとクラス拡張の違いはよくわからないことが判明しました。

内容

  • ショートカットキーのおさらい
    • Cmd+G - 検索において該当した次の検索結果へ移動
    • Shift+Cmd+G - 検索において該当した一つ前の検索結果に移動
    • Cmd+R - 実行
    • Cmd+B - ビルド
    • Cmd+T - テスト
  • Objective-Cの基礎のおさらい

ショートカットキーのおさらい

http://www.iosjp.com/dev/archives/92

Cmd+G

検索において該当した次の検索結果へ移動する

Shift+Cmd+G

検索において該当した一つ前の検索結果に移動する

Cmd+R

実行する

Cmd+B

ビルドする

Cmd+T

テストを実行する

Objective-Cの基礎のおさらい

Objective-C、一週間ぶりにやったら割と忘れていたので、 復習するたびに(それこそ10分くらいでできるまで)毎週やればいいんじゃないかな、と思いました。

メソッドに関して

NSmutable... オブジェクトに後から追加するメソッド

NSmutableStringに後から文字列を追加
[mutableString appendString:@"World"];

NSMutableArrayとまざってadd...かと思っていました。

NSMutableArrayの要素を追加
[mutable addObject:str1];

上同。

MSMutableDictionaryの要素を追加
mutableDict[key] = value;

上同。ちょっとややこしいと思います。

変数を宣言するときに初期値を設定しない場合は、右辺に[ObjectName obj];をしている気がする。

NSIntegerからNSNumberへ型変換

@(i); // i ... NSInteger

メソッドの定義の時の戻り値

そのクラスのインスタンスを返す場合は、(instancetype)
何も返さない時は(void)
文字列等を返す時は(NSSString *)

メソッド定義のとき引数を何も持たない時

メソッド名の後に何も書かない

- (void)methodName {
  // メソッドの中身
}

用語や文法の確認

復習の時は余裕があったのでまじめに確認しました。
https://developer.apple.com/jp/documentation/ObjC.pdf

レシーバーとメッセージ

前のときのメモでは「aオブジェクトのbメソッドを呼び出す」としていた部分を、 Objective-Cでは「レシーバーaにbというメッセージを送る」というみたいです。

bを実行してよというメッセージを送ってaというオブジェクトに動いてもらうという考え方です。

[obj method]というより
[receiver_obj message]のほうが適切で、[]の中の部分をメッセージ式と言います。

メッセージ式のメソッド名は、どのメソッドを(何の引数で)実行するかを選択する役割を果たすため、しばしばセレクタと呼ばれます。

インターフェイスファイル(.h),実装ファイル(.m)

インターフェイスの宣言

@interface ClassName : ItsSuperclass
// メソッド宣言、プロパティ宣言。
@end

カテゴリ

基本的にインターフェイスファイルに書いたあと、実装ファイルに書きます。

既にある(自分がソースを持っていない)クラスにメソッドを追加したい場合、カテゴリという機能を使うみたいです。

@interface メソッドを追加したいクラスの名前 (追加したいメソッドのカタマリつける名前(カテゴリ名))
  // メソッドの宣言
@end

という風にインターフェイスファイルに書いて

@implementation メソッドを追加したいクラスの名前 (カテゴリ名)
  // 宣言したメソッドの実装
@end

を実装ファイルに書きます。rubyでどこでも

class String
  def someMethod
    return "Hello"
  end
end

という風にクラスにメソッドが追加できますが、そんな感じなのでしょうか?

無名カテゴリ

カテゴリー名をいれずに@implementationのブロックを書くことができますが、
この書き方を無名カテゴリと言って、この中にメソッドを書くと擬似的なプライベートメソッドとして扱うことが出来ます。

実装ファイル

@interface ClassName ()
  //  擬似的なプライベートメソッドとして使いたいメソッドの宣言
@end
@implementation ClassName ()
  //  擬似的なプライベートメソッドとして使いたいメソッド
@end

予習のときに調べたクラス拡張は無名カテゴリの勘違いかと、さらに気になって調べたんだけど、

[Objective-C] クラス拡張と無名カテゴリ - Qiita

によると、クラス拡張も実装ファイルに

@interface ClassName ()

@end

と書き出すので非常に似て見えるんですが、

https://developer.apple.com/jp/documentation/ObjC.pdf

によると、

クラス拡張は匿名のカテゴリに似ていますが、宣言するメソッドを対応するクラスのメイン @implementationブロックで実装しなければならない点が異なり

だそうです。

匿名のカテゴリ(無名カテゴリ)についての説明がマニュアルを検索してみても見つからず、よく分からないのですが、
なんだか、クラス拡張は最初のメソッドの宣言部を

@interface MyClass () {
    float value;
}
- (void)setValue:(float)newValue;
@end

のように{}で囲ってあるのは気のせいでしょうか。
そして、{}で囲まれている部分は宣言されていなくてもエラーが出るとは書いていなかったり、@implementationのブロックで宣言されていなかったりするのが気になるのですが、まあ、書いて慣れていけばいいのでしょうか。