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];
}
とすれば全体に背景色を指定できる。

iPhone特定の条件でデバックを行う

Xcode4.2において、ブレークポイントを設定して、特定の条件のみ処理を止めたいときの設定

サンプルコード

いつも通りブレークポイントを設定します。
その後右クリックで「Edit Breakpoint」を選択します。
 Conditionに「i==50」と設定すれば、iの値が50の時だけBreakpointを有効にできます

設定項目
  • Condition
    • 数式を指定
  • Ignore
    • 指定した回数はスルーする (2を指定すると3回目に止まる)
  • Action
    • 以下の詳細な動作を登録できる。デフォルトは何もしないで止まるだけ
      • ActionScript
      • Capture OpenGL Frame
      • Debugger Command
      • Log message 
        • %B メソッド名、%H カウントなど指定可能
      • Shell Command
      • Sound
  • Option
    • 一時停止しないで次に進む

SSHで公開鍵方式でパスワードなしでログインする

クライアントPCで秘密鍵、公開鍵を作成します

$ ssh-keygen -t rsa
※パスワードを2回入れます
そして~/.ssh/id_rsa と ~/.ssh/id_rsa.pub が作成されます

それをサーバ側にscpしてサーバ側の.ssh/authorized_keysに追加します。
scp ~/.ssh/id_rsa.pub [アカウント]@[ホスト名]
ssh [アカウント]@[ホスト名] cat id_rsa.pub >> .ssh/authorized_keys

ポートスキャンをコマンドで行う

macのutilitiesにポートスキャンを行うコマンドがあるみたい。

/Applications/Utilities/Network\ Utility.app/Contents/Resources/stroke

使い方はそのまんまですね。


$  /Applications/Utilities/Network\ Utility.app/Contents/Resources/stroke -h
stroke address startPort endPort

アドレス、開始Port番号、終了Port番号って所でしょうか。

iPhone KVCで値が変更したら通知を受ける

iPhone開発において、ある値が変更されたら通知を受ける仕組みがある。
例えばネットワークに接続中かどうかのフラグがあり、それが変更するたびに、インジケータをまわす、止めるを制御したいなどなど

  • NetWorkManagerクラス
NetWorkManager.h
@property (nonatomic, readonly, getter=isNetworkAccessing) BOOL networkAccessing;

NetWorkManager.m

- (BOOL)isNetworkAccessing {
return [_requests count] = 0;
}

- (void) requestXXX {
NSRequest* reqeust;
// 省略
[self willChangeValueForKey:@"netWorkAccesing"];
[_requests addObject:request];
[self didChangeValueForKey:@"netWorkAccesing"];
}

  • ObserverReciveSampleクラス
ObserverReciveSample.m
- (id)init{
// 省略

// キー値監視の登録
_netWorkManager = [[[NetWorkManager* alloc] init];
[netWorkManager addObserver:self forKeyPath:@"networkAccessing" options:0 context:NULL];
}

- (void)observeValueForKeyPath:(NSString*)keyPath
ofObject:(id)object
change:(NSDictionary*)change
context:(void*)context {
// networkAccessingキーの場合
if ([keyPath isEqualToString:@"networkAccessing"]) {
// ネットワークアクティビティを更新する
[UIApplication sharedApplication].networkActivityIndicatorVisible = _netWorkManager.networkAccessing;
}
}

今回は明示的にwillChangeValueForKeyやdidChangeValueForKeyをしていますが、それを指定しない場合、以下のように監視する方法もあるみたいです。
※上記の場合だと、パラメータが存在しなくても動作します。



+ (BOOL)automaticallyNotifiesObserversForKey:(NSString*)key {
if ([key isEqualToString:@"networkAccessing"]) {
return YES;
}
return [super automaticallyNotifiesObserversForKey:key];
}





サーバが重たいと感じたら

WEB+DBPressの内容を自分なりに理解するためのメモ


1.ロードアベレージを確認
$ uptime
13:13 up 3 days, 2:18, 2 users, load averages: 3.35 3.18 2.27

(ロードアベレージが低い)
netstat -i

続きは今度

ReactNativeでAndroid対応する話

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