Category Archives: Objective-c

株式会社プラスアールでは、iOS ( or Android or PHP ) のエンジニアを募集しています。
http://www.plusr.co.jp/recruit/programmer

今回も下の問題が解けたら書類選考なしにいたします。さらに、面接の際にバックジョイをプレゼントしちゃいます。

image_backjoy

求人への応募はしないという方でも、問題が解けた&弊社まで景品をとりに来ていただけるようでしたら、先着10名様に限りバックジョイをプレゼントいたします。

こぞってご応募ください。

[問題]

以下の表はそのマスとその周囲8マスに含まれている爆弾の個数を表しています。フィールドに含まれている爆弾の位置を(x,y)としたとき、その積k(=x*y)が小さい順にアルファベットを並べるとある単語が完成します。

マインスイーパの説明

解けた方は次のメールアドレスまでご連絡ください!
[完成したメッセージ]-[kの総和]@plusr.co.jp
※[]は要りません。
※作成したプログラムのGithubへのリンク又は、プログラムを添付してください。
※面接の日程についてはメールで調整致します。

求人に応募しない方は、”解けた!”というご連絡だけでも構いません。
景品だけ希望の場合はその旨ご記載ください。
例:「景品ほしい」

よろしくお願いいたします!

※求人の定員に達し次第終了しますので、解けた方はすぐにご連絡下さい。

1 2 3 4 5 6
1  1 i  2 p  2 a  1 g  1 x  1 u
2  1 c  2 t  2 e  2 h  2 r  2 a
3  1 g  2 q  1 i  2 r  3 n  3 z
4  2 r  2 d  2 g  2 o  3 e  2 o
5  2 v  2 n  2 o  1 w  3 y  2 s
6  2 b  2 t  2 r  1 p  2 w  1 a
7  2 g  2 u  2 i  1 x  3 q  2 u
8  2 e  2 t  2 s  1 m  2 x  1 n

Objective-CではURLエンコード/デコードをするのがちょっと面倒です。

JavaScriptのencodeURIComponent()と同じように使えるC関数を提供するライブラリを書きました

使い方は単純です。

AZEncodeURIComponent(@"日本語"); // -> "%E6%97%A5%E6%9C%AC%E8%AA%9E"
AZDecodeURIComponent(@"%E6%97%A5%E6%9C%AC%E8%AA%9E"); // 日本語

CocoaPods経由でインストールできます。

pod "AZEncodeURIComponent"

単純なライブラリですが、何故かこれだけを提供するものがなかったので書きました。。

Lupinus

LupinusHTTP は直感的に扱いやすい事を目的にしたHTTPライブラリです。

NSURLSessionをベースにしているのでiOS7以降のみ対応です。

インストール

Cocoapodsからインストールできます。

pod "LupinusHTTP"

使い方

基本的には以下の2ステップで送信と受信ができます。

  1. LupinusHTTPRequest でどこにリクエストするのかを決める。
  2. 返り値のLupinusHTTPresponseJSONresponseString などどういう風にレスポンスを受け取るかを決める。

GET Request

http://httpbin.org/get?key=value にGETリクエストする例です

LupinusHTTPRequest *httpRequest = [LupinusHTTP request:LupinusMethodGET URL:@"http://httpbin.org/get" query:@{
    @"key" : @"value"
}];
[httpRequest responseJSON:^(NSURLRequest *request, NSURLResponse *response, id JSON, NSError *error) {
    NSLog(@"JSON = %@", JSON);
}];

レスポンスをどういう形式で受け取るかはどのresponse*を呼ぶかによって決まります。送信する段階ではなく、受信する段階でJSONやテキストで受け取るのかを決定出来ます。両方で受け取ることも出来ます。

以下はJSONで受け取る場合です。

LupinusHTTPRequest *httpRequest = [LupinusHTTP request:LupinusMethodGET URL:@"http://httpbin.org/get"];
[httpRequest responseJSON:^(NSURLRequest *request, NSURLResponse *response, id JSON, NSError *error) {
    NSLog(@"JSON = %@", JSON);// => JSON Object(NSDictionary or NSArray)
}];

普通にNSStringで受け取る事もできます。

LupinusHTTPRequest *httpRequest = [LupinusHTTP request:LupinusMethodGET URL:@"http://httpbin.org/get"];
[httpRequest responseString:^(NSURLRequest *request, NSURLResponse *response, NSString *string, NSError *error) {
    NSLog(@"string = %@", string);// => NSString
}];

POSTリクエスト

POSTリクエストも送ることが出来ます。

e.g) http://httpbin.org/post?key=value

body
    [1,2,3]

bodyの中身は自動でJSONシリアライズして送信されます。

[LupinusHTTP request:LupinusMethodPOST URL:@"http://httpbin.org/post" query:@{
    @"key" : @"value"
} body:@[@1, @2, @3]];
[httpRequest responseJSON:^(NSURLRequest *request, NSURLResponse *response, id JSON, NSError *error) {
    NSLog(@"JSON = %@", JSON);// => JSON Object(NSDictionary or NSArray)
}];

