android開発者がiPhoneアプリを開発するまでのメモ3

前回

storyboardを分割したい

    UIStoryboard *subviewStoryboard = [UIStoryboard storyboardWithName:@"SubView" bundle:nil];
    SubViewController *subviewController = [subviewStoryboard instantiateInitialViewController];
    [self.navigationController pushViewController:subviewController animated:YES];

グループの作成

  • Android Studioと違ってフォルダ構造をそのままxcodeのtreeで表示してくれるわけではない
  • Xcode内で表示順番を個別で持っているよう
  • 右クリックの[New Group]でフォルダ構造を作ることができる
  • あくまでXcodeの表示上の話なので、実フォルダが作成されるわけではない
  • 実ファイルはごちゃっとあるのでこれってどうなの?って思うけどそんなもんだろう。

libraryを管理したい

sudo gem install cocoapods
pod setup

// podfileの作成...

pod install

// podfileの編集...

pod update

category機能

データの永続化

  • androidで言うところのSharedPrefarence
  • UserDefaultsを使えば同じようなことができそう

他言語化

  • values-jaみたいなフォルダを作って・・・って流れではない
  • ローカライズが必要な文字列を表示する場所はNSLocalizedStringを使って作っておく
  • Localizable.stringをコマンドから作成
  • Localizable.stringの中身をいい感じに修正
  • コマンドラインで使ってる部分をひっぱってこれるのは楽そう
  • 参考:A-Liaison BLOG: iPhoneアプリをローカライズ(国際化対応)してみた

まとめ

とりあえずこれぐらいわかってれば既存ソースを見ても何となく分かるんじゃなかろうか。javaとobjective-cの言語の違いは既存ソースがあればなんとなくやりたいことがわかるからいいけど、UI使って画面遷移とかそのへんは言語じゃなくて固有の動作すぎるので新たに勉強しないといけないのがちょっとめんどい。まだまだ色々ありそうなのでなにかあれば追記していくつもり。

  • リンク

android開発者がiPhoneアプリを開発するまでのメモ2

前回

android開発者がiPhoneアプリを開発するまでのメモ1

Master-Detail Applicationを理解

delegate

  • 継承と思ってよさ気
  • hogehoge.delegate = self;で自分を指定してその中で必要な関数を記載してやるのが一般的っぽい

pragma mark – hogehoge

  • コメントみたいなもん
  • ここから何を書くかってのをコード上に表記するやつ

UISplitViewController

ViewControllerのイベント

awakeFromNib
xibとかstoryboardから起動された際に呼ばれる。onCreateみたいなイベント。
viewDidLoad
viewの読み込みが終わった時に呼ばれる。onResumeみたいなイベント。

Segue

  • NavigationControllerでの画面遷移で使う?
  • 画面遷移時のいろいろをやってるっぽい。

@property

UITableViewController

  • MasterViewControllerが継承してる奴
  • ListViewの拡張版だと思えば良さそう
  • viewDidLoadでLeftボタンとRightボタンを作っている。中身は見れば分かりそう。
  • Editボタン(editButtonItem)をおした時の削除できるようになるのは標準機能
  • commitEditingStyleでDeleteが押された時の挙動を指定している
  • insertもできるみたいだけどeditingStyleForRowAtIndexPathを指定しないといけない
  • defaultではdeleteのみ
  • 参考:iPhoneアプリ開発: 同じ UITableViewCell 上で Delete ボタンとプラスボタンを表示 | Passions, Skills, Market
numberOfSectionsInTableView
sectionが何個あるか返却する
numberOfRowsInSection
sectionにあるデータ数を返答する
cellForRowAtIndexPath
cellの中身を返答する。getView相当だと思う。今回は追加された時の日付を表示してる。

DetailViewController

  • detailItemで設定したやつを表示しているだけ
  • hで指定したproperty変数(こんな呼び方でいいのか?)はsetterを作ることができる
  • setterを使わなくても直接入れることもできる(今回の場合は設定時に処理が入ってるからだめだけど)
  • property変数はgetterとかでは_、それ以外ではself経由でアクセスするのがいいらしい
  • 参考:Objective-C – self.propertyと_propertyの違いと、使い分け方 – Qiita
        // どっちでもいける
        controller.detailItem = object;
        [controller setDetailItem:object];

まとめ

delegateの簡単な持ってきかたがよくわからない。javaのようにoverrideできる関数の一覧とか実装しなければいけない関数一覧とか簡単に作れてもいいと思うんでなにか方法があるんだろうと思われるがまだわかってない。

リンク

android開発者がiPhoneアプリを開発するまでのメモ1

今までAndroidアプリを開発していた僕がiPhoneアプリを開発するまでの理解のメモしていこうと思う。

開発環境&前提条件

  • Xcode6.2
  • Objective-C
  • Storyboard
  • autolayout
  • ARC

SingleViewApplicationを理解

何はともあれ作ってみる。

プロジェクトの作成

まずはプロジェクトの作成。以下をやるととりあえず出来上がる。

  • [File -> New -> Project]から[Single View Application]を選択

自動生成ファイルの説明

AppDelegate.h/m
Androidで言うところのApplicationだと思う
MainView.storyboard
layoutファイル。main_activity.xmlと同じと思えばいい
MainViewController.h/m
Viewを動かすためのソース。hがヘッダで、mが中身
info.plist
設定ファイル
main.m
アプリを起動するファイル。気にしなくていいと思う

起動の仕組み

  • main.mのmain関数が起動
  • main関数に記載されているAppDelegateクラスが起動
  • info.plistの[Launch screen interface file base name]に記載されたxibが起動
  • info.plistの[Main storyboard file base name]に記載されたstoryboardが起動
  • MainView.storyboardの[Custom Class]に記載されているClassが起動

