読者です 読者をやめる 読者になる 読者になる

@niwakk7 iPhoneアプリ作っていますよ

iPhoneアプリ作ってます。調べたことを、ゆるく残していきます。

【Swift基礎】print文、ログ出力

Swift基礎
//改行なし
print("hello world")
 
//改行付き
println("hello world")

Xcodeでエラーが出てないのにビルドに失敗(Build Failed)する。

エラーが全然でてないのに、ビルド失敗してどこを直していいかわからない!


ios - Xcode 4: Build Failed, No Issues - Stack Overflow

一番よくあるのは、

Bundle identifierとかPRODUCT NAMEにアンダースコアが入っている

かららしい。

だが、自分の場合は違った。

If you changed bundle identifier and cleaned project, but it also didn't work, try to empty /Users/YOUR_USERNAME/Library/Developer/Xcode/DerivedData directory.
It works for me.

ようは、キャッシュ削除すればいいらしい。

ターミナルからこのディレクトリにいって削除してもいいし、OrganizerのProjectタブからDerived DataをDeleteってやるもよし。

UIAlertControllerでアラートやテキスト入力モーダル画面を出す。

iOS8からUIAlertViewが非推奨になり、UIAlertControllerという新しいクラスを使う必要が出た。簡単に使い方をまとめた。

ボタン二つの通常のAlertView


f:id:niwakk7:20141002183359p:plain:w200

    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Title" message:@"message" preferredStyle:UIAlertControllerStyleAlert];
    
    //addActionでボタンと、押されたときのハンドラを登録。    
 [alert addAction:[UIAlertAction actionWithTitle:@"OK"
                                              style:UIAlertActionStyleDefault
                                            handler:^(UIAlertAction *action) {
                                                NSLog(@"OK pushed");
                                                
                                            }]];

    [alert addAction:[UIAlertAction actionWithTitle:@"Cancel"
                                              style:UIAlertActionStyleDestructive
                                            handler:^(UIAlertAction *action) {
                                                NSLog(@"Cancel pushed");
                                            }]];

    //出力
    [self presentViewController:alert animated:YES completion:nil];

delegateメソッドを登録する必要がなくなったのですっきりした。あと、BlocksKitも使う必要がなくなった。

テキスト入力するためのAlertView


f:id:niwakk7:20141002183524p:plain:w200

    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Title" message:@"message" preferredStyle:UIAlertControllerStyleAlert];
    
    [alert addAction:[UIAlertAction actionWithTitle:@"OK"
                                              style:UIAlertActionStyleDefault
                                            handler:^(UIAlertAction *action) {
                                                NSLog(@"OK pushed");
                                                
                                            }]];
    
    [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
        textField.placeholder = @"text input";
        textField.delegate = self;
    }];
    
    [self presentViewController:alert animated:YES completion:nil];
- (void)textFieldDidEndEditing:(UITextField *)textField
{
    self.text = textField.text;
    
    NSLog(@"text editing finished");
}

ポイントは、addTextFieldWithConfigurationHandlerかも。ここでdelegateを設定しておいて、OKボタンが押されたら編集終了となり、textFieldDidEndEditingがよばれるという流れ。


AlertControllerSample/AlertControllerSample at master · niwakk7/AlertControllerSample · GitHub

NSSortDescriptorを使って、日付でソートする

以下のような構造のデータの配列を、NSSortDescriptorを使ってソートする。

@interface ListData : NSObject <NSCoding>

@property (nonatomic, readonly) NSString *identifier;
@property (nonatomic, retain)   NSString *memo;
@property (nonatomic, retain)   NSDate *date;

@end

上記のデータを、datasという配列(mutable)でもっているとする。その配列を、日付でソートする。

- (void)sortByDate
{
    NSSortDescriptor *descDate = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO];
    NSArray *sortDescArray = [NSArray arrayWithObjects:descDate, nil];
    _datas = [[[_datas copy] sortedArrayUsingDescriptors:sortDescArray] mutableCopy];
}

copyやらmutableCopyやら...不細工でもうしわけないが、ひとまず動いたのでのせるよ♪

NSUserDefaultsにNSMutableArrayの配列をsetObjectしようとすると、固まる。

不正アクセスとかで落ちるわけではなく、ほんとうにパタッと固まってしまう。iOS7まではできたのが、とたんに動かなくなった。

