酒と泪とRubyとRailsと

Ruby on Rails と Objective-C は酒の肴です!

【詳解 Objective-C iPhoneアプリ開発 入門ノート】で再入門iPhoneアプリ開発!

久々にObjective-Cを触り始めました。ほとんど忘れてるかなと思ってたんですが、結構覚えていて自分でびっくりしています。前に開発していた時にかなり苦労したので、その分脳にしっかり刻み込まれていたのかもw

ということでリハビリで『詳細! Objective-C iPhoneアプリ開発 入門ノート』を読み始めました。この本はサンプルソースがかなり豊富なので、作りながら覚えていくのに最適な構成です。

今回は、特に参考になった点を中心にピックアップしていきます。

(04/05 22:45) ピンチイン・アウトとダブルタップを認識するサンプルを追加


入門者におすすめなドキュメント

キーボードで完結!ハイスピード Xcodeコーディング
スライド形式で、わかりやすくショートカットコマンドがわかる。これは初心者に超オススメ!

Objective-Cでは、インスタンス変数をどこに宣言するのが正しいのか?
Apple的には実装ファイル側に変数を書いてほしいそうですが、ソースの見通し的にはヘッダファイル側に変数を書いたほうが良さそうです。

Objective-Cの基礎

便利メソッドとか覚えておきたいメソッドとかを中心に書いてみました!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

// 便利メソッド
// 1以上のランダムな数を出す
int random = arc4random();
NSLog(@"arc4random() = %d", random); //=> 173176668

// 小数点の切り上げ
int ceil_num = ceil(0.5);
NSLog(@"ceil() = %d", ceil_num); //=> 1

// doubleの絶対値
double fabs_num = fabs(-55.2940);
NSLog(@"fabs() = %f", fabs_num); //=> 55.294000

// 今日の日付
NSDate *today = [NSDate date];
NSLog(@"today = %@", today); //=> 2014-04-02 10:19:34 +0000

// 文字列
NSString *address = @"東京都文京区本郷1-2-3";
NSLog(@"%@", [address substringFromIndex:6]); //=> 本郷1-2-3
NSLog(@"%@", [address substringToIndex:4]); //=> 東京都文京区

// 編集可能な文字列型
NSMutableString *str = [NSMutableString string];
[str setString:(@"あいうえお")];
[str insertString:@"def" atIndex:4];
NSLog(@"%@", str); //=> あいうえdefお

// 整数の配列の合計を求める
NSArray *intlist = @[@16, @5, @25, @54];
NSInteger sum = 0;
for (NSString *num in intlist) {
    sum += [num intValue];
}
NSLog(@"sum = %d", sum); //=> 100

// 配列の値をソートする
NSArray *fruits = @[@"melon", @"Peach", @"apple", @"orange"];
NSArray *sortedFruits = [fruits sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
NSLog(@"%@", sortedFruits); //=> apple, melon, orange, Peach

// 数値の配列をフィルタリングする
NSMutableArray *number_3 = [NSMutableArray arrayWithArray:@[@3, @18, @20, @7, @9, @10]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self >= 10"];
NSLog( @"%@", [number_3 filteredArrayUsingPredicate:predicate] ); // => 18, 20, 10

// セットを作る => 共通した要素を残す
NSArray *color1 = @[@"blue", @"red", @"yellow", @"white"];
NSArray *color2 = @[@"green", @"white", @"black"];
NSSet *colorSet2 = [NSSet setWithArray:color2];
NSMutableSet *commonColors = [NSMutableSet setWithArray:color1];
[commonColors intersectSet:colorSet2];
NSLog(@"Common = %@", commonColors); //=> white

画像タップで背景色を変えるサンプル。

シングルページビューで、画像をタップすると背景色が変わるようなサンプルを作成。

ViewController.h
1
2
3
4
5
6
7
8
9
10
11
#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
{
    // catのイメージビュー
    UIImageView *cat;
}
// タップで実行するメソッド
-(void) tapCat:(UITapGestureRecognizer *)gesture;

@end
ViewController.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController  {
    BOOL _screen_color;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    // イメージを作る
    UIImage *imageData = [UIImage imageNamed:@"cat.jpg"];

    // イメージビューを作る
    CGFloat width = imageData.size.width/10;
    CGFloat height = imageData.size.height/10;
    CGRect rect = CGRectMake(0, 0, width, height);
    cat = [[UIImageView alloc] initWithFrame:rect];

    // イメージビューにイメージを設定
    cat.image = imageData;
    cat.contentMode = UIViewContentModeScaleAspectFit;
    cat.center = CGPointMake(160, 100);

    // イメージビューがインタラクティブ操作を受け付けるようにする
    cat.userInteractionEnabled = YES;

    // タップジェスチャーを作る
    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapCat:)];

    // イメージビューにタップジェスチャーを設定
    [cat addGestureRecognizer:tapGesture];

    // イメージビューを表示する
    [self.view addSubview:cat];

    _screen_color = YES;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void) tapCat:(UITapGestureRecognizer *)gesture
{
    NSLog(@"心をタップされました。");

    if(_screen_color) {
        self.view.backgroundColor = [UIColor blueColor];
    } else {
        self.view.backgroundColor = [UIColor whiteColor];
    }

    // 色をトグルで変更
    _screen_color ^= YES;
}