storyboardにコンポーネントを配置

  • 画面右下のコンポーネントから配置したいものを持ってくる
  • 画面上でずらして調整してもレスポンシブにならない。端末の画面サイズによってずれる
  • 画面サイズは画面左上のアイコンの左から4番目を選択して出てくる[Simulated Metrics -> Size]からデバイスを選択することで変更できる
  • 位置調整はRelatvieLayoutと考えれば良さそう
  • Viewが表示されている画面下にいるアイコンたちで位置調整を行う
  • 一番左が要素同士の位置調整。親の中央とかViewの右側とか相対的な条件はここで設定する
  • 左から二番目で要素の大きさとか左に2px移動とかの絶対的な条件を設定する
  • 変更したら左から三番目の[Update Frames]で再描画しないとワーニングが出る

コンポーネントとコードのヒモ付

  • findViewByIdみたいにコードで紐付けを記載せずにUI上で紐付けを行うっぽい
  • 画面右上にある3つのボタンの真ん中をタップして画面をソースコードとstoryboardでわける
  • storyboardから紐付けたいViewを選択
  • 画面右上の一番右のアイコンを選択
  • なんか色々書いてあるやつの○を挿入したいコードの部分に持って行くと紐付けられる
  • 参照を持ってきたい場合は[Referencing Outlets]でもってこれる
  • 持ってきたものにeventを設定するわけじゃなくてeventもUI上で設定するっぽい
  • イベントを持ってきたい場合は[Sent Events]

h/mの使い分け

  • hは外部参照用のファイル。定義ファイル群となり、外部から参照する必要がある値、関数(public)をここに記載する
  • mは実装ファイル。関数の実装を記載する。private。

ボタンを押したらtextfieldの値を撮ってきてLabelの値を変更

@interface MainViewController ()

@property (strong, nonatomic) IBOutlet UILabel *label;
@property (strong, nonatomic) IBOutlet UITextField *textField;

@end

@implementation MainViewController

// 割愛...

- (IBAction)buttonClick:(id)sender {
    [self.label setText:[self.textField text]];
}

@end
  • buttonClickはstoryboard上で[Sent Events]の[touch up inside]と紐付けている
  • labelとtextFieldsは[Referencing Outlets]で挿入
  • propertyの値はselfで参照する

まとめ

とりあえずSingleViewApplicationはできるっぽい。あとはUIKitのAPIリファレンスとか見ながら必要に応じて記載していけばいいんだと思う。UI上で色々できるのは便利だけど、作ったあとにコードだけを見てどの要素とどのコードが紐付いているかがわからないのかはちょっと不便。いかに直感的な名前をつけるかでコードの読みやすさが大幅に変わりそうな予感がする。

リンク

history.back()で戻るとscrollイベントが取得できない

ハマったのでメモ。

挙動はタイトル通りなんだけど、iPhoneのSafariでhistory.back()を使用すると戻った画面でscrollイベントが取得できない模様。以下でscrollイベントを検出しようと3つを試してみたけどどれもだめ。

// jQueryで普通に
$(window).scroll(function() {
   console.log('scroll now');
});

// イベントにbindしてみる
$(window).on('scroll', function() {
    console.log('scroll now');
});

// 生のjavascriptで
window.onscroll = function() {
    console.log('scroll now');
};

history.back()で戻る前はどれもログが出力されるけど、戻った後は出力されない。Android標準ブラウザだと検出されるからiPhoneのSafariのバグなんじゃないかと疑っている。そもそもiPhoneのSafariとAndroid標準ブラウザだとscrollのイベント検出タイミングが

  • iPhoneのSafari:Scrollが完了したタイミングでイベント発生
  • Android標準ブラウザ:Scrollが発生している最中は定期的にイベントが発生し続ける

という風に違う。

PCブラウザだと、Android標準ブラウザと同じ挙動をするものが多い(*1)のでどうもiPhoneのSafariのScrollイベントとのbindがうまく動いてないんじゃないかと予想。position:fixed;のバグといい、iPhoneのSafariって出来が悪い気がする。ちなみにiOSの5.0で試してみました。なにか打開策をご存知のかたは教えてください。

追記

一応思いつく回避策を列挙。どれもぱっとしない。。。

  • history.back()を使わずに、location.hrefで頑張る
  • scrollイベントを使わずに、touchmoveイベントで頑張る
  • history.back()で戻ってきた場合は強制リロード

*1: Chrome, Firefoxで試した

iOS5系のSafariでtouchstartが動かない場合の対処

iOS5系のSafariでjQueryを使用してDOM構築時にtouchstartイベントにbindしてもtouchstartが検出されない。

以下のコードで試したところiOS4系やAndroidだと検出できるけど、iOS5系だと検出されなかった。

    $(function() {
        $('#content').append(
            $('<div>')
                .addClass('detail1')
                .on('touchstart', function(e) {
                    alert('detail1');
                })
        );

どうしたもんかと色々弄ってたら以下のコードで動いた

    $(function() {
        $('#content').append(
            $('<div>')
                .addClass('detail1')
                .on('touchstart', function(e) {
                    alert('detail1');
                })
        );
        $('#content').on('touchstart', function(e) {
        });
    });

親の要素に何でもいいからtouchstartイベントをbindしてあげるとなぜか動いた。他のtouchmoveとかtouchendとかも同様に動かないみたいで、その場合も親要素に空のイベントをbindしてあげると察知するようになるっぽい。

これはバグなのかなぁ・・・?