query: tag:objc

deprecatedになっているNSString.stringWithCString:length:を使っている古いコードがあり、新しい記述に書き換えようとしたのですが、documentによると length 指定ができない NSString.stringWithCString:encoding:
を使えという指示しかないようです。

等価なコードで置き換えるとしたらこんな感じかな?

objective-c>>
//[NSString stringWithCString:bytes length:length];
[[[NSString alloc] initWithData:
[NSData dataWithBytes:bytes length:length]
encoding:NSUTF8StringEncoding] autorelease];
<<--

ARC使用でしたら autorelease は不要ですね。

posted by genki genki on Wed 21 Dec 2011 at 00:10 with 0 comments

ちょっと必要だったので作りました。

ss

CoreGraphicsを使って、指定したCGRectの中に、指定した太さの×印(Cross Sign)を描画するためのPathを生成します。

objective-c>>
void PDPathAddCrossSign(CGMutablePathRef path, CGRect rect, CGFloat thickness)
{
CGFloat diff = rect.size.width - rect.size.height;
rect = CGRectDeflateRect(rect, MAX(0, diff/2), MAX(0, -diff/2));
CGFloat radius = rect.size.width/2;
CGFloat d = sqrt(2)*thickness/2;
CGFloat cx = CGRectGetMidX(rect), cy = CGRectGetMidY(rect);
CGAffineTransform transform = CGAffineTransformMakeTranslation(cx, cy);
CGPathMoveToPoint(path, &transform, d, 0);
for(int i = 0; i < 4; ++i){
CGPathAddLineToPoint(path, &transform, radius, radius - d);
CGPathAddLineToPoint(path, &transform, radius - d, radius);
CGPathAddLineToPoint(path, &transform, 0, d);
transform = CGAffineTransformRotate(transform, M_PI/2.0f);
}
CGPathCloseSubpath(path);
}
<<--

中で呼び出してるCGRectDeflateRectは以下のようなものです。

objective-c>>
CGRect CGRectInflateRect(CGRect rect, CGFloat width, CGFloat height)
{
rect.origin.x -= width;
rect.origin.y -= height;
rect.size.width += width2;
rect.size.height += height
2;
return rect;
}

CGRect CGRectDeflateRect(CGRect rect, CGFloat width, CGFloat height)
{
return CGRectInflateRect(rect, -width, -height);
}
<<--

これを使う事で、任意の大きさ、太さ、色で×印を描画できます。

posted by genki genki on Wed 4 Mar 2009 at 00:06 with 0 comments

Objective-CでCSSでよく使うようなABCDEFFFのようなHex encodeされた形式の文字列からUIColorを生成する方法の紹介です。

objective-c>>
@interface UIColor (HexEncoding)

  • (UIColor*)colorFromString:(NSString*)string;
  • (NSString*)encodeToString;
    @end

@implementation UIColor (HexEncoding)

  • (UIColor*)
    colorFromString:(NSString*)string
    {
    NSScanner *scanner = [NSScanner scannerWithString:string];
    NSUInteger value;
    [scanner scanHexInt:&value];
    CGFloat red = ((value & 0xFF000000) >> 24) / 255.0f;
    CGFloat green = ((value & 0x00FF0000) >> 16) / 255.0f;
    CGFloat blue = ((value & 0x0000FF00) >> 8) / 255.0f;
    CGFloat alpha = ((value & 0x000000FF) >> 0) / 255.0f;
    return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
    }
  • (NSString*)encodeToString
    {
    const CGFloat *components = CGColorGetComponents(self.CGColor);
    return [NSString stringWithFormat:@"%02x%02x%02x%02x",
    (int)(components[0]*255 + 0.5f),
    (int)(components[1]*255 + 0.5f),
    (int)(components[2]*255 + 0.5f),
    (int)(components[3]*255 + 0.5f)];

}

@end
<<--