どうやら、NSMutableArrayだとだめらしい。

宣言をみると、

- (void)setObject:(id)value forKey:(NSString *)defaultName;

なんだが、NSArrayしか受け付けてくれない。
ということで、いったんコピーしたらうまくできた。

NSArray *newArray = [mutableArray copy];

]
objective c - iOS 8 freezes at updating UserDefaults object - Stack Overflow

アプリをシンプルにつくったほうがいい、技術的な7個の理由。

iOSプログラミング

アプリをシンプルに作ったほうがよい理由は、ほとんど語り尽くされている。だが、技術的な理由はあまり語られていないかも。ということで、その技術的な視点からの、アプリをシンプルに作ったほうがいい理由をいくつか考えてみた。

開発工数が減る。

これは当然であり、誰もが思うかもしれない。機能を最小限にとどめれば、その分やることも減る。大切なのは、"それだけではない"ことを意識すること。

テスト工数が減る。

機能を減らせば、その分テストしなくてよくなる。また、テストはプログラムテストからユーザテストまでさまざまなものがあり、それを実行する人が複数人いる場合も多々ある。すべてのテスト工数を考えると、機能を減らすことがどれくらいのテスト工数を減らすことにつながるかが想像がつく。

運用工数が減る。

追加した機能は、当然ユーザさんのフィードバックを受け、それにちゃんと答えなくてはいけない義務が発生する。なんとなくつけた機能がそのアプリの本質とずれているにも関わらずいがいと使われたりする。そしてそこにバグが発生したり、要望が来たりするとそれに答えるコストが発生する。だったら最初から加えないほうがいい。

バグが発生するリスクが減る。

一つ上と少し似ているが、機能を追加すると当然その部分のバグが発生するリスクが出てくる。ましてや、その部分のプログラムが他の部分と密結合になっていたりすると、他にもバグが拡大する恐れがある。だったら最初からないほうがいいよね。

その部分を横展開したときのリスクが減る。

このアプリ結構DLされたから、横展開して○○アプリをつくろう!というのは、誰もが考える。しかし、これはリスクも横展開することになる。あるアプリでバグが出たとき、"あー、あのアプリもそういえばなおさなきゃいけないわー"ってなったとき、悲しいよね。

全体設計がシンプルになる。

考えることが減るので、全体設計もシンプルになる。全体が分かりやすくなり、ミスも減るし他の人の手も入れやすくなる。もちろん、設計だけではなく製造(プログラミング)もしやすくなる。機能追加すると、途中から設計のしなおしが入り、無理な設計になることがある。それが増えると、なんだがよくわからない設計になって、気がついたら納期が目の前とかよくある。

気持ちよい

上のこともふまえて、安全がプログラムができると気持ちよい。精神衛生上絶対にいい。もう手をいれるのすらはばかれるプログラムとかたまにあるけど、これは元をたどるとモリモリ機能アプリである場合が多い。

アプリをシンプルにつくったほうがいい理由を7つほどあげてみた。書いている間に気がついたのだが、以下のように考えている人、いがいに多いと思う。

開発工数 < 売り上げ

これは、ダメ。

正しいのは以下。

上記の全ての工数 < 売り上げ

厄介なのは、この工数のどれだけがが、未来に不規則に発生するかもしれないこと。
いずれにせよ、これはアプリをシンプルにすることで実現することができる。

アプリをシンプルにすることが技術的なリスクを減らし、工数を減らし、みんなを幸せにすることにつながることがわかる。

Lipo Error: can't open input file *** というエラーでビルドが通らない。

iOSプログラミング

さまざまな解決策が議論されているみたい。

xcode - Lipo Error: can't open input file - Stack Overflow

ただ、自分の場合は少しちがったみたい。
以下の方法で解決した。

Google AnalyticsSDKを参照から削除。

右クリックからDelete、Remove from referenceを選択、Google Analyticsの入っていたフォルダをごそっと参照から削除する。

Finderから追加しなおす。

要は、ふつうにGoogle Analyticsの入っていたフォルダをもとに戻す。

なにか、参照がおかしくなっていたみたい。

ちなみに今回の場合は、Subversionの環境においてあったプロジェクトをGitに移そうと思ってダウンロードし、立ち上げたらこうなった。

たぶん、他のSDKが悪さをしている場合もあるので、是非おためしください。