@neiraza

2匹の怪獣が寝た後にプログラマーしてる、最近はサイバーエージェントでゼミ長もしてる僕のネタ帳

iOSとAndroidアプリのダウンロード数を晒してみた

3年くらい前に初めて作ったiOS & Androidアプリについて、
公開から現時点までのダウンロード数を
記録がわりに、晒してみることにした。

広告とか入れてないので、収入は無し。
iOSはゲームで、Androidは添付画像ベースのメーラー

f:id:redogu:20140220100151p:plain

iOSの方は、5割りほどが中国ユーザでした。
ありがとう、中国。

最近はプライベートで Androidアプリは作ってないし、
iOSはずーっとreject続きだけど、次は3,000ダウンロードを目標に。。。

blockでコールバックを書いたった

blockでコールバックを書く

いい加減、delegateばっかだと、あっちこっち読むのが大変なので書いてみた
まず、呼び出される側から。

// BlockSample.h

#import <Foundation/Foundation.h>

typedef void (^BlockSampleCallBack)(NSArray *foo);

@interface BlockSample : NSObject
- (void)hoge:(NSString *)fuga callback:(BlockSampleCallBack)callback;
@end

typedefで定義してするほうが可読にいいよねってことらしい。

// BlockSample.m

#import "BlockSample.h"

@implementation BlockSample

- (void)hoge:(NSString *)fuga callback:(BlockSampleCallBack)callback
{
	NSArray *array = @[@"りんご", @"ごりら", @"らぶらぶ"];
	callback(array)
}

@end

次に呼び出し側を書く。

// CalledBlockSample.m

// いろいろと割愛

- (void)moDMP
{
	// BlockSampleがシングルトンだったとして...
	[[BlockSample] sharedManager] hoge:@"これはテストだ" callback:^(NSArray *foo) {
	NSLog(@"アホな配列がやってくるお %@", foo);
	}];
} 

// いろいろと割愛

CoreDataのサンプルでハマった?

もし、あなたが

Receiver type 'NSManagedObjectContext' for instance message is a forward declaration

でハマったら、

たぶん、サンプルではCoreDataのimportがpchファイルに書いてあるはず。


そんなiOS、CoreDataを始めますって方におすすめなのがこの本。

iOS Core Data徹底入門

iOS Core Data徹底入門

DBって何だよ(笑)ってレベルからでも、読みやすいと思われ。

UIAlertViewのdelegateでダラダラすんの禁止

UIAlertViewでok/cancelをタップした後の処理ってどうしてます?

delegateだけで対応すると、
複数のUIAlertView扱っちゃうと、分岐の嵐。

アラートダイアログが消えたら、○○するとかでも良いのかもだけど、
後々、UIKitが対応してくれるとしたら、blockでやってくれるはず。
また既に多くの人が、そーしてるはず。そいうライブラリもあるし。

あとは、カテゴリにしといてくれないと使いづらい。
シンプルにおさめると、こんなんでいいはず。


参考 UIAlertView の delegate 束縛を解放しよう | mixi Engineers' Blog

GMTな文字列をNSDateなローカル時間に変換した

iOSAndroidをいったりきたりしているうちに、
この単純な対応方法を忘れてしまったので書いておく。

そもそも、NSDateのカテゴリとかで残ってないのが不思議なんだけど。
前に作ってた時は、どーしてたんだろか。

基本方針として、
NSStringやNSDateのカテゴリとして作成しておく。

んで、呼び出す以上。

pod installできなくて困っていた件を解決した

気づいたら、こんなことになっていて、、、

> Installing MBProgressHUD (0.7)
 > GitHub download
   $ /usr/local/bin/git config core.bare
   true
   $ /usr/local/bin/git config core.bare
   true
 > Updating cache git repo (/Users/togu/Library/Caches/CocoaPods/GitHub/ef81a51251a828eea52cbd59e57827b0007c9dba)
     $ /usr/local/bin/git remote update
     error: cannot open FETCH_HEAD: Permission denied

[!] Pod::Executable remote update

error: cannot open FETCH_HEAD: Permission denied

言われた通りの場所が、rootになってた
なんでだろー?と思いつつ自分の権限にかえて、pod installで決まり

# ls -l /Users/togu/Library/Caches/CocoaPods/GitHub/ef81a51251a828eea52cbd59e57827b0007c9dba

-rw-r--r--   1 root  staff  6028  8 19 18:54 FETCH_HEAD 

# sudo chown togu:staff

UITextFieldの本当の文字数をみてなかた

ほんたったで写経したり、設計書や資料集やらを置いて捗りまくりです。

EDISON ほんたった赤(ハードケース入り)

EDISON ほんたった赤(ハードケース入り)

本題

UITextFieldを2つ、UIButtonを1つの画面を作っていて、
UITextFieldが2つともN文字以上の場合のみ、UIButtonを有効にしたい

こういう時、UITextFieldDelegateを使いますよね。
UITextFieldDelegate Protocol Reference

たぶん、使うのはshouldChangeCharactersInRangeだと思うんですけど、
なんか思い通りにいかなくて。

hogeTextFieldの長さを取得するのに、

int hogeLen = hogeTextField.text.length;

こうしてるんだけど、

1文字入力
hogeLen :0

1文字削除
hogeLen :1

なんでだよーと思ってたら、ようはdelegateで捕まえてきた時の入力前の状態なのね。

というわけで、shouldChangeCharactersInRangeの引数を使って解決。

まとめ

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{    
    NSMutableString *str = [textField.text mutableCopy];
    [str replaceCharactersInRange:range withString:string];

    /*
      * あとはlengthをとって、文字数オーバならNOを返せばいいし、
      * 問題ないなら、そのhogeTextField.selected = YESとかしちゃって、
      * 他UITextFieldのselectedをみつつ、条件が合致すれば、button.enabled でいいかも
      */
 
    return YES;
}