UIViewについて
前回の予告の通り、いま15パズルの改良(?)版をテスト中ですが、なかなかバグが取れずに難渋しています。
この過程で気がついたことを二つご報告します。
一つ目は、前のコードの説明の中に何度も出てきた<convertRect>という関数についてです。
たとえば、
//比較元のPieceを取り出す Piece *p = [piece objectAtIndex:i]; //比較元のPieceの矩形を親のView(GameBoad)の座標に変換する CGRect prect = [boad convertRect:p.bounds fromView:p];
これは、共にUIViewであるpがboadのsubviewである時に、pの矩形を示すプロパティboundsを親のView(boad)の座標に変換するもので、これ自体間違いではありません。しかし、よくよくUIViewのドキュメントを見てみるとboundsのほかにframeというプロパティがあって、こちらは「Setting the frame rectangle repositions and resizes the receiver within the coordinate system of its superview. 」というではありませんか。
つまり、boundsをわざわざ座標変換しなくても、frameには親のviewの座標が入っています。上のコードは、
CGRect prect = [piece objectAtIndex:i].frame;
だけでいいのでした。
もうひとつ。こちらは気付いたどころか、少々青くなったのですが、UIViewのboundsにしてもframeにしても実体はCGRectですが、このCGRectは次のような構造体になっており、
struct CGRect { CGPoint origin; CGSize size; }; typedef struct CGRect CGRect;
矩形の原点であるoriginは「The origin is located in the lower-left of the rectangle.」、左下(lower-left)を指していると読めるではありませんか。
ぼくはずっと、originは画面の左上を指しているとばかり思っていました。では、これまでバグが出なかったのは、originは左上という早とちりが単に「一貫して」いたからだけなのか?
そこで、次のようなテストコードを書いて確かめてみました。
- (void)viewDidLoad { [super viewDidLoad]; UIView *view01 = [[UIView alloc] initWithFrame:CGRectMake(20.0, 20.0, 280.0, 280.0)]; view01.backgroundColor = [UIColor blackColor]; [self.view addSubview:view01]; NSLog([NSString stringWithFormat:@"view01 bounds origin.x:%f origin.y:%f size.width:%f size.height:%f",view01.bounds.origin.x,view01.bounds.origin.y,view01.bounds.size.width,view01.bounds.size.height]); NSLog([NSString stringWithFormat:@"view01 frame origin.x:%f origin.y:%f size.width:%f size.height:%f",view01.frame.origin.x,view01.frame.origin.y,view01.frame.size.width,view01.frame.size.height]); UIView *view02 = [[UIView alloc] initWithFrame:CGRectMake(100.0, 100.0, 80, 80)]; view02.backgroundColor = [UIColor yellowColor]; [view01 addSubview:view02]; NSLog([NSString stringWithFormat:@"view02 bounds origin.x:%f origin.y:%f size.width:%f size.height:%f",view02.bounds.origin.x,view02.bounds.origin.y,view02.bounds.size.width,view02.bounds.size.height]); NSLog([NSString stringWithFormat:@"view02 frame origin.x:%f origin.y:%f size.width:%f size.height:%f",view02.frame.origin.x,view02.frame.origin.y,view02.frame.size.width,view02.frame.size.height]); CGRect rect02 = [view01 convertRect:view01.bounds fromView:view02]; NSLog([NSString stringWithFormat:@"rect02 origin.x:%f origin.y:%f size.width:%f size.height:%f",rect02.origin.x,rect02.origin.y,rect02.size.width,rect02.size.height]); }
結果の画面とデバッグログは次の通り。
view01 bounds origin.x:0.000000 origin.y:0.000000 size.width:280.000000 size.height:280.000000 view01 frame origin.x:20.000000 origin.y:20.000000 size.width:280.000000 size.height:280.000000 view02 bounds origin.x:0.000000 origin.y:0.000000 size.width:80.000000 size.height:80.000000 view02 frame origin.x:100.000000 origin.y:100.000000 size.width:80.000000 size.height:80.000000 rect02 origin.x:100.000000 origin.y:100.000000 size.width:280.000000 size.height:280.000000
やはり、originは画面の左上です。
lower-leftとは、iPhone画面の座標系(X軸は右にプラス、Y軸は下にプラス)上でのlower-left、見かけの左上を示すということのようです。ほっとしました。
以上、tipsにもなりませんがご報告です。
コメントもいただいているのですが、なかなかお返事できません。申し訳ありません。