2011年09月07日

NSStringとC文字列(3)

NSStringとC文字列の間の変換についての3回目。

前2回は文字列エンコーディングを指定してNSStringからC文字列を取り出す方法を見てきました。

その中で、エンコーディングによってはNSStringに格納されている文字列情報を変換できずにC文字列の取得に失敗する場合があるという話がありました。文字列中に変換できない文字があったとしても他の文字は変換可能ですので、変換できない文字1つのために取得できる情報がゼロというのも困った物です。その場合にどうすればいいのかを見てみたいと思います。

その前に、C文字列が取得できなかった原因がメモリ不足など他の原因ではないことを確認するメソッドがあります。

- (BOOL)canBeConvertedToEncoding:(NSStringEncoding) encoding


これは指定されたエンコーディング(その1で例示しています)に情報の欠落なしに、ということは全ての文字を変換可能かどうかを返します。YESであれば変換可能。NOであれば変換不能。つまりここでNOが返ってくれば前回までのメソッドではC文字列を取得できないことがわかります。

続きを読む
posted by 永遠製作所 at 14:53| 東京 ☀| Comment(0) | TrackBack(0) | Cocoa | このブログの読者になる | 更新情報をチェックする

2011年09月04日

NSStringとC文字列(2)

さて、前回に続きNSStringからC文字列を取り出す変換について。今回のが書きたかったこと。

簡易な変換方法では文字列の保存領域確保が不要な反面、いずれ勝手に解放されてしまう不便があります。

ですから、メモリ解放が自動ではない方法があればそれにこしたことはない。それがこれ。


- (BOOL)getCString:(char *)buffer maxLength:(NSUInteger)maxBufferCount encoding:(NSStringEncoding)encoding


bufferはあらかじめ呼び出し側で確保したメモリなので誰も勝手に解放しません。そこにC文字列+NULL終端文字を含めて返してくれます。文字列エンコーディングはencodingで指定します。指定する定数は前回示したもの。

ただし、確保したメモリより変換後の文字列が長ければ不正なメモリアクセスなどよろしくないことが起こるかもしれません。そのために確保したメモリのサイズをmaxBufferCountで示します。

ここでポイントはmaxBufferCountは、確保したメモリサイズを与えるということ。つまり文字列長+NULL文字分必要です。メソッド名の引数指定部分がmaxLength:なので文字列長かと間違えやすいので要注意です。間違えない?私は間違えてかなり時間を無駄にしました。

バッファが短すぎたり、指定した文字列のエンコーディングでは変換できない場合、戻り値でNOが戻ります。成功した場合にはYESが戻ります。

ではどれだけのサイズのメモリを確保すればいいのでしょうか?



続きを読む
ラベル:NSString Char
posted by 永遠製作所 at 14:27| 東京 ☀| Comment(0) | TrackBack(0) | Cocoa | このブログの読者になる | 更新情報をチェックする

2011年09月02日

NSStringとC文字列(1)

Mac OS XでもiOSでも同じですが、Cocoaで文字列を扱う場合には、NSString系のクラスを使います。ですが、通信処理やC言語由来のライブラリを使いたい時など、場合によってはC言語の形式の文字列が必要になる場合があります。

そのために、NSString から C文字列、あるいはC文字列からNSStringへの変換をする必要があります。

今回はその方法についてメモしておきます。

■NSStringからC文字列を取り出す。

いくつか方法がありますが、一番お手軽なのは


- (const char *)UTF8String;


これを呼べばNULL文字終端のC文字列が戻り値で得られます。その場でなにかして終わりという場合には一番簡単です。

文字列の保存されているメモリ領域はNSStringが内部的に確保してくれて自動的に開放されます。が、この開放タイミングがよくわかりません。ですから、c文字列を取り出した後保持しておきたいとかしばらくたってから使うという場合には、別に領域を確保してそこに複製します。

ちなみにリファレンスでは以下。


The returned C string is automatically freed just as a returned object would be released; you should copy the C string if it needs to store it outside of the autorelease context in which the C string is created.


C文字列が生成されたオートリリースプールコンテキストの外に出たら自動的に開放されるよと。いうことになっています。このC文字列を保持するためのなんらかのコンテイナオブジェクトが存在していてそれが、プログラマ側に見えていないだけってことでしょうか?



const char *temp = [theString UTF8String];
size_t size = strlen(temp) + 1;
char *buff = malloc(size);
strlcpy(buff,temp,size);


ただし、このメソッドではUTF8でしか取り出せません。JISとかSJISとかの他の文字列エンコーディングで取り出したい場合には別のメソッドを使います。

続きを読む
posted by 永遠製作所 at 18:01| 東京 ☀| Comment(0) | TrackBack(0) | Cocoa | このブログの読者になる | 更新情報をチェックする

2011年08月30日

isKindOfClass:の使い方

使うたびに使い方を忘れて、テストコードを書いている。いつまでたっても使い方を憶えられない。それがNSObjectプロトコルの-isKindOfClass:です。なのでここにメモしておきます。

これはあるインスタンスがあるクラス(またはそのサブクラス)のオブジェクトかどうかを判定するのに使います。ですからメッセージ送り先はインスタンスで引数はクラスオブジェクトです。

例えばNSStringのクラスかどうかは以下のようにして判定します。


if ( [anObject isKindOfClass:[NSString class]] ) {
NSLog(@"Yeh! It's a kind of NSString class.");
} else {
NSLog(@"Noop! Sorry.");
}


よく間違えるのが、以下のような書き方。


if ( [[anObject class] isKindOfClass:[NSString class]] ) ...


これはどちらもClass型になるのでanObjectがどんなクラスのインスタンスでも常に等しくなります。続きを読む
ラベル:Objective-C クラス
posted by 永遠製作所 at 01:15| 東京 ☁| Comment(0) | TrackBack(0) | Cocoa | このブログの読者になる | 更新情報をチェックする

2011年08月16日

[Cocoa]セグメントの選択方法

セグメントコントロールというものがある。クラス名で言えばNSSegmentedControll。
これは継承樹で言えば以下のようになる。

NSSegmentedControll : NSControl : NSView : NSResponder : NSObject

NSControlの家族で兄弟にNSButtonなどがいる。実際の描画はActionCellである。NSSegmentedCellが担当している。

ので使い方も他のコントロール類と同じだと思って実装したが全然思ったような動きをしない。そこで調べてみたら少し動作が違うことがわかりました。

(1)値の参照

下記のようにselectSegmentWithTag:で表示したい区分のタグを設定する。


NSSegmentedControl *segmentView_;
[segmentView_ selectSegmentWithTag:0];

続きを読む
ラベル:API Cocoa
posted by 永遠製作所 at 00:00| 東京 ☁| Comment(0) | TrackBack(0) | Cocoa | このブログの読者になる | 更新情報をチェックする

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。