Hatena::Groupiphone-dev

iPhoneアプリ開発まっしぐら★ このページをアンテナに追加 RSSフィード

引っ越し後の日記はコチラです

tokoromのその他の日記

2010-07-11

いつのまにかインスタンス変数の記述が省略できるようになってた

| 01:19 | はてなブックマーク -  いつのまにかインスタンス変数の記述が省略できるようになってた - iPhoneアプリ開発まっしぐら★

これってはじめからでしたっけ?

プロパティを使う場合、もともと

// 定義
@interface UIViewBoundsSample : UIViewController
{
 @private
  UILabel* label0;
}

@property (nonatomic, retain) UILabel* label0;

@end

// 実装
@implementation UIViewBoundsSample

@synthesize label0;

- (void)dealloc {
  self.label0 = nil;
  [super dealloc];
}

@end

のように、

  • インスタンス変数の定義
  • @property
  • @synthesize

の3つ全てを記述しないといけなかったと思うのですが、少なくとも今つかっているXCode3.2.3だと「インスタンス変数の定義」を省略してもきちんと動いています。

いつからだろう?

なにはともあれ、コード量が減るのは嬉しいことです。

// 定義
@interface UIViewBoundsSample : UIViewController

@property (nonatomic, retain) UILabel* label0;

@end

// 実装
@implementation UIViewBoundsSample

@synthesize label0;

- (void)dealloc {
  self.label0 = nil;
  [super dealloc];
}

@end

natsun_happynatsun_happy2010/07/13 05:16私もあまり詳しくはないのですが、定義を省略できるかはランタイムに依存しているはずです。

"modern"なランタイム(iPhoneと64bit Mac)であればこの記述方法が可能なようです。SDK4.0でシミュレータのランタイムが変更になったので、SDK4.0からは、実機/シミュレータともに使えるようになったのだと思います。逆に、SDK3.2(もしくはそれ以前)を使うと、実機ビルドではOK、シミュレータビルドではNGになるのではないかと思います。

何はともあれ、シミュレータと実機で環境が統一されつつあるのは嬉しいことですね。

この"modern"なランタイムには、ほかにもいろいろとメリットがありそうです。私ももう少し調べてみようと思います。

ひとまずここが詳しそうです:
http://cocoawithlove.com/2010/03/dynamic-ivars-solving-fragile-base.html

tokoromtokorom2010/07/15 21:14natsun_happyさんTwitter and Blogコメントありがとうございます。
"modern"なランタイムに他にも有用な更新があるかもしれないと思うと楽しみです!
ぼくも調べてみます!

AbiAbi2013/01/22 20:00That hits the traegt dead center! Great answer!

