レビューと言えないような酷い書き込みは削除できるらしい
ホームスクリーンに表示されるタイトルもASOの対象?
BundleDisplayNameを使ったASO対策がローカライズ対応に凄く使える
ASOといえば、
- アプリタイトル
- 説明文
- keyword
- レビュー評価
- レビュー文言
などが重要かなと思っていたのですが、タイトル欄に入りきらない文言も検索対象になっているとの事。
個人的にはタイトルが…で省略されるのはちょっといやなんですけど、keywordをガッツリ盛りたい場合は有効かも。
但し、やり過ぎると常にリジェクトのリスクがあります。 エンジニアが死ぬ気で詰めた日程を、このようなリジェクトでふいにしてしまうのは何とも悲しい事ですね。
プログラムの処理時間を計測する
処理時間計測の簡単な方法としてはNSLogを処理の始めと終わりに出力してその時間差を計算する方法がありますが、もう少し正確な計測をしてみたいと思います。
方法は以下の通り!
//これをインポートしておく #import <sys/time.h> //任意のメソッド内の記述 struct timeval start, stop; gettimeofday(&start, NULL); *** 実際の処理を行う記述 *** gettimeofday(&stop, NULL); double sec = stop.tv_sec - start.tv_sec; double usec = stop.tv_usec-start.tv_usec; double time = (stop.tv_sec*1000000+stop.tv_usec)-(start.tv_sec*1000000+start.tv_usec); NSLog(@"sec=%f",sec); NSLog(@"usec=%f",usec); NSLog(@"time=%f",time);
tv_secで処理時間の秒の部分、tv_usecでマイクロ秒の部分を取得します。
トータルの処理時間は
double time = (stop.tv_sec*1000000+stop.tv_usec)-(start.tv_sec*1000000+start.tv_usec);
このような形で計算します。
[NSThread sleepForTimeInterval:0.5f];
このような形で処理の部分にwait timeを設定して挙動を確認してみてください。
意外と面倒!タイムラインで見られる1時間前、1日前といった文字列を生成する
関連記事 NSDateの罠 - まいまいワークス
サーバーから取得した時間情報を元に、現在の時刻から計算を行い、タイムラインで見られる1時間前、1日前といった文字列を生成します。
サーバーが日本時間を基準に値を返し、iPhoneで設定された時間帯がアメリカだったりすると時差の関係で表示がおかしくなったりしますが、ここも考慮していきます。
日付関連はハマりポイントが多いです!
ソースは以下の通り
サーバーが2014-04-25 12:34:56
という値を返したと想定します。
//サーバーがこの値を返したと仮定 NSString* dateStr = @"2014-04-25 12:34:56"; //時差補正用数値の指定 float diff = [[NSTimeZone localTimeZone] secondsFromGMT]; //時差補正用 float diffTokyoTimeZone = 9*60*60; //サーバーがGMTの時間を送ってきていればここは0になる //フォーマット指定 NSDateFormatter* format = [NSDateFormatter new]; [format setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; //これで端末の設定に関わらずデータを取得する。 [format setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]]; //ロケーションに関わらずその瞬間のGMTを取得 NSDate* now = [NSDate date]; //sinceDate以降はロケーションによって値が時差分補正されたGMTになる (datestrは不変) //dateWithTimeInterval以降のオフセットはdiffとdiffTokyoTimeZoneで指定。 //diff:GMTからの時差(秒)で補正。sinceDate以降の値の補正を相殺→ロケーションに関わらず一定のNSDate値を使用できる //diffTokyoTimeZone:stringで得られる時刻がJSTで得られる前提でロケーションに関わらず9時間戻す NSDate* date = [NSDate dateWithTimeInterval:diff-diffTokyoTimeZone sinceDate:[format dateFromString:datestr]]; //経過時間の計算 NSCalendar* cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; NSDateComponents* comps = [NSDateComponents new]; //秒を計算 comps = [cal components:NSSecondCalendarUnit fromDate:date toDate:now options:0]; NSUInteger sec = [comps second]; //分を計算 comps = [cal components:NSMinuteCalendarUnit fromDate:date toDate:now options:0]; NSUInteger min = [comps minute]; //時間を計算 comps = [cal components:NSHourCalendarUnit fromDate:date toDate:now options:0]; NSUInteger hour = [comps hour]; //日数を計算 comps = [cal components:NSDayCalendarUnit fromDate:date toDate:now options:0]; NSUInteger day = [comps day]; //週を計算 comps = [cal components:NSWeekCalendarUnit fromDate:date toDate:now options:0]; NSUInteger week = [comps week]; //月を計算 comps = [cal components:NSMonthCalendarUnit fromDate:date toDate:now options:0]; NSUInteger month = [comps month]; //年を計算 comps = [cal components:NSYearCalendarUnit fromDate:date toDate:now options:0]; NSUInteger year = [comps year];
sec
,min
,hour
,day
,week
,month
,year
にそれぞれの単位で計算された差分が入ります。
あとはこれを煮るなり焼くなりなのですが、今回は以下のようにしてみます。
差分が30秒未満ならたった今
それ以外なら単純に〜時間前
といった値を生成します。
NSString* outStr; if (year != 0) { outStr = [NSString stringWithFormat:@"%ld年前",year]; }else if (month != 0) { outStr = [NSString stringWithFormat:@"%ldヶ月前",month]; }else if (week != 0){ outStr = [NSString stringWithFormat:@"%ld週間前",week]; }else if (day != 0){ outStr = [NSString stringWithFormat:@"%ld日前",day]; }else if (hour != 0){ outStr = [NSString stringWithFormat:@"%ld時間前",hour]; }else if (min != 0){ outStr = [NSString stringWithFormat:@"%ld分前",min]; }else if (sec != 0){ if (sec < 30) { outStr = @"たった今"; }else{ outStr = [NSString stringWithFormat:@"%ld秒前",sec]; } }else{ outStr = @"error"; }
Xcodeユニットテスト事始め
自作クラスに対して、修正が入るたびに手動でテストを行うのはあまりにも非効率なのでユニットテストの調査を行いました。
本エントリはその初歩の初歩。
テスト対象のクラスを作成
ここではテスト用の簡単なクラスを定義します。
#import <Foundation/Foundation.h> @interface MyClass : NSObject @property(nonatomic, assign)int a; @property(nonatomic, assign)int b; -(int)calcAdd; @property(nonatomic, strong)NSString* aaa; @property(nonatomic, strong)NSString* bbb; -(NSString*)strfunc; @end
ここではint型のaとbをcalcAdd
に食わせて結果を得るメソッド
NSString型のaaaとbbbをstrfunc
に食わせて結果を得るメソッドの2つを定義します。
#import "MyClass.h" @implementation MyClass -(int)calcAdd{ return _a+_b; } -(NSString*)strfunc{ return [NSString stringWithFormat:@"%@%@",_aaa, _bbb]; } @end
aとbを加算、aaaとbbbを接続するだけの簡単なクラスです。
テストの記述
xxxx.hファイルは不要、xxxx.mだけで良さそうです。
ここではnewTest.mファイルを作成します。
testではじまるメソッド名のメソッドがテストメソッドと見なされるようです。
#import <XCTest/XCTest.h> //これはお約束 #import "MyClass.h" //テスト対象のクラスをインポート @interface newTest : XCTestCase @end @implementation newTest -(void)testCalcAdd{ MyClass* calc = [MyClass new]; calc.a = 3; calc.b = 4; XCTAssertEqual([calc calcAdd], 7, @"エラー!"); } -(void)testStr{ MyClass* str = [MyClass new]; str.aaa = @"abc"; str.bbb = @"def"; XCTAssertEqualObjects([str strfunc], @"abcdef", @"エラー!"); } @end
各メソッドともにインスタンス化してプロパティ設定を行うところまでは通常のクラスの実行と同じです。
この後の行に書かれているのがテスト関数になります。
XCTAssertEqual(値1, 値2, @"メッセージ");
値1と値2を比較して、値1 == 値2となることが確認できればテスト成功。
失敗の場合はメッセージを出力します。
XCTAssertEqualObjects(object1, object2, @"メッセージ");
object1とobject2を比較して[object1 isEqual:object2]で等しい事を確認できればテスト成功。
失敗の場合はメッセージを出力します。
テスト実行
Product
>Test
もしくは⌘U
でテストを実行します。
詳細な情報
関数などの詳細な情報はXcodeユニットテストガイドをご一読ください。
アラートにテキストフィールドを追加する
ちょっとしたテキスト情報の入力とか、ID/Passの入力などわざわざviewをつくるよりアラートでできた方が便利ですね。
今回はそのやり方。
UIAlertView* alert = [UIAlertView new]; alert.title = @"タイトル"; alert.message = @"メッセージ"; alert.delegate = self; //<UIAlertViewDelegate>を設定する事 [alert addButtonWithTitle:@"cancel"]; [alert addButtonWithTitle:@"OK"]; alert.alertViewStyle = UIAlertViewStyleDefault; [alert textFieldAtIndex:0].placeholder = @"プレースホルダー"; [alert textFieldAtIndex:0].clearButtonMode = UITextFieldViewModeWhileEditing; [alert show];
alertViewStyle
プロパティには以下の3つが設定できます。
- UIAlertViewStylePlainTextInput
- UIAlertViewStyleLoginAndPasswordInput
- UIAlertViewStyleSecureTextInput
UIAlertViewStyleDefault
にすると普通のアラートが出てきます。(デフォルト)
それぞれのテキストフィールドの設定を行う場合は
[alert textFieldAtIndex:0]
[alert textFieldAtIndex:1]
といった感じで指定します。
上記の例だと、placeholderとclearButtonModeの設定を行っています。
入力した情報の取得は以下の通り
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ if (buttonIndex==1) { NSLog(@"text=%@",[[alertView textFieldAtIndex:0] text]); NSLog(@"text=%@",[[alertView textFieldAtIndex:1] text]); } }
CocoaPodsでライブラリのライセンスの表記を自動生成してみた
オープンソースのライブラリの中には使用している旨を明記しなければいけないものがあったりするのですが、これがなかなかめんどくさいのです。
しかしながらCocoaPods自動生成のフローを一度作ってしまえば後はファイルのコピペと少しの書き換え程度で使い回しができそうです。
手順1 Settings.bundleの作成
New File…
からSettings.bundle
を作成。
同時に生成されるRoot.plist
を編集し、Acknowledgements.plist
を追加します。
Root.plistの編集
Preference Items
の配下にアイテムをひとつ配置して、
以下のように設定する。
type = Child Pane
Title = Acknowledgements
Filename = Acknowledgements
Acknowledgements.plistを追加
普通にファイルを追加しようとしたのですが、うまくいかなかったので
Root.plistあたりを右クリックでShow in Finder
ファインダでRoot.plistを複製してファイル名をAcknowledgements.plist
に変更。
中の要素を削除。ってな感じで対処しました。
Podfileの編集
Podfileに以下を追加します。
post_install do | installer | require 'fileutils' FileUtils.cp_r('Pods/Pods-acknowledgements.plist', 'abcde/Settings.bundle/Acknowledgements.plist', :remove_destination => true)
Setting.bundle
のパスが下記のようになっている場合のソースです。
'abcde/Settings.bundle/Acknowledgements.plist'
の部分はそれぞれの環境によって書き換えてください。
Setting.bundle
とPodfile
の定型文を一度書いてしまえばあとはコピペで行けそうですね。
pod install
を実行して、ビルドするとライセンス表記が自動生成されます。
素晴らしい!