LoginSignup
41
40

More than 5 years have passed since last update.

[Objective-C] ハマったメモ

Last updated at Posted at 2014-02-28

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


クラス編

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

superが呼べない

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


メモリ管理編

UIViewControllerのtouchesBegan:withEvent:が呼ばれない!

こちらの記事を見て解決。
UIViewControllerのtouchesBeganとかtouchesEndedが上手く機能しなかったと思ったら・・・

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

以下のようにするとOK。

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

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

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

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

// (void *)型にキャスト
NSString *sammple = @"sample";
[anyObject someMethod:(__bridge void *)sample];
// 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を使わないほうがいい)に記載があった。

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

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

- (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:メソッドをデリゲートする。

サンプルコード

- (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が表示されない

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

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

// OK
self.tableView.tableFooterView = aView;
41
40
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
41
40