iPhone ツールバーを均等に配置する

ツールバーにボタンなどを単純に追加すると、左寄せになってしまう。





UIToolbar* toolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 480-44, 320, 44)];
 UIBarButtonItem* prevButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRewind target:self action:@selector(clickPrev)];
    UIBarButtonItem* nextButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFastForward target:self action:@selector(clickNext)];
    UIBarButtonItem* space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    [toolBar setItems:[NSArray arrayWithObjects:space, prevButton, space, nextButton, space, nil]];



それを均等にする方法




間にUIBarButtonSystemItemFlexibleSpaceを入れるだけ。


UIToolbar* toolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 480-44, 320, 44)];
    UIBarButtonItem* prevButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRewind target:self action:@selector(clickPrev)];
    UIBarButtonItem* nextButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFastForward target:self action:@selector(clickNext)];
    UIBarButtonItem* space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    [toolBar setItems:[NSArray arrayWithObjects:space, prevButton, space, nextButton, space, nil]];

iPhone 複数画像スライド、拡大縮小させる

完成系のイメージはiPhoneのアルバム。

複数画像がある状態で、
1.フリック動作で次の画像、前の画像がみれる
2.2本の指で拡大縮小ができる
3.(できれば)ステータスバーやツールバーが自動的に消える

を作りたいなーと思い、いろいろ調べながら試行錯誤した内容を書きます。

1.フリック動作で次の画像、前の画像がみれる

これはUIScrollViewのプロパティーを設定する。
pagingEnabled ページング
showsHorizontalScrollIndicator 横スクロールバー
showsVerticalScrollIndicator 縦スクロールバー
scrollsToTop ステータスバーをタップしたときにTOPに戻る(今回は横ページ遷移のため特にいらない)

各ページのx座標をずらしてaddSubviewすればOK
1ページ目 CGRextMake(0, 0, 320, 480);
2ページ目 CGRextMake(320, 0, 320, 480);
3ページ目 CGRextMake(640, 0, 320, 480);
のような感じで。


UIScrollView* scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
    scrollView.pagingEnabled = YES;
    scrollView.showsHorizontalScrollIndicator = NO;// 横スクロールバー非表示
    scrollView.showsVerticalScrollIndicator = NO; // 縦スクロールバー非表示
    scrollView.scrollsToTop = NO; // ステータスバーのタップによるトップ移動禁止

    NSArray* imageNames = [NSArray arrayWithObjects:@"image2.jpeg", @"image1.jpeg", @"image3.jpeg", nil];
    int imageNum = [imageNames count];
    for (int i=0; i < imageNum; i++) {
        UIImage* image = [UIImage imageNamed:[imageNames objectAtIndex:i]];
        UIImageView* imageView = [[[UIImageView alloc] initWithImage:image] autorelease];
        CGSize size = CGSizeMake(MIN(image.size.width, 320), MIN(image.size.height, 480));
        imageView.frame = CGRectMake(320*i + (320 - size.width) / 2, 0 + (480 - size.height) / 2, size.width, size.height);
        [scrollView addSubview:imageView];
    }
    [scrollView setContentSize:CGSizeMake(320*imageNum, 480)];
    [self.view addSubview:scrollView];

iPhone SHA1、SHA256の生成

iPhoneでSHA1、SHA256の生成方法。
調べてもあまり出てこないので、ちょっとあっているのか不安ですが、簡単な文字列の比較では問題ない感じでした。


+(NSString*) sha1ForStr:(NSString *)str {
 const char *c = [str UTF8String];
    unsigned char result[CC_SHA1_DIGEST_LENGTH];
    CC_SHA1(c, strlen(c), result);
    NSMutableString* strs = [NSMutableString string];
    for (int i=0; i < CC_SHA1_DIGEST_LENGTH; i++) {
        [strs appendFormat:@"%02x", result[i]];
    }
    return strs;
}

+(NSString*) sha256ForStr:(NSString *)str {
 const char *c = [str UTF8String];
    unsigned char result[CC_SHA256_DIGEST_LENGTH];
    CC_SHA256(c, strlen(c), result);
    NSMutableString* strs = [NSMutableString string];
    for (int i=0; i < CC_SHA256_DIGEST_LENGTH; i++) {
        [strs appendFormat:@"%02x", result[i]];
    }
    return strs;
}

ちなみにperlでは
perl -MDigest::SHA -e 'print Digest::SHA::sha1_hex("aaa"), "\n"'
perl -MDigest::SHA -e 'print Digest::SHA::sha256_hex("aaa"), "\n"'
です。

iPhone文字列のサイズを取得

テキストフィールドは高さ固定ですが、UITextViewは高さを調整できます。
そして、動的に高さを変更する場合、高さを取得するためのAPIが存在します。

