Posted at

Objective-C (Quartz 2D) の便利な関数集

More than 5 years have passed since last update.

UIView の frame や各種座標、領域などでよく使うQuratzの構造体などの便利な関数集です。よくCGRect などの値を直接比較したりしてませんか?もちろん動作としてはそれでも問題ないですが、コードが冗長になり if が画面がはみ出したりしていませんか?CGGeometry Reference などをみると便利な関数が結構あります。知らなくても別に問題ありませんが、知ってるとコードがちょっときれいになります。そんな便利関数をいくつか紹介します。

参照:CGGeometry Reference


CGRect に関する関数等


定数


CGRectZero

各要素(x, y, width, height)が0な定数です。次と等価です。


CGRectNull

CGRectZero と似ていますが、これは存在しない領域を指し示します。CGRect を返すようなメソッドで、エラー発生時などに返すと便利です。


比較


CGRectEqualToRect

bool CGRectEqualToRect (

CGRect rect1,
CGRect rect2
);

二つのCGRectを比較し、同じだった場合は YES となる関数です。二つとも CGRectNull だった場合も YES を返します。if 文内でずらっと並べると長くなってしまうので積極的に使うとかなりきれいになります。


CGRectIsEmpty

bool CGRectIsEmpty (

CGRect rect
);

引数の rect が CGRectZero もしくはCGRectNull と同じ場合は YES を返します。


CGRectIsNull

bool CGRectIsNull (

CGRect rect
);

引数の rect が CGRectNull のときのみ YES を返します。


CGRectContainsPoint

bool CGRectContainsPoint (

CGRect rect,
CGPoint point
);

引数の point が rect に含まれていると YES を返します。


CGRectContainsRect

bool CGRectContainsRect (

CGRect rect1,
CGRect rect2
);

引数の rect2 が rect1 に完全に含まれているときに YES を返します。一部しかかぶっていない場合は、NO となります。この場合でも判定したい場合は、次の CGRectIntersectsRect を使用してください。


CGRectIntersectsRect

bool CGRectIntersectsRect (

CGRect rect1,
CGRect rect2
);

引数の rect2 が rect1 に含まれるか、一部がかぶっているときに YES を返します。


取得 (CGRectGet....系)

CGFloat CGRectGet... (

CGRect rect
);

CGRectGetで始まる各関数は CGRect の各要素を取り出します。


CGRectGetMinX, CGRectGetMinY

CGRect 左端、上端の値を返します。rect.location.x, rect.location.y と一緒ですが、他の CGRectGet に合わせると多少きれいに見えます。


CGRectGetMidX, CGRectGetMidY

CGRect の中央となる値を返します。

  CGFloat midX = rect.location.x + rect.size.width / 2;

CGFloat midY = rect.location.y + rect.size.width / 2;


CGRectGetMaxX, CGRectGetMaxY

CGRect の右端、下端を返します。

  CGFloat mixX = rect.location.x + rect.size.width;

CGFloat mixY = rect.location.y + rect.size.width;


CGRectGetWidth, CGRectGetHeight

CGRect の幅、高さを返します。rect.size.width, rect.size.height と等価ですが、これも若干コードがきれい見える気がします。


特殊


CGRectIntersection

CGRect CGRectIntersection (

CGRect r1,
CGRect r2
);

r1 と r2 が重複している領域を返します。二つのCGRectがかぶっていないときは CGRectNull が返ってきます。


CGRectUnion

CGRect CGRectUnion (

CGRect r1,
CGRect r2
);

二つの領域が収まる領域を返します。


CGRectInset

CGRect CGRectInset (

CGRect rect,
CGFloat dx,
CGFloat dy
);

dx, dy で指定した分上下左右を削ります。dx, dy が負数の場合は広げます。上下、左右に削るため、新しい領域の大きさは指定した値の倍小さくなります。

  CGRect rect1 = CGRectMake(0, 0, 100, 100);

CGRect rect2 = CGRectInset(rect1, 10, 10);
// rect2 = 10, 10, 80, 80


CGRectOffset

CGRect CGRectOffset (

CGRect rect,
CGFloat dx,
CGFloat dy
);

dx, dy で指定した分だけ rect を移動させます。この関数ではサイズは変更されません。

次のコード等価です。

  CGRect rect2 = rect;

rect2.location.x = rect.location.x + dx;
rect2.location.y = rect.location.y + dy;


文字列変換

NSLog なのでCGRect の値を表示させるときに便利なのが次の関数です。引数に、それぞれの構造体を渡してやると、いい感じに文字列で表現してくれます。


  • NSStringFromCGPoint

  • CGRectFromString

  • CGSizeFromString


オブジェクト変換

CG~で始まる構造体はそのままだとオブジェクトとして扱うことができません。performSelectorとかで、渡すときにちょっと面倒ですね・・・そんな時は次の関数です。


  • CGPointCreateDictionaryRepresentation

  • CGRectCreateDictionaryRepresentation

  • CGSizeCreateDictionaryRepresentation

この関数に各構造体渡してやると CFDictionaryRef を生成してくれます。CFDictionaryRefは NSDictionary と Toll free bridged なのでそのまま変換できます。

逆に戻しときは次の関数を使用します。


  • CGPointMakeWithDictionaryRepresentation

  • CGRectMakeWithDictionaryRepresentation

  • CGSizeMakeWithDictionaryRepresentation