わかりやすいように、UIColorにメソッドカテゴリを追加しています。
encodeToStringのほうでは、0.5を足してroundをかけていますが、
状況に応じてfloorにしたりceilにしたりしてください。

また、この例ではComponentsのサイズが4である事を期待しています。
そうではない色を扱うときには問題が発生しますので、ご注意ください。

posted by genki genki on Fri 7 Nov 2008 at 12:10 with 0 comments

Objective-Cは、Rubyのようにメソッドの定義を書き換えたりする事ができます。

objective-c>>
#import <objc/runtime.h>

id (foo_without_bar)(id, SEL);
id foo_with_bar(id self, SEL selector)
{
/
do your work here */
return foo_without_bar(self, selector);
}

// exchange method implementation
SEL fooSelector = @selector(foo);
Method method = class_getInstanceMethod(class, fooSelector);
(IMP)&foo_without_bar =
method_getImplementation(method);
method_setImplementation(method, (IMP)foo_with_bar);
<<--

この例では、IMPの定義と同じプロトタイプのメソッドを書き換えてるので不要ですが、IMPの定義と異なるプロトタイプのメソッドを書き換える場合は、
IMPにキャストする必要があります。

また、戻り値が浮動小数型であったり、サイズが大きい構造体を返すメソッドの場合は、上記の例とは異なる方法を使う必要があるので、注意が必要です。(NSInvocationを使う必要があります)

See Also

posted by genki genki on Fri 7 Nov 2008 at 11:42 with 2 comments

UIScrollViewのscrollRectToVisible:animated:の挙動についてのメモです。

これは名前の通り、第一引数で指定したCGRectをViewの可視領域に
持って行くためのメソッドなのですが、
可視領域からはみ出すような大きなCGRectを指定した場合は、CGRectの下端が優先的に表示されるような挙動になるようです。
また、CGRectがemptyの場合は何もおこりません。

上端を優先して表示させたい場合は、
可視領域のCGRectを求めて、あらかじめ可視領域に収まるようにしてから呼び出せばOkです。

ところで、このメソッドはcontentInsetを意識してくれないようなので、
contentInsetを使っている場合は、contentInsetの分だけ広げたrectを指定してあげると良い感じになるようです。

posted by genki genki on Fri 7 Nov 2008 at 11:06 with 0 comments

たいしたものではないですが、
iPhoneアプリ開発用に
Linked ListとLRUCacheを実装したユーティリティライブラリを公開します。

http://github.com/genki/s21gutils/tree/master

本当はサードパーティフレームワークの形にしたかったんですが、
iPhoneでサポートされてないようなので、ソースとUnitTest用プロジェクトの形で公開します。

ヘッダファイルをコピーとかするのが面倒なので、
Gitでソースを管理してるプロジェクトで使う場合は、
以下のようにGit submoduleとして追加するとメンテナンスが楽かもです。

pre>>
% git submodule add http://github.com/genki/s21gutils/tree/master Classes/s21gutils
<<--

Public Domainです。無償・商用問わず自由に使ってください。
よろしくお願いします。

posted by genki genki on Sun 2 Nov 2008 at 07:55 with 0 comments

ちょっとした時間計測に使っているマクロです。

objective-c>>
#define BM_START(name) NSDate *name##_start = [NSDate new]
#define BM_END(name) NSDate *name##_end = [NSDate new];
NSLog(@"%s interval: %f", #name, [name##_end timeIntervalSinceDate:name##_start]);
[name##_start release];[name##_end release]
<<--

iPhoneアプリを開発している場合、シミュレータ上の動作時間と
実機での動作時間は全く異なるので、
実際に実機で動かしてみた場合にどの程度の時間がかかっているかを
測定するのに使っています。

objective-c>>
BM_START(something);
/* do work */
BM_END(something);
<<--

こんな感じに使います。

posted by genki genki on Sat 1 Nov 2008 at 15:11 with 0 comments