tag:blogger.com,1999:blog-77252443359124219562024-03-13T21:47:51.872+09:00C開発者によるiPhoneプログラミングC,C++,C#開発者によるObjective-Cプログラミング日記。Unknownnoreply@blogger.comBlogger84125tag:blogger.com,1999:blog-7725244335912421956.post-18975501739852210322013-03-15T17:25:00.000+09:002013-03-15T17:50:33.547+09:00独自クラスの配列をソートする独自の型を持つ要素の配列をソートするには、NSArrayクラスの「<span style="background-color: yellow;">sortedArrayUsingSelector</span>」メソッドを使います。<br />
<br />
例えば、TestClassという独自のクラスを配列にしてソートさせたい場合、以下のようにします。<br />
<hr />
<br />
@interface TestClass : NSObject {<br />
@public<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSString *scale;<br />
}<br />
<br />
<span style="background-color: yellow;">-(NSComparisonResult)compare_func:(TestClass*)a; // ソート時に呼ばれます</span><br />
<br />
@property (nonatomic, retain) NSString *scale;<br />
<br />
@end<br />
<br />
<br />
@implementation TestClass<br />
@synthesize scale;<br />
<br />
-(id)init<br />
{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>self = [super init];<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>if (self) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>scale = @"ちゅうくらい";<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>return self;<br />
}<br />
<br />
-(id)initWithString:(NSString*)str<br />
{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>self = [super init];<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>if (self) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>scale = [str retain];<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>return self;<br />
}<br />
<br />
<span style="background-color: yellow;">-(NSComparisonResult)compare_func:(TestClass*)a // ソート時に呼ばれます</span><br />
{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>if ([self.scale isEqualToString:@"ちゅうくらい"]) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>if ([a.scale isEqualToString:@"おおきい"]) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>return NSOrderedAscending;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>} else if ([a.scale isEqualToString:@"ちゅうくらい"]) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>return NSOrderedSame;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>} else {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>return NSOrderedDescending;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>} else if ([self.scale isEqualToString:@"おおきい"]) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>return NSOrderedDescending;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>} else if ([self.scale isEqualToString:@"ちいさい"]) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>return NSOrderedAscending;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>return NSOrderedAscending;<br />
}<br />
<br />
@end<br />
<br />
<br />
<hr />
<br />
ソート処理の中身とかは別にどうでも良いのですが、重要なのはソート処理に使うメソッドを用意しておくということです。<br />
このクラスを配列にしてソートさせるには、以下のようにします。<br />
<hr />
<br />
// 独自クラス(TestClass)の配列を生成<br />
NSArray *test_array = [[NSArray arrayWithObjects:<br />
[[[TestClass alloc] init] autorelease]<br />
, [[[TestClass alloc] initWithString:@"おおきい"] autorelease]<br />
, [[[TestClass alloc] initWithString:@"ちいさい"] autorelease]<br />
, nil] retain];<br />
<br />
// ソート<br />
NSArray *sorted_array = [test_array sortedArrayUsingSelector:@selector(<span style="background-color: yellow;">compare_func:</span>)];<br />
<br />
// 結果を出力<br />
for (TestClass *tc in sorted_array) {<br />
NSLog(@"%@", tc.scale);<br />
}<br />
<br />
<hr />
<br />
NSArrayクラスの「sortedArrayUsingSelector」メソッドの引数に独自クラスに実装したソート用のメソッド(compare_func:)を指定することで、NSArrayがソート時に呼び出してくれるようになります。<br />
<br />
結果は以下のようになります。<br />
<hr />
<br />
ちいさい<br />
ちゅうくらい<br />
おおきい<br />
<br />
<hr />
<br />
<br />
<br />
<br />
NSArrayクラスの「<span style="background-color: white;">sortedArrayUsingSelector</span>」メソッドは要素となるクラスにソート処理を実装しなければなりませんが、「<span style="background-color: yellow;">sortedArrayUsingFunction</span>」メソッドはソート処理を外部の関数に指定することができます。<br />
<hr />
<br />
// ソート処理を配列要素ではなく、外部の関数に定義<br />
NSInteger compare_func(TestClass *a, TestClass *b, void* context)<br />
{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>if ([a.scale isEqualToString:@"ちゅうくらい"]) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>if ([b.scale isEqualToString:@"おおきい"]) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>return NSOrderedAscending;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>} else if ([b.scale isEqualToString:@"ちゅうくらい"]) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>return NSOrderedSame;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>} else {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>return NSOrderedDescending;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>} else if ([a.scale isEqualToString:@"おおきい"]) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>return NSOrderedDescending;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>} else if ([a.scale isEqualToString:@"ちいさい"]) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>return NSOrderedAscending;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>return NSOrderedAscending;<br />
}<br />
<br />
<br />
int main (int argc, const char * argv[])<br />
{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSArray *test_array = [[NSArray arrayWithObjects:[[[TestClass alloc] init] autorelease]<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span> , [[[TestClass alloc] initWithString:@"おおきい"] autorelease]<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span> , [[[TestClass alloc] initWithString:@"ちいさい"] autorelease]<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span> , nil] retain];<br />
<span style="background-color: yellow;"><span class="Apple-tab-span" style="white-space: pre;"> </span>NSArray *sorted_array = [test_array sortedArrayUsingFunction:compare_func context:NULL];</span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>for (TestClass *tc in sorted_array) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSLog(@"%@", tc.scale);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>return 0;<br />
}<br />
<br />
<hr />
<br />
結果は先の結果と同じになります。<br />
<br />
<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-57393107594019493452013-03-14T10:30:00.002+09:002013-03-14T10:30:54.167+09:00NSArrayのソートNSArrayをソートするには、sortedArrayUsingComparatorメソッドを使います。<br />
<br />
数値を降順にソートする場合<br />
<hr />
<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSArray *num_array = [NSArray arrayWithObjects:[NSNumber numberWithInt:0]<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span> , [NSNumber numberWithInt:3]<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span> , [NSNumber numberWithInt:2]<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span> , [NSNumber numberWithInt:4]<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span> , [NSNumber numberWithInt:1]<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span> , [NSNumber numberWithInt:7]<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span> , [NSNumber numberWithInt:10]<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span> , [NSNumber numberWithInt:9]<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span> , [NSNumber numberWithInt:8]<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span> , [NSNumber numberWithInt:5]<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span> , nil];<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSArray *sorted_array = <span style="background-color: yellow;">[num_array sortedArrayUsingComparator:^NSComparisonResult(NSNumber *a, NSNumber *b) {</span><br />
<span style="background-color: yellow;"><span class="Apple-tab-span" style="white-space: pre;"> </span>return b.intValue - a.intValue; // ソート</span><br />
<span style="background-color: yellow;"><span class="Apple-tab-span" style="white-space: pre;"> </span>}];</span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>for (NSNumber *aNum in sorted_array) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSLog(@"sorted_num:%@", aNum);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<br />
<hr />
上記のブロック関数内のaとbを入れ替えてやれば昇順にソートさせることもできます。<br />
<br />
結果は以下のようになります。<br />
<hr />
<br />
sorted_num:10<br />
sorted_num:9<br />
sorted_num:8<br />
sorted_num:7<br />
sorted_num:5<br />
sorted_num:4<br />
sorted_num:3<br />
sorted_num:2<br />
sorted_num:1<br />
sorted_num:0<br />
<br />
<hr />
<br />
<br />
文字を降順にソートする場合<br />
<hr />
<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSArray *str_array = [NSArray arrayWithObjects:@"A", @"E", @"B", @"Z", @"C", @"F", @"D", nil];<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>sorted_array = <span style="background-color: yellow;">[str_array sortedArrayUsingComparator:^NSComparisonResult(NSString *a, NSString *b) {</span><br />
<span style="background-color: yellow;"><span class="Apple-tab-span" style="white-space: pre;"> </span>return [b compare:a]; // ソート</span><br />
<span style="background-color: yellow;"><span class="Apple-tab-span" style="white-space: pre;"> </span>}];</span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>for (NSString *str in sorted_array) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSLog(@"sorted_str:%@", str);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<br />
<hr />
上記のブロック関数内のaとbを入れ替えてやれば昇順にソートさせることもできます。<br />
<div>
<br />
結果は以下のようになります。<br />
<hr />
<br />
sorted_str:Z<br />
sorted_str:F<br />
sorted_str:E<br />
sorted_str:D<br />
sorted_str:C<br />
sorted_str:B<br />
sorted_str:A<br />
</div>
<hr />
<br />
<br />
他にもsortedArrayUsingFunctionやsortedArrayUsingSelector等あります。<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-49447294955123964982013-03-01T11:44:00.000+09:002013-03-01T13:36:37.227+09:00Cabochaを呼び出す[mac](この記事はiphoneではなく、[mac]のみ対応です。)<br />
<br />
日本語の構文解析ツールにCabochaというものがあります。<br />
CabochaにはC言語から呼び出す為のAPIが用意されています。<br />
C言語用のAPIですが、もちろんObjective-Cからも呼び出すことが可能です。<br />
<br />
Cabochaがインストールされていることが前提ですが(インストール方法は他のサイトでいろいろ出てきますので・・)、その利用方法はまず、コマンドラインから次のコマンドを入力します。<br />
<br />
cabocha-config --cflags<br />
<br />
上記でCabochaヘッダのインストールパスを取得できます。<br />
私の環境では<br />
<br />
-I/usr/local/include<br />
<br />
となりました。<br />
ヘッダのインストールパスをxcodeのBuild Settingsの[SearchPaths]の[Header Search Paths]ところに設定します。その際、-Iは不要なので「/usr/local/include」と設定します。<br />
<br />
これでCabochaのAPIを利用する準備ができたので、あとは利用するソースからヘッダを引き込む為に<br />
<br />
#import "cabocha.h"<br />
<div>
<br /></div>
<div>
を書き、以下のようにすればCabochaが呼び出せます。</div>
<div>
<br /></div>
<hr />
<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>const char *p = [@"これは日本語のテストです。" UTF8String];<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>const char *result;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// Cabocha起動<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>char *argv[] = {"cabocha", "-f1"};<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>c = cabocha_new(2, argv);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>result = cabocha_sparse_tostr(c, p);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSString *strResult = [NSString stringWithCString:result encoding:NSUTF8StringEncoding];<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>cabocha_destroy(c);<br />
<br />
<hr />
<div>
<br /></div>
<div>
cabocha_newの1番めの引数はargvの要素数を設定します。<br />
<br />
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-3119942071477480302013-02-27T14:35:00.002+09:002013-02-27T14:35:30.275+09:00NSDictionary(plist)をバイナリで保存するNSDictionaryはwriteToFileで簡単に保存できますが、XMLファイルで保存される為、サイズが非常に大きくなってしまう場合があります。<br />
<br />
バイナリファイルで保存するには、NSPropertyListSerializationを使って以下のようにします。<br />
<br />
<hr />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// 辞書を生成<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];<br />
<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// 辞書に追加<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>[dic setValue:@"1" forKey:@"TEST"];<br />
<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// ストリームを生成<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSOutputStream *outstream = [NSOutputStream outputStreamToFileAtPath:@"./testDic" append:NO];<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>[outstream open];<span class="Apple-tab-span" style="white-space: pre;"> </span>// オープン<br />
<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// 辞書をバイナリでファイルに保存<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>[NSPropertyListSerialization writePropertyList:dic toStream:outstream format:NSPropertyListBinaryFormat_v1_0 options:NSPropertyListImmutable error:&error];<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>if (error != nil) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSLog(@"Error:%@", error.description);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>[outstream close];<span class="Apple-tab-span" style="white-space: pre;"> </span>// クローズ<br />
<br />
<hr />
<br />
保存したものを読み込むには以下のようにします。<br />
<br />
<hr />
<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>dic = [NSDictionary dictionaryWithContentsOfFile:@"./testDic"];<br />
<br />
<hr />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-11394867363535387882013-02-27T10:12:00.000+09:002013-02-27T10:35:41.513+09:00NSArrayとNSDictionaryの検索速度NSArrayとNSDictionaryを生成して検索速度を比較してみました。<br />
結果、NSDictionaryの検索速度の方が速いようです。<br />
ハッシュ(連想配列)なので当たり前と言えば当たり前ですが。。<br />
<br />
<hr />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// 計測用データ作成<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSMutableArray *array = [[NSMutableArray alloc] init];<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>for (int i = 0 ; i < 500000; i++ ) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSString *val = [NSString stringWithFormat:@"%d", i];<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>[dic setValue:[NSString stringWithFormat:@"%ld", i] forKey:val];<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>[array addObject:val];<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSLog(@"辞書検索Start");<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSDate *startTime = [NSDate date];<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSString *strTest = @"400000";<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSString *num = [dic valueForKey:strTest];<span class="Apple-tab-span" style="white-space: pre;"> </span>// 辞書を検索<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSTimeInterval interval = [[NSDate date] timeIntervalSinceDate:startTime];<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSLog(@"辞書検索Stop at:%lf", interval);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>if (num) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSLog(@"There is %@ in the dictionary", strTest);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>} else {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSLog(@"There is not %@ in the dictionary", strTest);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSLog(@"配列検索Start");<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>startTime = [NSDate date];<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>unsigned long idx = [array indexOfObject:strTest];<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>interval = [[NSDate date] timeIntervalSinceDate:startTime];<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSLog(@"配列検索Stop at:%lf", interval);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>if (idx != NSNotFound) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSLog(@"There is %@ in the dictionary", strTest);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>} else {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSLog(@"There is not %@ in the dictionary", strTest);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSLog(@"配列検索2Start");<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>startTime = [NSDate date];<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>BOOL hasString = [array containsObject:strTest];<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>interval = [[NSDate date] timeIntervalSinceDate:startTime];<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSLog(@"配列検索2Stop at:%lf", interval);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>if (hasString) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSLog(@"There is %@ in the dictionary", strTest);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>} else {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NSLog(@"There is not %@ in the dictionary", strTest);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<hr />
<br />
結果は以下のようになりました。(iPhoneでの計測ではなく、Mac上で計測しました。)<br />
<br />
<hr />
辞書検索Start<br />
辞書検索Stop at:0.000017<br />
here is 400000 in the dictionary<br />
配列検索Start<br />
配列検索Stop at:0.036717<br />
here is 400000 in the dictionary<br />
配列検索2Start<br />
配列検索2Stop at:0.037023<br />
here is 400000 in the dictionary<br />
<hr />
<br />
配列検索ではindexOfObjectによる検索とcontainsObjectによる検索を計測しましたが、どちらも大差は無さそうです。<br />
ちなみに、検索する要素を"400000"から"250000"にすると以下のようになりました。<br />
<br />
<hr />
<br />
<br />
辞書検索Start<br />
辞書検索Stop at:0.000050<br />
There is 250000 in the dictionary<br />
配列検索Start<br />
配列検索Stop at:0.022836<br />
There is 250000 in the dictionary<br />
配列検索2Start<br />
配列検索2Stop at:0.022718<br />
There is 250000 in the dictionary<br />
<br />
<br />
<hr />
<br />
ハッシュの検索はほぼ大差ない速度(むしろ若干遅くなっている)ですが、配列の検索では要素位置が上のほうにある為か高速に検索が行えました。<br />
<br />
結論としては、<br />
・ハッシュ(NSDictionary)は要素の数や位置に関わらずほぼ同一速度で検索が行える。<br />
・配列(NSArray)は要素数や要素位置に応じて検索速度が変わる<br />
・indexOfObjectとcontainsObjectによる検索は速度に大差なし<br />
<br />
というところでしょうか。<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-60082561330100708462012-12-10T15:18:00.000+09:002012-12-14T12:15:35.414+09:00アドレスブック(連絡先)からの情報取得アドレスブック(連絡先)へアクセスするには以下の様にします。<br />
<br />
<hr />
<div class="p1">
<span class="s1"> </span><span class="s2">// </span>アドレスブックを生成</div>
<div class="p2">
<span class="s3"> </span><span class="s4">ABAddressBookRef</span><span class="s3"> book = </span>ABAddressBookCreateWithOptions<span class="s3">(</span><span class="s5">NULL</span><span class="s3">, </span><span class="s5">nil</span><span class="s3">);</span></div>
<div class="p1">
<span class="s1"> </span><span class="s2">// </span>アドレスブックのレコード配列を取得</div>
<div class="p2">
<span class="s3"> </span><span class="s4">CFArrayRef</span><span class="s3"> records = </span>ABAddressBookCopyArrayOfAllPeople<span class="s3">(book);</span></div>
<div class="p2">
<span class="s3"><br /></span></div>
<div class="p3">
<span class="Apple-tab-span"> </span></div>
<div class="p1">
<span class="s1"> </span><span class="s2">// </span>配列の要素の数だけ繰り返す</div>
<div class="p4">
<span class="Apple-tab-span"> </span><span class="s5">for</span> (<span class="s5">int</span> i = <span class="s5">0</span> ; i < <span class="s6">CFArrayGetCount</span>(records) ; i++) {</div>
<div class="p5">
<span class="s3"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span></span> // 1<span class="s7">レコード取得</span></div>
<div class="p4">
<span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="s4"> ABRecordRef</span> record = <span class="s6">CFArrayGetValueAtIndex</span>(records, i);</div>
<div class="p3">
<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></div>
<div class="p5">
<span class="s3"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span></span> // <span class="s7">名を取得</span></div>
<div class="p2">
<span class="s3"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span></span><span class="s4"> NSString</span><span class="s3"> *firstName = (</span><span class="s4">NSString</span><span class="s3">*)</span>ABRecordCopyValue<span class="s3">(record, </span>kABPersonFirstNameProperty<span class="s3">);</span></div>
<div class="p4">
<span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="s5"> if</span> (firstName == <span class="s5">nil</span>) {</div>
<div class="p4">
<span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span> firstName = <span class="s8">@""</span>;<span class="Apple-tab-span"> </span><span class="s9">// </span><span class="s10">無ければ空文字に</span></div>
<div class="p4">
<span class="Apple-tab-span"></span><span class="Apple-tab-span"></span> }</div>
<div class="p3">
<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></div>
<div class="p5">
<span class="s3"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span></span> // <span class="s7">氏を取得</span></div>
<div class="p2">
<span class="s3"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span></span><span class="s4"> NSString</span><span class="s3"> *lastName = (</span><span class="s4">NSString</span><span class="s3">*)</span>ABRecordCopyValue<span class="s3">(record, </span>kABPersonLastNameProperty<span class="s3">);</span></div>
<div class="p4">
<span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="s5"> if</span> (lastName == <span class="s5">nil</span>) {</div>
<div class="p4">
<span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span> lastName = <span class="s8">@""</span>;<span class="Apple-tab-span"> </span><span class="s9">// </span><span class="s10">無ければ空文字に</span></div>
<div class="p4">
<span class="Apple-tab-span"></span><span class="Apple-tab-span"></span> }</div>
<div class="p3">
<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></div>
<div class="p5">
<span class="s3"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span></span> // <span class="s7">氏名を生成</span></div>
<div class="p4">
<span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="s4"> NSString</span> *name = [<span class="s4">NSString</span> <span class="s6">stringWithFormat</span>:<span class="s8">@"%@ %@"</span>, lastName, firstName];</div>
<div class="p2">
<span class="s3"> NSLog(@"%@", name);</span></div>
<div class="p4">
<span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="s5"> if</span> (firstName != <span class="s5">nil</span>) {</div>
<div class="p4">
<span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="s6"> </span> <span class="s6">CFRelease</span>(firstName);</div>
<div class="p4">
<span class="Apple-tab-span"></span><span class="Apple-tab-span"></span> }</div>
<div class="p4">
<span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="s5"> if</span> (lastName != <span class="s5">nil</span>) {</div>
<div class="p4">
<span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="s6"> </span> <span class="s6">CFRelease</span>(lastName);</div>
<div class="p4">
<span class="Apple-tab-span"></span><span class="Apple-tab-span"></span> }</div>
<div class="p3">
<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></div>
<div class="p1">
<span class="s1"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span></span><span class="s2"> // </span>レコードから電話番号の取得</div>
<div class="p2">
<span class="s3"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span></span><span class="s4"> ABMultiValueRef</span><span class="s3"> tels = </span>ABRecordCopyValue<span class="s3">(record, </span>kABPersonPhoneProperty<span class="s3">);</span></div>
<div class="p2">
<span class="s3"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span></span><span class="s5"> if</span><span class="s3"> (</span>ABMultiValueGetCount<span class="s3">(tels)) {</span></div>
<div class="p2">
<span class="s3"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span></span><span class="s4"> </span> <span class="s4">NSString</span><span class="s3"> *tel = (</span><span class="s4">NSString</span><span class="s3">*)</span>ABMultiValueCopyValueAtIndex<span class="s3">(tels, </span><span class="s5">0</span><span class="s3">);</span></div>
<div class="p2">
<span class="s3"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span> </span> <span class="s3">NSLog(@"%@", </span><span class="s3">tel);</span></div>
<div class="p4">
<span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="s6"> </span> <span class="s6">CFRelease</span>(tel);</div>
<div class="p4">
}<span class="Apple-tab-span"></span></div>
<div class="p4">
}<span class="Apple-tab-span"></span></div>
<div class="p2">
<span class="s3"> </span>CFRelease<span class="s3">(book);</span></div>
<div class="p4">
<span class="Apple-tab-span"> </span><span class="s6">CFRelease</span>(records);</div>
<hr />
<br />
「ABRecordCopyValue」のパラメータで指定するkABPersonFirstNameProperty等で連絡先から何を取得するかを指定します。<br />
その他プロパティには以下のものがあります。<br />
<br />
<table border="1">
<tbody>
<tr><td>kABPersonFirstName</td><td>ファーストネーム</td></tr>
<tr><td>kABPersonLastName</td><td>ラストネーム</td></tr>
<tr><td>kABPersonMiddleName</td><td>ミドルネーム</td></tr>
<tr><td>kABPersonPrefixProperty</td><td>プレフィックス</td></tr>
<tr><td>kABPersonSuffixProperty</td><td>サフィックス</td></tr>
<tr><td>kABPersonNicknameProperty</td><td>ニックネーム</td></tr>
<tr><td>kABPersonFirstNamePhoneticProperty</td><td>ファーストネームの読み</td></tr>
<tr><td>kABPersonLastNamePhoneticProperty</td><td>ラストネームの読み</td></tr>
<tr><td>kABPersonMiddleNamePhoneticProperty</td><td>ミドルネームの読み</td></tr>
<tr><td>kABPersonOrganizationProperty</td><td>組織</td></tr>
<tr><td>kABPersonJobTitleProperty</td><td>役職</td></tr>
<tr><td>kABPersonDepartmentProperty</td><td>部門</td></tr>
<tr><td>kABPersonDepartmentProperty</td><td>Eメール</td></tr>
<tr><td>kABPersonBirthdayProperty</td><td>誕生日</td></tr>
<tr><td>kABPersonNoteProperty</td><td>メモ</td></tr>
<tr><td>kABPersonCreationDateProperty</td><td>作成日</td></tr>
<tr><td>kABPersonModificationDateProperty</td><td>更新日</td></tr>
<tr><td>kABPersonAddressProperty</td><td>住所</td></tr>
<tr><td>kABPersonDateProperty</td><td>日付</td></tr>
<tr><td>kABPersonKindProperty</td><td>種別</td></tr>
<tr><td>kABPersonPhoneProperty</td><td>電話番号</td></tr>
<tr><td>kABPersonInstantMessageProperty</td><td>インスタントメッセージ</td></tr>
<tr><td>kABPersonURLProperty</td><td>URL</td></tr>
<tr><td>kABPersonRelatedNamesProperty</td><td>関係</td></tr>
</tbody></table>
<br />
また、アドレスブックから取得した各種情報はCFReleaseで解放する必要があります。(ARCを使用していない場合)<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-8224921787156523912012-07-06T01:15:00.000+09:002012-07-06T01:15:29.346+09:00Apple Developer登録の更新方法アップルのデベロッパー登録は、1年ごとに更新する必要があります。<br />
<br />
毎年やる度に試行錯誤することになってしまうので、備忘録として記録しておきます。<br />
<br />
各種証明書の概念は<b><span style="color: red;"><a href="http://technical-iphone.blogspot.jp/2012/06/ios.html" target="_blank">こちらの説明</a></span></b>に譲るとして、以下の流れで各種証明書を更新する必要があります。<br />
<br />
<br />
<br />
1. アプリケーション→ユーティリティにあるキーチェーンアクセス.appを起動し、「iPhone Developer」証明書と「iPhone Distribution」証明書を削除する。(ログインタブとシステムタブにあります。念のため削除後に検索バーから「iPhone」で検索をかけて旧い証明書が検索されないか確認する。旧いのが残っていると、後でビルド時に証明書関連のエラーが出て時間を浪費することになるので注意。)<br />
<br />
2. 「キーチェーンアクセス」→「証明書アシスタント」→「認証局に証明書を要求」後、「ユーザーのメールアドレス」、「通称」を入力、(「CAのメールアドレス」は空でも良い)要求の処理に「ディスクに保存」をチェック、「鍵ペア情報を生成」はチェック無しで「続ける」をクリックし、「CertificateSigningRequest.certSigningRequest」証明書をデスクトップに書き出し。<br />
<br />
3. アップルのデベロッパーサイトを開き、Certificatesから「Request Certificate」をクリック。<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-ZTG2aw9ztUI/T_W8MefG-tI/AAAAAAAAAb0/IgPDORIRJVU/s1600/3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-ZTG2aw9ztUI/T_W8MefG-tI/AAAAAAAAAb0/IgPDORIRJVU/s1600/3.png" /></a></div>
<br />
<br />
4. 画面下部の「ファイルを選択」をクリックする。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-eE-nmLgx2l0/T_W8MyvWidI/AAAAAAAAAcA/YRoXmscqnyw/s1600/4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-eE-nmLgx2l0/T_W8MyvWidI/AAAAAAAAAcA/YRoXmscqnyw/s1600/4.png" /></a></div>
<br />
<br />
5. 2で書き出した証明書ファイルを選択し、「submit」ボタンをクリックする。<br />
<br />
6. 証明書の「Status」が「Pending」になるので、他のタブ(Distribution等)を選択後、適当な時間待ってから「Development」タブを選択する。<br />
<br />
7. 「Status」が「Issued」に変わり、「Download」ボタンが押せるようになっているので、クリックして証明書(ios_development.cer)をダウンロードする。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-cEwey0uuk1k/T_W8NlUKyBI/AAAAAAAAAcI/XIdvzVMYEGs/s1600/7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-cEwey0uuk1k/T_W8NlUKyBI/AAAAAAAAAcI/XIdvzVMYEGs/s1600/7.png" /></a></div>
<br />
<br />
8. ダウンロードした証明書(ios_development.cer)ファイルをダブルクリックする。(キーチェーンアクセス.appで新しい有効期限の証明書になっていることを確認する。)<br />
<br />
9. 「Distribution」タブをクリックし、「Revoke」をクリック。確認画面で「OK」を押して期限切れ間近(または既に期限切れになっている)Distribution用証明書を削除する。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-GLqqdcQD_MY/T_W8OMUt9jI/AAAAAAAAAcQ/leTpaLx2kjU/s1600/9.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-GLqqdcQD_MY/T_W8OMUt9jI/AAAAAAAAAcQ/leTpaLx2kjU/s1600/9.png" /></a></div>
<br />
<br />
10. 「Request Certificate」ボタンが押せるようになっているのでクリックする。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-qlGbHqBSLRM/T_W8KiNoJpI/AAAAAAAAAbk/9RlNjmWwWTs/s1600/10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-qlGbHqBSLRM/T_W8KiNoJpI/AAAAAAAAAbk/9RlNjmWwWTs/s1600/10.png" /></a></div>
<br />
<br />
11. 「ファイルを選択」をクリックする。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-f-87RY2qVdY/T_W8LO96YXI/AAAAAAAAAbo/WR2dnIM6Isk/s1600/11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-f-87RY2qVdY/T_W8LO96YXI/AAAAAAAAAbo/WR2dnIM6Isk/s1600/11.png" /></a></div>
<br />
<br />
12. 2で書き出したファイルを選択し、「submit」ボタンをクリックする。<br />
<br />
13. 証明書の「Status」が「Pending」になるので、他のタブ(Development等)を選択後、適当な時間待ってから「Distribution」タブを選択する。<br />
<br />
14. 「Status」が「Issued」に変わり、「Download」ボタンが押せるようになっているので、クリックして証明書(ios_distribution.cer)をダウンロードする。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-qNOsRIp7Tmk/T_W8L65s-bI/AAAAAAAAAbw/0nHZn0ZyQTE/s1600/14.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-qNOsRIp7Tmk/T_W8L65s-bI/AAAAAAAAAbw/0nHZn0ZyQTE/s1600/14.png" /></a></div>
<br />
<br />
15. ダウンロードした証明書(ios_distribution.cer)ファイルをダブルクリックする。(キーチェーンアクセス.appで新しい有効期限の証明書になっていることを確認する。)<br />
<br />
16. 以上で終了です。App IDとDevice IDは変更する必要はありませんが、プロビジョニングプロファイルは再作成&ダウンロードする必要があります。<br />
<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-78737429050869161762012-06-04T18:14:00.000+09:002012-06-04T18:19:22.498+09:00iOSアプリの証明書まとめiOSアプリを実機で動作させるには、iOS Developer Centerでいくつか証明書を作成・登録する必要があります。<br />
以前、アップルのマニュアルなどを見て設定は行っているのですが、1年ごとの更新の度に忘れてしまうのでまとめておきます。<br />
<br />
まずは概要からです。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-QDdzcahDIiI/T8x6C_0cylI/AAAAAAAAAao/OSnzTKsedSY/s1600/iOS%E3%82%A2%E3%83%95%E3%82%9A%E3%83%AA%E8%A8%BC%E6%98%8E%E6%9B%B8%E6%A6%82%E8%A6%81.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="http://1.bp.blogspot.com/-QDdzcahDIiI/T8x6C_0cylI/AAAAAAAAAao/OSnzTKsedSY/s640/iOS%E3%82%A2%E3%83%95%E3%82%9A%E3%83%AA%E8%A8%BC%E6%98%8E%E6%9B%B8%E6%A6%82%E8%A6%81.png" width="637" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
以下、上の概要の手順を、1つずつ少し詳しく書いたものです。</div>
<div class="separator" style="clear: both; text-align: left;">
まず、証明書署名要求ファイルの登録です。</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-VIsl3dCUse4/T8x7ORBTfNI/AAAAAAAAAaw/CJ7TcVhTUX8/s1600/%E8%A8%BC%E6%98%8E%E6%9B%B8%E3%81%AE%E6%B5%81%E3%82%8C1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="346" src="http://4.bp.blogspot.com/-VIsl3dCUse4/T8x7ORBTfNI/AAAAAAAAAaw/CJ7TcVhTUX8/s640/%E8%A8%BC%E6%98%8E%E6%9B%B8%E3%81%AE%E6%B5%81%E3%82%8C1.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
次に、デバイスの登録です。</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-hI7LFQgJkvU/T8x7PLjGrkI/AAAAAAAAAa0/v8WH6Ud5PQQ/s1600/%E8%A8%BC%E6%98%8E%E6%9B%B8%E3%81%AE%E6%B5%81%E3%82%8C2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="384" src="http://1.bp.blogspot.com/-hI7LFQgJkvU/T8x7PLjGrkI/AAAAAAAAAa0/v8WH6Ud5PQQ/s640/%E8%A8%BC%E6%98%8E%E6%9B%B8%E3%81%AE%E6%B5%81%E3%82%8C2.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
次に、アプリケーションの登録です。</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-ncN4RFff4I8/T8x7P9ZNp8I/AAAAAAAAAa8/7Nprl9NxDBo/s1600/%E8%A8%BC%E6%98%8E%E6%9B%B8%E3%81%AE%E6%B5%81%E3%82%8C3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="368" src="http://3.bp.blogspot.com/-ncN4RFff4I8/T8x7P9ZNp8I/AAAAAAAAAa8/7Nprl9NxDBo/s640/%E8%A8%BC%E6%98%8E%E6%9B%B8%E3%81%AE%E6%B5%81%E3%82%8C3.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
次に、プロビジョニングプロファイルの登録です。</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-B42H1STIRkk/T8x7QoZfC2I/AAAAAAAAAbE/xXwUpxzIAHs/s1600/%E8%A8%BC%E6%98%8E%E6%9B%B8%E3%81%AE%E6%B5%81%E3%82%8C4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="368" src="http://4.bp.blogspot.com/-B42H1STIRkk/T8x7QoZfC2I/AAAAAAAAAbE/xXwUpxzIAHs/s640/%E8%A8%BC%E6%98%8E%E6%9B%B8%E3%81%AE%E6%B5%81%E3%82%8C4.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
最後に、ビルドします。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-5nLPATuUScs/T8x7RP8aLMI/AAAAAAAAAbI/4ib9EPnFC5g/s1600/%E8%A8%BC%E6%98%8E%E6%9B%B8%E3%81%AE%E6%B5%81%E3%82%8C5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="288" src="http://4.bp.blogspot.com/-5nLPATuUScs/T8x7RP8aLMI/AAAAAAAAAbI/4ib9EPnFC5g/s640/%E8%A8%BC%E6%98%8E%E6%9B%B8%E3%81%AE%E6%B5%81%E3%82%8C5.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-88396766569672445862012-01-20T08:47:00.000+09:002012-01-20T08:47:46.868+09:00isaって何?デバッグをしていると、よくisaという変数を目にすることがあります。<br />
isaは、NSObjectが持っている構造体で、スーパークラスへのポインタや、メソッドの情報を保持しています。<br />
<br />
例えば、NSMutableStringはNSStringクラスを継承したクラスですが、NSMutableStringのisa変数の中にNSStringへのポインタを保持しています。<br />
<br />
また、NSMutableStringは「stringByAppendingString:」というメソッドを持っていますが、このメソッドの情報を以下の様にNSMutableStringのisa変数に格納しています。<br />
<br />
セレクタ メソッド名の文字列<br />
22 stringByAppendingString:<br />
33 メソッドA<br />
44 メソッドB<br />
・ ・<br />
・ ・<br />
・ ・<br />
<br />
上の例のセレクタは説明の為適当な値です。また、セレクタはchar*型ですが、実際にはint型の数値が入ります。<br />
Objective-Cのコンパイラは、メソッドの呼び出しを以下の様にC言語のコードに展開します。<br />
<br />
[objA stringByAppendingString:objB];<br />
↓<br />
objc_msgSend(objA, 22, objB);<br />
<br />
「objc_msgSend」関数は、objAにあるセレクタ22に対してobjBを送信してくれるC言語の関数です。<br />
objc_msgSend関数はobjAの中にあるisa変数を参照して、指定されたセレクタ(22)を検索します。そしてそこにあったメソッドにobjBを渡すとともに呼び出してくれます。<br />
ここで該当するセレクタがisaの中に見つからなかった場合は、スーパークラスであるNSStringのポインタを取得し、NSStringのisaに対して同様の処理を行います。<br />
NSStringでも見つからなければ更にその継承元・・という風に辿っていき、最終的にNSObjectでも見つからなければ例外を発生させるという流れになります。<br />
<br />
このような処理を行うことで、Objective-Cではプログラム実行時に動的にメソッドを入れ替えることがし易くなっているのです。<br />
<br />
ただし、C言語のように直にポインタを呼び出すとかではないので動作は遅くなるはずです。また、C++言語と比べてもObjective-Cは検索処理などが行わる為、動作はかなり遅くなるはずです。(C++言語はクラスメソッドのジャンプテーブルを参照するのでC言語より数ステップ程度動作は遅くなります。)<br />
多分ですが、メソッド呼び出しだけを見る限りC言語よりも数十倍〜数百倍は遅くなっているはずです。(遅さを補っても余りある利便性があるということです。)Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-59335200072698154662011-11-23T12:53:00.001+09:002011-11-23T12:55:01.293+09:00UISearchBarに画像を設定するUISearchBarに画像を設定するには、UISearchBarBackgroundビューを入れ替えてやります。<br />
<br />
<hr>// searchBarはUISearchBarのインスタンス<br />
for (UIView *v in searchBar.subviews) {<br />
if ([NSStringFromClass(v.class) isEqualToString:@"UISearchBarBackground"]) {<br />
[v removeFromSuperview];<br />
}<br />
}<br />
UIImage *img = [UIImage imageNamed:@"custom_searchbar"];<br />
UIImageView *iv = [[UIImageView alloc] initWithImage:img];<br />
[searchBar insertSubview:iv atIndex:0];<br />
[iv release];<br />
<hr><br />
1.UISearchBarのサブビューからUISearchBarBackgroundを探し、サーチバーから削除します。<br />
2.UISearchBarBackgroundが合った場所にUIImageViewを挿入すれば画像が表示されるようになります。<br />
(custom_searchbarは背景に使用する画像ファイル名です。)Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-52834088345982119442011-07-12T11:49:00.000+09:002013-04-13T17:27:24.002+09:00UILocalNotificationUILocalNotificationは、アプリケーションが終了した状態でも指定時間になったらメッセージを表示する等の動作を行わせることができる機能です。<br />
<br />
<hr />
// ローカル通知を作成<br />
UILocalNotification *ln = [[UILocalNotification alloc] init];<br />
<br />
NSDate *dt;<br />
dt = [NSDate dateWithTimeIntervalSinceNow:60]; // 60秒後に表示<br />
<br />
// 通知時刻を設定<br />
[ln setFireDate:dt];<br />
<br />
// タイムゾーンを設定<br />
[ln setTimeZone:[NSTimeZone localTimeZone]];<br />
<br />
// メッセージを設定<br />
[ln setAlertBody:@"起きて"];<br />
<br />
// サウンド設定<br />
[ln setSoundName:UILocalNotificationDefaultSoundName];<br />
<br />
// ボタンタイトルの設定<br />
[ln setAlertAction:@"Open"];<br />
<br />
// ローカル通知を登録<br />
[[UIApplication sharedApplication] scheduleLocalNotification:ln];<br />
<br />
[ln release];<br />
<hr />
上記例の処理をアプリに行わせて終了させると、アプリが動作していなくても60秒後に「起きて」というメッセージが表示されるようになります。<br />
<br />
サウンド設定にはサウンドファイル名を拡張子付きで指定しますが、再生時間が30秒未満、かつ以下の形式でないと無効となり、システムのデフォルトサウンドが再生されてしまうので注意が必要です。<br />
<br />
●リニアPCM<br />
● MA4(IMA/ADPCM)<br />
● µLaw<br />
● aLaw<br />
<br />
上記ファイルはaiff, caf, wavのファイルです。<br />
<br />
また、applicationIconBadgeNumberプロパティに任意の数字を指定することで、メールアプリなどでよく見られるようなバッヂが表示されるようになります。<br />
<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-79966198316813584202011-07-07T11:46:00.002+09:002011-07-07T11:50:15.360+09:00特殊フォルダのパスを取得するドキュメントフォルダなどのパスの一覧を取得するには、NSSearchPathForDirectoriesInDomain関数を使用します。<br />
<br />
<hr />NSArray * NSSearchPathForDirectoriesInDomains (<br />
NSSearchPathDirectory directory,<br />
NSSearchPathDomainMask domainMask,<br />
BOOL expandTilde<br />
);<br />
<hr /><br />
NSSearchPathDirectoryは、取得するパスの種類を指定します。<br />
<table border="2"><tbody>
<tr><td>定数</td><td>内容</td></tr>
<tr><td>NSApplicationDirectory</td><td>アプリケーションディレクトリ<br />
(/Applications)</td></tr>
<tr><td>NSDemoApplicationDirectory</td><td>デモバージョンアプリケーション<br />
ディレクトリ<br />
(/Demos)</td></tr>
<tr><td>NSDeveloperApplicationDirectory</td><td>開発用アプリケーションディレクトリ<br />
(/Developer/Applications)</td></tr>
<tr><td>NSAdminApplicationDirectory</td><td>システムとネットワーク管理者用<br />
アプリケーションディレクトリ<br />
(/Administration)</td></tr>
<tr><td>NSLibraryDirectory</td><td>ライブラリディレクトリ</td></tr>
<tr><td>NSDeveloperDirectory</td><td>開発ツールディレクトリ(/Developer)</td></tr>
<tr><td>NSUserDirectory</td><td>ユーザディレクトリ(/Users)</td></tr>
<tr><td>NSDocumentationDirectory</td><td>ドキュメンテーションディレクトリ<br />
(/Library/Documentation)</td></tr>
<tr><td>NSDocumentDirectory</td><td>ドキュメントディレクトリ</td></tr>
<tr><td>NSCoreServiceDirectory</td><td>コアサービスディレクトリ<br />
(/System/Libary/CoreServices)</td></tr>
<tr><td>NSAutosavedInformationDirectory</td><td>自動保存ディレクトリ<br />
(~/Library/Autosave Information)</td></tr>
<tr><td>NSDesktopDirectory</td><td>デスクトップ</td></tr>
<tr><td>NSCachesDirectory</td><td>キャッシュディレクトリ<br />
(Library/Caches)</td></tr>
<tr><td>NSApplicationSupportDirectory</td><td>アプリケーションサポート<br />
ディレクトリ<br />
(Library/Application Support)</td></tr>
<tr><td>NSDownloadsDirectory</td><td>ダウンロードディレクトリ</td></tr>
<tr><td>NSInputMethodsDirectory</td><td>インプットメソッドディレクトリ<br />
(Library/Input Methods)</td></tr>
<tr><td>NSMoviesDirectory</td><td>ムービーディレクトリ(~/Movies)</td></tr>
<tr><td>NSMusicDirectory</td><td>ミュージックディレクトリ(~/Musics)</td></tr>
<tr><td>NSPicturesDirectory</td><td>ピクチャディレクトリ(~/Picture)</td></tr>
<tr><td>NSPrinterDescriptionDirectory</td><td>プリンタ情報ディレクトリ<br />
(Library/Printers/PPDs)</td></tr>
<tr><td>NSSharedPublicDirectory</td><td>パブリックディレクトリ(~/Public)</td></tr>
<tr><td>NSPreferencePanesDirectory</td><td>プリファレンスペインディレクトリ<br />
(~/PreferencePanes)</td></tr>
<tr><td>NSItemReplacementDirectory</td><td>「NSFileManager」クラスの<br />
「URLForDirectory:inDomain<br />
:appropriateForURL:create:error:」<br />
メソッドと組み合わせて使用する定数</td></tr>
<tr><td>NSAllApplicationsDirectory</td><td>全アプリケーションディレクトリ</td></tr>
<tr><td>NSAllLibrariesDirectory</td><td>全ライブラリディレクトリ</td></tr>
</tbody> </table><br />
<br />
NSSearchPathDomainMaskは、取得するパスの範囲を指定します。<br />
<table border="2"><tbody>
<tr><td>定数</td><td>内容</td></tr>
<tr><td>NSUserDomainMask</td><td>ユーザーのホームディレクトリ</td></tr>
<tr><td>NSLocalDomainMask</td><td>ローカルマシン内</td></tr>
<tr><td>NSNetworkDomainMask</td><td>ネットワーク内(/Network等)</td></tr>
<tr><td>NSSystemDomainMask</td><td>システム内(/System)</td></tr>
<tr><td>NSAllDomainsMask</td><td>全てのドメイン</td></tr>
</tbody> </table><br />
<br />
expandTildeは、パスが長い場合にチルダをフルパスにするかを指定します。<br />
<br />
NSString文字の配列がNSArrayに返却されます。Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-84805239940893567782011-07-07T10:52:00.001+09:002011-07-07T10:53:11.068+09:00アプリで作成したドキュメントをMacと共有できるようにするiPhoneアプリで作成したドキュメントをMacと共有するには、アプリのInfo.plistファイルを編集します。<br />
<br />
ビルド設定の「Info」タグに行を追加し、「Application supports iTunes file sharing」 を追加し、タイプをBOOL型にしてYESにします。<br />
<br />
これでiTunesのAppタグからアプリのドキュメントを共有できるようになります。Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-50630928045350803322011-07-05T10:50:00.002+09:002011-10-04T21:11:30.191+09:00codesign failedアップルのデベロッパー登録は1年毎に更新する必要がありますが、この時アップルの説明書の通りに更新しても、いざ新しくビルドを行おうとする時に以下のエラーが出てハマる場合があります。<br />
<br />
<hr />iPhone Developer: ・・・・・・・・: ambiguous (matches "iPhone Developer: ・・・・・・・・・" in /Library/Keychains/System.keychain and "iPhone Developer: ・・・・・・・・・" in /Users/・・・・・/Library/Keychains/login.keychain)<br />
Command /usr/bin/codesign failed with exit code 1<br />
<hr />・・・の部分は開発者ごとに異なります。<br />
<br />
この原因はキーチェインに以前登録した古い開発者用の証明書が残っていて、「証明書ユーティリティが新しいのと古いのとどっちを使っていいのか分からない」のが原因みたいです。<br />
この場合、 【アプリケーション】→【ユーティリティ】にあるキーチェーンアクセスを起動してみると、☓印がついた証明書(期限切れの証明書)があると思うので、削除します。<br />
<br />
☓印がついた証明書が見えない場合もあり(私はこれでハマりました)、この場合は検索ボックスで「iphone」と検索すると表示されるようになります。<br />
<br />
<br />
【追記】<br />
xcode4.0.1を使っている時にエラーが出る場合もあります。<br />
この場合、xcode4.1がひっそりとリリースされていて、をれを使えば直る場合があります。<br />
バージョン4以降は【product】→【edit scheme】でArchiveのBuild ActionをDistributionに変えておくのも忘れないようにしましょう。<br />
<br />
【更に追記】<br />
同じcodesignエラーですが、エラーの内容が以下の様になる場合があります。<br />
<hr /><blockquote> <code>Code sign <span class="highlight">error</span>: The identity "<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone"><span class="highlight">iPhone</span></a> <span class="highlight">Developer</span>" <span class="highlight">doesn't</span> <span class="highlight">match</span> <span class="highlight">any</span> <span class="highlight">valid</span> certificate / private <a class="keyword" href="http://d.hatena.ne.jp/keyword/key"><span class="highlight">key</span></a> <span class="highlight">pair</span> in the default <span class="highlight">key</span>chain.</code> </blockquote><hr />これはキーチェインがデフォルトになっていないからだそうです。<br />
【アプリケーション】→【ユーティリティ】でキーチェインアクセスを起動し、左上の窓からログインを右クリック。【キーチェーン”ログイン”をデフォルトにする】を選択するとエラーが出なくなります。Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-73829016761739989322011-06-04T10:26:00.001+09:002011-06-04T10:44:19.993+09:00実機とシミュレータで挙動を変えるごくまれにですが、実機では動くのにシミュレータでは動かない命令があります。<br />
<br />
例えば、iAd広告を表示する時、ADBannerViewのrequiredContentSizeIdentifiersプロパティを設定しようとすると何故かシミュレータでは動きません。<br />
<br />
このような場合等に実機とシミュレータで挙動を切り替える必要が出てきますが、シミュレータ上だけで有効になるデファイン値が用意されています。 <br />
<br />
<hr />#ifndef TARGET_IPHONE_SIMULATOR<br />
・<br />
・<br />
#endif<br />
<hr />#ifndefで囲んだ部分は、シミュレータ用のビルドではビルドされません。Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-40846266278552654642011-04-18T01:09:00.000+09:002011-04-18T01:09:15.482+09:00Subviewを最前面・再背面に移動する特定のSubviewを最前面に移動する場合、bringSubviewToFrontメソッドを使用します。<br />
逆に、再背面に移動したい場合、sendSubviewToBackメソッドを使用します。<br />
<br />
<hr />[self.view bringSubviewToFront:最前面に移動したいView];<br />
[self.view sendSubviewToBack:最背面に移動したいView]<br />
<hr />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-72110261475487014892011-03-25T11:34:00.001+09:002011-03-25T11:38:58.449+09:00GameKitで小数を送信するGameKitでスコアやランキングデータを送信する時、Appleのドキュメントでは整数(int64)のデータを送信する方法しか載っていないので、タイムなどの小数(45.67秒等)を送信したい場合は一瞬戸惑います。<br />
<br />
小数を送信する場合、NSNumberクラスを使用します。<br />
NSNumberクラスはBoolやdouble,Int型などのprimitive型をオブジェクトにしたい場合に使用する便利なクラスです。<br />
<br />
<hr>-(void)reportScores:(double)score forCategory:(NSString*)category<br />
{<br />
scoreReporter = [[[GKScore alloc] initWithCategory:category] autorelease];<br />
NSNumber *numScore = [NSNumber numberWithDouble:round(score * 100)];<br />
scoreReporter.value = numScore.intValue;<br />
[scoreReporter reportScoreWithCompletionHandler:^(NSError* error) {<br />
if (error != nil) {<br />
// エラー処理<br />
return;<br />
}<br />
}];<br />
}<br />
<hr><br />
Appleのドキュメントに載っているスコア送信例を、double型を送信するように変更してあります。<br />
上の例では、少数以下2桁を送信する例です。<br />
引数のdouble型scoreを整数にしたいので100倍してNSNumber型のオブジェクトにします。<br />
その後、そのint値(64ビット値)をGKScoreオブジェクトに設定しています。<br />
勿論、iTunesでリーダーボードのスコア設定をDecimal小数2桁等、小数を扱うように設定しておく必要はあります。<br />
<br />
後はAppleドキュメントに載っている様にランキング受信処理でGKScoreのformattedValueプロパティを参照すれば、iTunesで設定したフォーマットでNSString文字列が取得できます。Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-88358369253998625812011-03-02T23:03:00.000+09:002011-03-02T23:03:38.561+09:00IOS4以降のアニメーションIOS4以降のアニメーションは、[UIView animateWithDulation:delay:options:animations:completion:]を使います。IOS4以降でも従来のアニメーションは行えるようですが、非推奨となってしまったようです。<br />
もっと簡易的に使えるメソッドもありますが、これだけ覚えておけば事足りるかもしれません。<br />
<br />
<HR> [UIView animateWithDuration:0.5<br />
delay:0<br />
options:UIViewAnimationOptionCurveEaseOut<br />
animations:^{<br />
button.alpha = 0.0; // UIButtonインスタンスを徐々に透明に<br />
}<br />
completion:^(BOOL finished){<br />
button.alpha = 1.0f; // buttonを現す<br />
}];<br />
<HR><br />
第一引数はアニメーションにかける時間を指定します。上記例では0.5秒間でボタンを徐々に透明にしていきます。<br />
delayはアニメーションを開始する時間を指定します。上記例では0なので即時アニメーション開始です。<br />
optionsはアニメーションの動作のオプションです。上記例ではEaseOutで徐々に速度を落としてアニメーションをさせています。<br />
animationsが実際のアニメーションの指定です。<br />
completionはアニメーションが終了した時に呼び出される処理です。上記例では徐々に透明になったボタンの姿を再度現すようにしています。Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-47405092568543187282011-02-19T00:42:00.000+09:002011-02-19T00:42:59.075+09:00プロビジョニングプロファイルプロビジョニング等セキュリティ関連の情報をなんとなくまとめてみました。<br />
<br />
<TABLE border="1"><TBODY>
<TR><TD>ID/プロファイル</TD><TD>内容</TD></TR>
<TR><TD>Bundle ID</TD><TD>アプリケーション固有のID。アプリケーション1つに1個。(例:com.apple.iTunes)</TD></TR>
<TR><TD>App ID</TD><TD>開発者がアプリケーションに「Push Notification」「in App Purchase」「Game Center」等へのアクセスを許可・禁止設定する為の挙動を管理するID。<br />
キーチェインでのアクセス識別子となり、それぞれのアプリケーションの挙動を制御する。<br />
アプリケーションの「挙動」について1つ付けられるIDの為、複数アプリケーションをまとめて指定できるワイルドカード指定が認められている。(例:com.apple.*)<br />
ただし、GameCenter等のサービスを許可する時はワイルドカード指定は使えない。つまり各アプリケーションに1個のApp IDを付けなければならない。</TD></TR>
<TR><TD>プロビジョニングプロファイル</TD><TD>デバイスにインストールされて、実行時に正規のルートからインストールされたか確認するための情報を保持するファイル。(App ID/デバイスID/開発者IDを保持)</TD></TR>
</TBODY>
</TABLE>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-23667475384147655972011-02-04T10:35:00.001+09:002011-02-04T10:37:58.039+09:00メモリリークしない為に その1NSMutableArrayやNSArrayをautorelease以外でメモリ確保した場合、配列を解放しても要素の解放処理が呼び出されるわけではありません。<br />
<br />
<hr />ar1 = [[NSMutableArray alloc] initWithObjects:@"TEST1", @"TEST2", @"TEST3", nil];<br />
ar2 = [[NSMutableArray alloc] initWithObjects:[SomeClass alloc]<br />
, [SomeClass alloc]<br />
, [SomeClass alloc], nil];<br />
<br />
arrays = [[NSArray alloc] initWithObjects:ar1, ar2, nil];<br />
・<br />
・<br />
・<br />
[arrays release]; // ar1 / ar2 とSomeClassがメモリリーク<br />
<hr /><br />
上記例では、「arrays」の解放しか行っていないので、「ar1」「ar2」「SomeClass」が全てメモリリークとなります。<br />
「TEST1」「TEST2」「TEST3」の文字列はautoreleaseされるので解放の必要はありません。<br />
<br />
要素を全て解放すればメモリリークしなくなります。<br />
<hr />[ar1 release]; // ar1を解放<br />
// ar2の要素を解放<br />
for (int i = 0; i < ar2.count; i++) {<br />
SomeClass* tmp = [ar2 objectAtIndex:i];<br />
[tmp release];<br />
}<br />
[ar2 release]; // ar2を解放 [arrays release]; // arraysを解放 <br />
<hr />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-17302194094192693552011-01-18T10:31:00.000+09:002011-01-18T10:31:58.843+09:00UINavigationBarUINavigationBarをUINavigationControllerではなく、UIViewController等に独自に実装する場合、以下のようにします。<br />
<br />
<HR> // ナビゲーションバーを生成<br />
UINavigationBar* navBarTop = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, 320, 40)];<br />
navBarTop.alpha = 0.7f;<br />
<br />
// ナビゲーションアイテムを生成<br />
UINavigationItem* title = [[UINavigationItem alloc] initWithTitle:@"Title"];<br />
<br />
// 戻るボタンを生成<br />
UIBarButtonItem* btnItemBack = [[UIBarButtonItem alloc] initWithTitle:@"Back" style:UIBarButtonItemStyleBordered target:self action:@selector(clickBack:)];<br />
<br />
// ナビゲーションアイテムの右側に戻るボタンを設置<br />
title.rightBarButtonItem = btnItemBack;<br />
<br />
// ナビゲーションバーにナビゲーションアイテムを設置<br />
[navBarTop pushNavigationItem:title animated:YES];<br />
<br />
// ビューにナビゲーションアイテムを設置<br />
[self.view addSubview:navBarTop];<br />
<HR><br />
ナビゲーションアイテムを生成するときにタイトルを設定します。上記では「Title」という文字列を設定しました。これで画面上部に大きな文字で「Title」と表示されます。<br />
<br />
また、ナビゲーションアイテムにiPhoneアプリでよく見られる、画面右上と左上に表示されるボタンなどを設置します。<br />
上記では右上に「戻る」ボタンを追加していますが、leftBarButtonItemプロパティに設置すれば、左上にも表示できます。<br />
<br />
UIBarButtonItemはカスタマイズ可能で、例えば<br />
<HR> // segmentedControlはUISegementedControlのインスタンス<br />
UINavigationItem* title = [[UINavigationItem alloc] initWithCustomView:segmentedControl];<br />
<HR>等とすれば、ナビゲーションバーの内部にUISegmentedControlのインスタンスや、その他スライダー等、いろいろと設置することが可能なようです。<br />
<br />
最後に「pushNavigationItem」でナビゲーションバーにアイテムを設置します。<br />
「addSubview」を使いそうになりますので注意が必要です。Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-82408099663680308852011-01-09T10:04:00.000+09:002011-01-09T10:04:08.997+09:00連続アニメーション複数のアニメーションを連続して再生させるには、1つのアニメーションの終了を検知し、その後、続きのアニメーションを再生させます。<br />
<br />
アニメーションの終了は「setAnimationDidStopSelector:finished:context:」でアニメーションの終了メソッドを登録しておきます。<br />
<br />
<HR> [UIView beginAnimations:@"Animation1" context:nil];<br />
[UIView setAnimationDuration:1.0];<br />
[UIView setAnimationDelegate:self];<br />
[UIView setAnimationDidStopSelector:@selector(animationFinished:finished:context:)];<br />
// imgViewはUIImageViewのインスタンス<br />
imgView.frame = CGRectMake(100, 200, imgView.frame.size.width, imgView.frame.size.height);<br />
[UIView commitAnimations];<br />
・<br />
・<br />
・<br />
- (void)animationFinished:(NSString *)animationID finished:(BOOL)finished context:(void *)context<br />
{<br />
if ([animationID isEqualToString:@"Animation1"]) {<br />
[UIView beginAnimations:@"Animation2" context:nil];<br />
[UIView setAnimationDuration:0.5];<br />
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];<br />
imgView.frame = CGRectMake(100, 50, imgView.frame.size.width, imgView.frame.size.height);<br />
[UIView commitAnimations];<br />
<HR><br />
上記例では、イメージ(imgView)を1秒間かけて(100, 200)に移動した後、続いて0.5秒間かけて(100, 50)に移動させます。Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-65503427884916230782010-12-10T23:24:00.002+09:002010-12-10T23:36:31.394+09:00変更される可能性のあるクラスのメソッドを呼び出す任意のクラスのメソッドを呼び出すには下記のように<br />
<hr>[testClass testMethod];<br />
<hr>等と呼び出せば良いですが、例えば上記の「testClass」がプログラム実行中に動的に変更されてしまう場合は以下のようにします。<br />
<br />
<hr>objc_object* ptrClass = testClass;<br />
SEL ptrMethod = @selector(testMethod:);<br />
[ptrClass performSelector:ptrMethod withObject:パラメータ]; // 呼び出し<br />
・<br />
・<br />
ptrClass = testClass2; // 動的にクラスを変更<br />
ptrMethod = @selector(testMethod2:); // 動的にメソッドを変更<br />
[ptrClass performSelector:ptrMethod withObject:パラメータ]; // 呼び出し<br />
<hr><br />
C++に慣れた方であればポインタ変数を任意のクラスにキャストしてメソッド呼び出しを行いそうですが、Objective-Cでは上記のようにします。<br />
<br />
なお、withObjectでパラメータを複数渡したい場合は、複数オブジェクトを格納するNSArrayオブジェクトを渡すようにします。<br />
また、afterDelay:で秒数を指定すれば、任意の秒数後にメソッド呼び出しが行われます。Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-84694584455325875312010-12-10T17:57:00.001+09:002010-12-10T17:58:05.228+09:00NULLとnilNULLとnilはどちらも値としては同じ0のようです。<br />
<br />
しかし、NULLはポインタに対して空という意味であり、<br />
nilはオブジェクトに対して空という意味を表すそうです。<br />
<br />
CやC++言語でBOOL型に0かFALSEを使いましたが、それと似たような感じです。<br />
現状ではNULLでもnilでもどちらでも良さそうですが、今後問題とならないように、きちんと使い分けをしておいた方が良いかもしれません。<br />
<br />
ところで、NSMutableArrayにnilを追加することはできないようですが、NSNullという空の意味を表すオブジェクトが用意されており、これを使えば追加することができるそうです。Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7725244335912421956.post-26240639802553001952010-12-08T09:27:00.000+09:002010-12-08T09:27:37.979+09:00独自のUIViewを作る独自のUIViewを作るには、描画処理を独自に作成する必要があります。<br />
<br />
UIViewでは描画を行う時に「drawRect:(CGRect)rect」メソッドが呼び出されます。<br />
<br />
このメソッドをオーバーライドして独自の描画処理を行わせます。<br />
<br />
独自のUIViewを作成するのは、割と低レベル(OSに近くなると言う意味)なことですので、C言語の関数で描画を行う必要があります。また、フォントの扱い等、多少クセがあるようです。<br />
<br />
<HR>-(void)drawRect:(CGRect)rect<br />
{<br />
// 描画範囲を取得<br />
CGRect parentViewBounds = self.bounds;<br />
<br />
// ビューのコンテクストを取得<br />
CGContextRef ctx = UIGraphicsGetCurrentContext();<br />
<br />
// 塗りつぶし色設定<br />
CGContextSetFillColorWithColor(ctx, [UIColor whiteColor].CGColor);<br />
<br />
// 塗りつぶし色でビューを塗りつぶし<br />
CGContextFillRect(ctx, CGRectMake(0, 0, parentViewBounds.size.width, parentViewBounds.size.height));<br />
<br />
// 描画設定終了<br />
CGContextClosePath(ctx);<br />
<br />
// パスを描画<br />
CGContextStrokePath(ctx);<br />
}<br />
<HR>UIViewのboundプロパティは、自身のUIViewの描画範囲をCGRect構造体で取得するプロパティです。<br />
<br />
UIGraphicsGetCurrentContext()関数は、自身のUIViewインスタンスのコンテキストを取得する関数です。後の描画関数で引数として使用されます。<br />
<br />
上記では、色の設定関数(CGContextSetFillColorWithColor)や塗りつぶし関数(CGContextFillRect)を呼び出していますが、実際の描画は最後に呼び出している描画関数(CGContextStrokePath)で行われます。色やパスの設定関数を呼び出した時点ではないことに少し注意が必要です。<br />
例えば、色を何回変更してパスの設定を行ったとしても、実際の変更が行われるのはCGContextStrokePath等の描画関数を呼び出した時点ですので、途中の色設定は無視されて、最後の色設定のみが反映されることになります。<br />
<br />
また、マウス操作などでリアルタイムに描画を変更したい場合などは、「setNeedsDisplayInRect」メソッドを呼び出せば、いつでもdrawRectメソッドがCallbackされます。<br />
<HR> [self setNeedsDisplayInRect:self.frame];<br />
<HR><br />
<br />
描画を行う関数は大量にありますが、ほんの一部を抜き出すと、以下のようになります。<br />
もっと知りたい方は、ドキュメントをCGContextで検索すればたくさん出てきます。<br />
<br />
<TABLE border="1"><TR><TD>関数</TD><TD>概要</TD>
<TR><TD>CGContextAddLines</TD><TD>線の描画設定</TD>
<TR><TD>CGContextAddPath</TD><TD>パスの描画設定</TD>
<TR><TD>CGContextSetStrokeColorWithColor</TD><TD>線の色設定</TD>
<TR><TD>CGContextSetLineWidth</TD><TD>線の太さ設定</TD>
<TR><TD>CGContextSetFillColor</TD><TD>塗りつぶし色設定</TD>
<TR><TD>CGContextShowTextAtPoint</TD><TD>テキストの設定</TD>
<TR><TD>CGContextSelectFont</TD><TD>フォントの設定</TD>
</TR>
</TABLE><br />
上記表は描画関数のほんの一部です。上記表にはありませんが、イメージを描画したり、カーブ線を描画する関数もあるようです。Unknownnoreply@blogger.com0