@end

ピンチイン・アウトとダブルタップを認識するアプリ

中央に画像を置いて、画像のピンチイン・アウトが出来たり、ダブルタップでの拡大をするためのソース。

ViewController.h
1
2
3
4
5
6
7
8
9
10
11
#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UIScrollViewDelegate>

// スクロールビュー
@property (weak, nonatomic) IBOutlet UIScrollView *myScrollView;

// スクロールビューにおいたイメージビュー
@property (weak, nonatomic) IBOutlet UIImageView *myImageView;

@end
ViewController.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#import "ViewController.h"

@interface ViewController ()
// 拡大する領域を求めるメソッド
- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center;
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // スクロールビューのデリゲート先になる
    _myScrollView.delegate = self;

    // ズームの最小/最大を設定する
    _myScrollView.minimumZoomScale = 1;
    _myScrollView.maximumZoomScale = 8;

    // スクローラを表示する
    _myScrollView.scrollEnabled = YES;
    _myScrollView.showsHorizontalScrollIndicator = YES;
    _myScrollView.showsVerticalScrollIndicator = YES;

    // ダブルタップジェスチャーを作る
    UITapGestureRecognizer *doubleTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTap:)];

    // ダブルタップを認識する設定にする
    doubleTapGesture.numberOfTapsRequired = 2;

    // イメージビューにダブルタップジェスチャーを設定する
    _myImageView.userInteractionEnabled = YES;
    [_myImageView addGestureRecognizer:doubleTapGesture];
}

// 拡大写真をピンチイン/ピンチアウトできるようにする
- (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return _myImageView;
}

// 写真がダブルタップされたならば拡大/縮小する
- (void)doubleTap:(UIGestureRecognizer *)gesture {
    // 最大倍率でなければ拡大する
    if(_myScrollView.zoomScale < _myScrollView.maximumZoomScale)
    {
        // 現在の3倍の倍率にする
        float newScale = _myScrollView.zoomScale * 3;

        //拡大する領域を求める
        CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gesture locationInView:gesture.view]];

        // タップした位置を拡大する
        [_myScrollView zoomToRect:zoomRect animated:YES];
    } else {
        // 倍率1に戻す
        [_myScrollView setZoomScale:1.0 animated:YES];
    }
}

// 指定の座標を中心にして拡大する領域を求める
- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center {
    CGRect zoomRect;

    // 倍率から拡大する縦横サイズを求める
    zoomRect.size.height = [_myScrollView frame].size.height / scale;
    zoomRect.size.width  = [_myScrollView frame].size.width / scale;

    // 座標(左上)を設定する
    zoomRect.origin.x = center.x - (zoomRect.size.width/2.0);
    zoomRect.origin.y = center.y - (zoomRect.size.height/2.0);

    // 領域を返す
    return zoomRect;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

変更来歴

(04/04 22:45) タップするサンプルを追加
(04/05 22:45) ピンチイン・アウトとダブルタップを認識するサンプルを追加

おすすめの書籍