ここで紹介している問題はバグではなく、UICollisionBehaviorの仕様です。
IMPORTANT
When setting the initial position for a dynamic item, you must ensure that its bounds do not intersect any collision boundaries. The animation behavior for such a misplaced item is undefined.
要するに考えずに重ねて初期配置すると変なことになるよ。
ということです。
再現コード
ViewController.m
@interface ViewController (){
UIDynamicAnimator *animator;
UICollisionBehavior *collisionBehavior;
NSMutableArray*vs;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
vs = [NSMutableArray array];
animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
collisionBehavior = [UICollisionBehavior new];
collisionBehavior.translatesReferenceBoundsIntoBoundary = true;
[animator addBehavior:collisionBehavior];
UITapGestureRecognizer*t = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)];
[self.view addGestureRecognizer:t];
}
- (void)tap{
UIView*v = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
v.backgroundColor = [UIColor redColor];
[self.view addSubview:v];
[vs addObject:v];
for (id o in collisionBehavior.items) {
[collisionBehavior removeItem:o];
}
int index = 0;
for (UIView*view in vs) {
view.frame = CGRectMake(0,100*index, 100,100);
[collisionBehavior addItem:view];
if (view.bounds.size.height!=view.bounds.size.width) {
view.backgroundColor = [UIColor blueColor];
NSLog(@"size w=%f : h=%f",view.bounds.size.width,view.bounds.size.height);
}
index++;
}
}
@end
タップするたびに100100の四角を画面左端に並べていくコードです。
ただし、translatesReferenceBoundsIntoBoundaryが設定してあるので画面をはみ出すと初期位置が画面右下のビューと被った状態でコリジョンビヘイビアに登録されます。
上記のコードでは縦横100100が崩れると青くなるように書かれています。
↓
↓
再現出来ました。
frameのsizeを弄っていないのにビューのサイズが変わってしまったのを確認出来たかと思います。
なかなかエグい仕様なので、ごちゃごちゃするUIを作る場合には注意です。