anuzbtlanuzbtl2013/01/25 16:59iNz2Vq , [url=http://bcfbpcwcprmo.com/]bcfbpcwcprmo[/url], [link=http://fjfprdohinqv.com/]fjfprdohinqv[/link], http://umlwqrigzvbz.com/

2010-05-14

タブバーやツールバーみたいなアルファ値ベースのアイコンを作成する

| 21:46 | はてなブックマーク -  タブバーやツールバーみたいなアルファ値ベースのアイコンを作成する - iPhoneアプリ開発まっしぐら★

タブバーやツールバーでは、アルファ値だけを使った1色のアイコンが作られて表示されるが、これを自作のコントロールでも使いたくなった。

ということで、こういったアイコンを自分のプログラムで作成するのにトライしてみた。


用意する画像

A. アルファ値で作成したアイコン画像(タブバーやツールバーに設定するような画像)

source.png

f:id:tokorom:20100514214114p:image

B. アイコンの前景色にするための画像(例えばグラデーションをかけた画像など)

foreground.png

f:id:tokorom:20100514214115p:image


処理の流れ

1. 「A」の画像のアルファ値を抜いて、マスク用画像を作成する

2. 新しく作るアイコン画像のベースとなるアルファ値付きのコンテキスト(下地みたいなもの?)を作る

3. コンテキストに「1」で作ったマスクを設定する

4. コンテキストに「B」の画像を描画する

5. このコンテキストから画像を作成する

完成!

f:id:tokorom:20100514214116p:image


実際のコード

  UIImage* sourceImage = [UIImage imageNamed:@"source.png"];
  UIImage* foregroundImage = [UIImage imageNamed:@"foreground.png"];
  CGFloat width = sourceImage.size.width;
  CGFloat height = sourceImage.size.height;
  CGRect rect = CGRectMake( 0, 0, width, height );
  // 元画像からマスクを作成
  CGContextRef maskContext = CGBitmapContextCreate( NULL, width, height, 8, 0, NULL, kCGImageAlphaOnly );
  CGContextDrawImage( maskContext, rect, sourceImage.CGImage );
  CGImageRef maskImage = CGBitmapContextCreateImage( maskContext );
  CGContextRelease( maskContext );
  // 新しく作る画像のコンテキストをアルファ値付きで作成
  CGColorSpaceRef genericColorSpace = CGColorSpaceCreateDeviceRGB();
  CGContextRef newImageContext = CGBitmapContextCreate( NULL, width, height, 8, 0, genericColorSpace, kCGImageAlphaPremultipliedFirst );
  CGColorSpaceRelease( genericColorSpace );
  // コンテキストにマスクを設定
  CGContextClipToMask( newImageContext, rect, maskImage );
  // コンテキストに任意の前景画像を描画
  CGContextDrawImage( newImageContext, rect, foregroundImage.CGImage );
  CGImageRelease( maskImage );
  CGImageRef maskedImage = CGBitmapContextCreateImage( maskContext );
  CGContextRelease( newImageContext );
  // 作成したCGImageからUIImageを作成
  UIImage* newImage = [UIImage imageWithCGImage:maskedImage];
  CGImageRelease( maskedImage );
  // このnewImageが完成アイコン!

補足

マスクをかけたCGImageを作成するのには、

CGImageCreateWithMask

を使うほうが簡単だと思ったのだが、こちらだとAlphaInfoがkCGImageAlphaNoneのアルファ値がないCGImageができてしまい、せっかく作ったアイコンの背景が黒くなってしまったため、強制的にアルファ値付きのコンテキストを作成してそこでマスクをかけるようにしている。

kCGImageAlphaNoneのCGImageをアルファ値付きのコンテキストに描画し直す方法も考えられるが、それはちょっと冗長なので上記のように

CGContextClipToMask

を使ってコンテキストで直接マスクすることとした。

※なんかこのアイコンを一発で作る標準関数がありそうな気もするんですが、知っているかたがいたら教えてください m(_ _)m


c5h12さんのコメントを受けて

※2010/05/28 追記

c5h12さんから、以下の条件を満たせばCGImageCreateWithMaskメソッドでもいけるのでは、とコメントいただきました。あざーす!

  • foreground.pngをアルファ付きで用意すること
  • マスクをグレースケールで用意すること
  • 利用するPNGにアルファ値が1以外の部分が含まれていること

ということで、これらの条件が満たされる場合には、以下のように短いコードにできます。

  UIImage* sourceImage = [UIImage imageNamed:@"source.png"];
  CGImageRef foregroundImage = sourceImage.CGImage;
  CGImageRef mask = CGImageMaskCreate( CGImageGetWidth( foregroundImage ),
                                       CGImageGetHeight( foregroundImage ),
                                       CGImageGetBitsPerComponent( foregroundImage ),
                                       CGImageGetBitsPerPixel( foregroundImage ),
                                       CGImageGetBytesPerRow( foregroundImage ),
                                       CGImageGetDataProvider( foregroundImage ),
                                       NULL,
                                       false );
  CGImageRef maskedImage = CGImageCreateWithMask( [[UIImage imageNamed:@"foreground.png"] CGImage], mask );
  CGImageRelease( mask );
  // 作成したCGImageからUIImageを作成
  UIImage* newImage = [UIImage imageWithCGImage:maskedImage];
  CGImageRelease( maskedImage );
  // このnewImageが完成アイコン!

c5h12さん、ありがとうございましたっ!!


参考サイト

c5h12c5h122010/05/19 13:20初めまして。
ツイッターで見て、後で読むしておいたもので今頃拝見しました(笑)
前に自分でやった時はできた気がするんだけどな、と思って少し試してみたところ CGImageCreateWithMask(image, mask) は第1引数のimageにアルファがあれば抜けるようです。
なのでforeground.pngをアルファ付きで用意するか、アルファのあるCGContextに描いて取得すれば使えると思います。
あとこの場合はマスクをグレイスケールで用意する必要がありますのでご注意ください。
また、リソースに入れたPNGはアルファが全部1だと勝手にチャンネルを削除するようなのでそちらもご注意ください。

tokoromtokorom2010/05/21 12:47c5h12さん
返信が遅れ申し訳ありません。
なるほど、条件を満たせばCGImageCreateWithMaskでいけるんですねー!早速TRYさせていただきます!
コメントありがとうございました m(_ _)m

JoyelleJoyelle2012/02/04 03:15Ah yes, nicely put, eveyrone.

omqtsyomqtsy2012/02/06 00:19BaN2xX <a href="http://xqveictrakaf.com/">xqveictrakaf</a>

wsahkparwsahkpar2012/02/07 21:38bYTvaS , [url=http://xbbnareuufui.com/]xbbnareuufui[/url], [link=http://hhnhybsqczlg.com/]hhnhybsqczlg[/link], http://zxvpmapsbycx.com/

inoiwcimvtiinoiwcimvti2012/02/11 23:18oB01ZE , [url=http://mkvotrbhbttz.com/]mkvotrbhbttz[/url], [link=http://qhqsemijoayf.com/]qhqsemijoayf[/link], http://dqojhfbagecw.com/

2010-02-20

NSStringのlengthについてのメモ書き

| 09:43 | はてなブックマーク -  NSStringのlengthについてのメモ書き - iPhoneアプリ開発まっしぐら★

文字エンコーディングによって結果が変わることを確認。

ちなみにソースコードはUTF-8で書いている。

NSString* defaultString = @"あいうえお";
NSString* utf8String = [NSString stringWithCString:"あいうえお" encoding:NSUTF8StringEncoding];
NSString* asciiString = [NSString stringWithCString:"あいうえお" encoding:NSASCIIStringEncoding];
NSLog( @"default: %d", defaultString.length );
NSLog( @"utf8String: %d", utf8String.length );
NSLog( @"asciiString: %d", asciiString.length );

■実行結果

default: 5
utf8String: 5
asciiString: 15