UIStringDrawing.hに定義があります。

//単一行
- (CGSize)sizeWithFont:(UIFont *)font; // Uses UILineBreakModeWordWrap
- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode;

//複数行
- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size; // Uses UILineBreakModeWordWrap
- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(UILineBreakMode)lineBreakMode; // UITextAlignment is not needed to determine size

サンプルコード
UITextView* textView = [[[UITextView alloc] init] autorelease];
    [textView setText:@"sample"];

 // ピクセル
 CGSize textSize = [textView.text sizeWithFont:textView.font
        constrainedToSize:CGSizeMake(320, 1000)
         lineBreakMode:UILineBreakModeCharacterWrap];
    NSLog(@"textSize font:%@ w:%f h:%f", textView.font, textSize.width, textSize.height);
    // textSize font: font-family: "Helvetica"; font-weight: normal; font-style: normal; font-size: 12px w:39.000000 h:15.000000

ちなみに2行文のテキストを指定すると
[textView setText:@"sample\n2nd line"];
...
//w:43.000000 h:30.000000

iPhone開発 ARC forbids explicit message send of ‘retain’の解決方法

Xcode4.2で、「ARC forbids explicit message send of ‘retain’」のエラーが。

ひとまず解決方法

1.プロジェクトファイルを選択
2.Bullid Settingsを選択
3.Allを選択して、検索フィールドにAutomaticを指定
4.Apple LLVM compiler 3.0 - Language内のObjective-C Automatic Refarence CountingをYesに変更

iPhone 子プロセスではNSURLConnectionののタイムアウトが検知できない?

タイムアウトが検知できないというか、delegateが何も通知されてきません。

実装は至ってシンプル

-(void)click:(UIButton*)button
{
    // サブスレッドを作成する
    [NSThread detachNewThreadSelector:@selector(doProcess) toTarget:self withObject:nil];
//    [self doProcess];
}

- (void)doProcess {
    // ここから追加
    NSURL *url = [NSURL URLWithString:@"http://localhost:5000/"];
    NSURLRequest *req=[NSURLRequest requestWithURL:url];
    NSURLConnection *conn=[[NSURLConnection alloc] 
                                    initWithRequest:req delegate:self];
    if (conn) {
        NSLog(@"start loading");
        receivedData = [[NSMutableData data] retain];
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    NSLog(@"receive response");
    [receivedData setLength:0];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    NSLog(@"receive data");
    [receivedData appendData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    NSLog(@"Connection failed! Error - %@ %@",
          [error localizedDescription],
          [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    NSLog(@"Succeeded! Received %d bytes of data",[receivedData length]);
    NSLog(@"%@", [[NSString alloc]initWithData:receivedData encoding:NSUTF8StringEncoding]);
}

サブプロセスからだと、ログは以下のものしかでません
2011-11-29 01:13:04.444 Sample01[98789:13003] start loading

もちろんサブプロセスではなく、メインスレッドであれば正しく動作します。
2011-11-29 01:23:50.675 Sample01[98997:f803] start loading
2011-11-29 01:23:51.182 Sample01[98997:f803] receive response
2011-11-29 01:23:51.183 Sample01[98997:f803] receive data
2011-11-29 01:23:51.183 Sample01[98997:f803] Succeeded! Received 1446 bytes of data

そもそもサブプロセスなんだから非同期の通信じゃなくてもよくて、
NSURL *theURL = [NSURL URLWithString:@"http://localhost:5000/"];
    NSURLRequest *req=[NSURLRequest requestWithURL:theURL];
 NSMutableData*      data;
    NSHTTPURLResponse*  resp;
    NSError*            err = nil; 
    data = [NSMutableData dataWithData:[NSURLConnection sendSynchronousRequest:req returningResponse:&resp error:&err]];

    NSLog(@"Succeeded! Received %d bytes of data",[data length]);
    NSLog(@"%@", [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);

これで正しく取得できました。

UITableViewCellの背景色の指定

UITableViewCellの背景色は
tableView: cellForRowAtIndexPath:
ではなく、
tableView:willDisplayCell:forRowAtIndexPath:
じゃないと効かない。

ただし、UITableViewCellのcontentViewにaddSubviewした場合は、
上記の方法でもselectionStyleは正しく背景色が指定できない。
※今は解決されているかも(Xcode4.2)

上記の問題があったので、
UITableViewCellのサブクラスを作成して、
-(void)layoutSubviews {
    self.backgroundColor = [UIColor redColor];
}
とすれば全体に背景色を指定できる。

ReactNativeでAndroid対応する話

前提 ReactNativeでiOS版のアプリをリリースしていて、Android版をリリースする話 トラブルシューティング Build.VERSION_CODES.Q が存在しないエラー compileSdkVersionを29以上にすると解決 メモリー足りないエラー Execu...