[Objective-C] ハマったメモ


なんか細々とハマったことをメモ。
随時更新中。

------------------------------------------

##クラス編

まだまだ理解不足です・・。

###superが呼べない

スーパークラスの非公開メソッドを上書きしたくて、同じメソッド名で定義を行い、内部で`[super anyMethod]`を叩こうとしたら`super`にアクセスできなかった。
冷静に考えれば当たり前だけど、メソッドの場合はprivateやpublicみたいなのを明示していないので「あれ？」となったのでメモ。

------------------------------------------

##メモリ管理編

###UIViewControllerの`touchesBegan:withEvent:`が呼ばれない！

こちらの記事を見て解決。
[UIViewControllerのtouchesBeganとかtouchesEndedが上手く機能しなかったと思ったら・・・](http://akisute.com/2009/10/uiviewcontrollertouchesbegantouchesende.html)

おそらくオブジェクトが破棄？されてしまって動かないのかな。
ARCオフを知らないと問題だと思ったので、ARCオフでごにょごにょしていたらハマった。
必要ないと思って、UINavigationController#initWithRootViewControllerにUIViewControllerを渡したあとに`release`を呼んでいたのが原因だった。

以下のようにするとOK。

```objc
ViewController *vc = [[ViewController alloc] init];
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:[vc retain]];
[vc release];
```

同様の問題として、UINavigationViewControllerなども破棄されてしまうと、戻るボタンとかで戻った際に関連するViewController周りも解放されてしまっておかしくなる。
（とはいえ、普通はインスタンス変数に保持しておくはずだから、問題になることはないはず）

###(void *)型とid型とのキャスト

ARC環境下では(void *)型とid型との間で普通のキャストが行えない（コンパイルエラーとなる）。
ARC環境でこれを行うにはbridgeキャストを利用する。
具体的には

```objc
// (void *)型にキャスト
NSString *sammple = @"sample";
[anyObject someMethod:(__bridge void *)sample];
```

```objc
// NSString型にキャスト
NSString *sample2 = (__bridege NSString *)sample;
```

##Xcode編

###Could not launch APP_NAME failed to get the task for process XXXX

上記エラーが出てハマった。
特に、調べて出てくる問題では解決できなくて（code signingがdestributionになってるうんぬん）
色々設定を変えてみたら、該当ターゲットの設定で「General > Identity > Team」が変わってしまっていた。これの何が原因かは分からないのだけど、とりあえず「None」にしたら起動できたのでよしとする。

###targetの切り替え

targetを切り替えて開発をしていると、いくつかの設定をtargetごとに設定しないとならない。（例えばARCのフラグとか）
また、新規作成したファイルの`Target Membership`を適切に設定しないと、現在対象としているtargetでファイルがなくてビルドエラーになったりするので注意。

##実装編

###`hoge.m`をimportするとLinkerエラー

なんでか間違えてヘッダではなく実装ファイルをimportしていた。
そのせいでLinkerエラーが出ていた。作成したばかりのファイルだったので困惑したけどただの間違いでした。

###UITableViewの下にUIViewを固定配置

UITableViewControllerを使っていて、画面下部に特定のボタンを固定配置しようとしてハマった。
調べていたら[この記事（UITableViewをカスタマイズしたいならUITableViewControllerを使わないほうがいい）](http://j7lg.tumblr.com/post/7292520181/uitableview-uitableviewcontroller)に記載があった。

どうも、UITableViewControllerを使うと、最初のsubviewを引き伸ばす、という処理が行われる模様。
この引き伸ばす処理が行われるのは`viewWillAppear`と`viewDidAppear`の間の模様。

なので、`viewDidAppear`メソッド内に固定配置する処理を入れたら動いた。

```objc
- (void)viewDidAppear:(BOOL)animated
{
    CGFloat buttonHeight  = 44.0f;
    CGFloat contentHeight = self.view.frame.size.height - buttonHeight;
    self.tableView.frame = CGRectMake(0, 0, self.tableView.frame.size.width, contentHeight);
    UIView *fixedView = [[UIView alloc] initWithFrame:CGRectMake(0, contentHeight, self.view.frame.size.width, buttonHeight)];
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, 250, buttonHeight)];
    label.textColor = [UIColor whiteColor];
    label.text = @"test";
    label.font = [UIFont fontWithName:@"Helvetica" size:16];
    label.backgroundColor = [UIColor blueColor];
    [fixedView addSubview:label];
    fixedView.backgroundColor = [UIColor grayColor];
    [self.view.superview addSubview:fixedView];
}
```


###layoutSubviews in viewController

**layoutSubviewsは、ViewControllerのviewでのみ実行される**

画面の回転時などで再layoutが必要なとき、`layoutSubviews`メソッドが呼ばれるのはViewControllerのviewのみ。UIViewController#view#subviewsのほうのレイアウト調整をしたい場合は、明示的にsubviewsの`setNeedsLayout`メソッドを呼んでやる必要がある。

ちなみに回転を検知するには、`UIViewController#willAnimateRotationToInterfaceOrientation:duration:`メソッドをデリゲートする。

####サンプルコード

```objc
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
{
	//ここに回転時の処理
}
```

###AutoLayoutで自動レイアウト

iOS6から導入されたAutoLayout。
とりあえずコードからすべて制御できたほうがいいだろうと、特に使わない方針で勉強しているんだけど、これはデフォルトでオンになっている。
これが影響して、コード上でいくらUIViewの位置を変更しても反映されない、という問題にハマった。
本当はAutoLayoutを使ってやるのが正しいのだと思うのだけど、とりあえずコードだけでやっている場合はオフにしておくといいかも。

###`this class is not key value coding-compliant`でアプリが落ちる

>
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<`HogeController` 0x801eb80> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key `Fuga`.'

Key Value Coding? と思ったら、IBOutletを使っているとおきるみたい。
つまり、IB上で紐付けたけど、コード側で削除したりしてしまった場合。
コードだけでは問題が見えないのでハマる。

###tableFooterViewが表示されない

```objc
// NG
[self.tableView.tableFooterView addSubview:aView];
```

みたいにしてたら追加されず。プロパティアクセスにしないとならないみたい。

```objc
// OK
self.tableView.tableFooterView = aView;
```