今日は、バブルソートをアニメーションさせるようなiPhoneアプリのサンプルコードを描いてみます。
動かすとこんな感じです
サンプルコード
#import “ViewController.h”
@interface MyBubble : NSObject
@property (nonatomic, strong) NSMutableArray *arr;
@property (nonatomic, strong) NSString *changeMessage;
@end
@implementation MyBubble
– (id)init
{
self = [super init];
if (self) {
self.arr = [NSMutableArray array];
for (int i=0; i<20; i++) {
[self.arr addObject:@(arc4random() % 10)];
}
}
return self;
}
– (int)intValueAtIndex:(NSUInteger)idx
{
return [self.arr[idx] intValue];
}
– (void)exchangeObjectAtIndex:(NSUInteger)idx1 withObjectAtIndex:(NSUInteger)idx2
{
[self.arr exchangeObjectAtIndex:idx1 withObjectAtIndex:idx2];
self.changeMessage = [NSString stringWithFormat:@”%d,%d”, idx1 + 1, idx2 + 1];
}
@end
@interface ViewController ()
@property (nonatomic, strong) MyBubble *myBubble;
@property (nonatomic, strong) NSMutableArray *animationQueue;
@end
@implementation ViewController
– (void)viewDidLoad
{
[super viewDidLoad];
[self addObserver:self forKeyPath:@”myBubble.changeMessage” options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:NULL];
self.myBubble = [[MyBubble alloc] init];
self.view.backgroundColor = [UIColor colorWithRed:0.0 green:0.5 blue:0.1 alpha:1.0];
for (int i=0; i<self.myBubble.arr.count; i++) {
float x = CGRectGetMaxX(self.view.frame) – (i / 5) * 60 – 60;
float y = (i % 5) * 40 + 80;
UILabel *bubble = [[UILabel alloc] initWithFrame:CGRectMake(x, y, 30, 30)];
bubble.tag = i + 1;
bubble.layer.cornerRadius = 15;
bubble.layer.borderWidth = 2;
bubble.layer.borderColor = [UIColor whiteColor].CGColor;
bubble.font = [UIFont fontWithName:@”ChalkboardSE-Light” size:20];
bubble.text = [@([self.myBubble intValueAtIndex:i]) stringValue];
bubble.textAlignment = NSTextAlignmentCenter;
bubble.textColor = [UIColor whiteColor];
[self.view addSubview:bubble];
}
}
– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self bubbleSort:self.myBubble];
}
– (void)bubbleSort:(MyBubble *)bubble
{
for (int i=0; i<bubble.arr.count; i++) {
for (int j=bubble.arr.count–1; j>i; j–) {
if ([bubble intValueAtIndex:j] < [bubble intValueAtIndex:j-1]) {
[bubble exchangeObjectAtIndex:j withObjectAtIndex:j-1];
}
}
}
[self startBubbleAnimation];
}
– (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@”myBubble.changeMessage”]) {
id new = change[@”new”];
if (new != (id)[NSNull null]) {
NSArray *idx = [new componentsSeparatedByString:@”,”];
if (!self.animationQueue) {
self.animationQueue = [NSMutableArray array];
}
[self.animationQueue addObject:idx];
}
}
}
– (void)startBubbleAnimation
{
[self swapPosition];
}
– (void)swapPosition
{
NSArray *idx = self.animationQueue[0];
[self.animationQueue removeObjectAtIndex:0];
UIView *v0 = [self.view viewWithTag:[idx[0] intValue]];
UIView *v1 = [self.view viewWithTag:[idx[1] intValue]];
v0.tag = v1.tag;
v1.tag = [idx[0] intValue];
CGPoint newP0 = v1.center;
[UIView animateWithDuration:0.2 animations:^{
v1.center = v0.center;
v0.center = newP0;
} completion:^(BOOL finished) {
if (self.animationQueue.count) {
[self swapPosition];
}
}];
}
@end