GETやPOSTなどのレスポンスを受け取る共通の挙動としてresponse.statusCode >= 400 の時は自動的にerrorとなります。
コールバックのerrorに値が入った状態でレスポンスが帰ってきます。

LupinusHTTPRequest *httpRequest = [LupinusHTTP request:LupinusMethodGET URL:@"http://httpbin.org/status/403"];
// response status code is 403
[httpRequest responseJSON:^(NSURLRequest *request, NSURLResponse *response, id JSON, NSError *error) {
    // error is not nil
    if(error){
        NSLog(@"%@", error);
    }
}];

NSURLSessionではNSURLSessionConfigurationをつけうことで独自のHTTPヘッダ等を付加することが出来ますが、LupinusHTTPRequestを呼ぶときにそれを渡すことが出来ます。

// default : [NSURLSessionConfiguration defaultSessionConfiguration]
+ (instancetype)httpWithSessionConfiguration:(NSURLSessionConfiguration *) sessionConfiguration;

リクエストのキャンセル

LupinusHTTPRequest#cancelを呼ぶことで送信したリクエストをキャンセル出来ます。
この場合コールバックは呼ばれません。

LupinusHTTPRequest *httpRequest = [LupinusHTTP request:LupinusMethodGET URL:@"http://httpbin.org/get"];
[httpRequest responseJSON:^(NSURLRequest *request, NSURLResponse *response, id JSON, NSError *error) {
  // this callback doens't call!
}];
// cancel request
[httpRequest cancel];

Swiftで書かれたAlamofireに影響を受けて作られているので似ている部分は多いです。

Credit

Photo by Tatu Väyrynen

NSDictionaryでkey=valueを指定したものからURLのクエリ文字列(param=value&param2=val2)を作るライブラリを書きました

pod 'NSDictionaryAsURLQuery'

でインストールできます。

使い方

NSString *results = [URLQueryBuilder buildQueryWithDictionary:@{
    @"param_1" : @1,
    @"param_2" : @"string"
}];
// => @"param_1=1&param_2=string"

という感じで、[URLQueryBuilder buildQueryWithDictionary:dict];と指定するだけの単機能なライブラリです。

面倒なURLエンコード等も適当にやってくれるので安全です。

2012年(主に後半の3-4ヶ月ぐらい)でのiOSアプリ開発についての振り返りの雑談をしたので、
その時のメモとなります。

UIAppearance

UIAppearance によるタブカスタマイズ

UIAppearance によるナビゲーションカスタマイズ

CocoaPods

PonyDebugger

square/PonyDebugger · GitHub

  • PonyDebugger
  • Chromeを使ったデバッグ
  • 意外と役に立つ機会が多い
  • cocoapods経由で入れて下記のようなシンプルなセットアップで導入できる
  • minimum PonyDebugger setup

カレンダー

  • <UITableViewDataSource>ライクなAPI
  • ヘッダー、曜日、日付のセル、フッター等細かくパーツを分けてxibでUIを作れる
  • AZCalendarView

StoryBoard

UIKitサブクラスの利点

  • StoryBoardで配置できる
  • 使い回ししやすい

UIViewのカスタムデザイン

UIAppearanceと合わせれば、見た目を変えるのにその都度プロパティを変更するようなコードは書かなくなる。
(サブクラスで作ったUIは使い回ししやすい気がする)

KVC/KVO

__weakの書き方

いつも以下のような感じにしてる

 __weak typeof(self) that = self;

NSIndexSet


プロパティメソッドチェーン

Foundation拡張

Scalaコレクションメソッドメモ(Hishidama’s Scala collection method Memo) みたいなコレクション系のメソッドが欲しい

Category

Objective-Cにプライベートはなかった問題

iOS6 と iPhone5の対応

iOS6以前とiPhone5を同時に対応するのが面倒

  • AutoLayoutが使いたい
  • AutoSizingで耐え忍ぶ

ドキュメント

  • ドキュメントが一箇所にまとまってないのが不便
  • モックデザインと仕様についてを並べておきたい
  • 遷移とかを全てデザインモックに入れるとあまり見やすくなくなるかもしれない

TestFlight

  • 「チェックします」と言われて何をチェックしてるのかわからない。
  • 先に終わり(これができてたら終わり)というチェックポイントを設ける
  • 終わり間際になってデザインの細かい修正等がめんどくさい
  • 実装者ではない人が終わりを判断することになるとコストが大きい
  • 機能の完成をアプリの完成にする/デザインの完成が終わりだと主観が入るので時間がかかってしまう

今後したいこと

  • MVCがちゃんと出来るようにしたい
  • 使い回しができる部品作り
  • Custom Objectsがつくる

その他

最近見つけた感じの

 

NSDateFormatterの国際化

dateFormatFromTemplate は便利なのでもっと使われるといい気がする。

手動で曜日の配列を定義するよりもNSDateFormatter#shortWeekdaySymbolsなどを使ったほうが楽でいいと思います。

日付操作

和暦の罠

NSDate Utilについて