8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

BlocksKitをまねしてCLLocationManagerにblockを追加してみた

Posted at

割と簡単にできてびっくりしている。

やりたかったこと

Delegateメソッドを書かずに、CLLocationManagerを使いたかった。

通常位置情報を扱う場合は、CLLocationManagerのdelegateを登録し、ViewController等にDelegateメソッドを追加して実装します。ですがこの方法は王道ですが、メソッドが増えたりソースコード的に書きにくい読みにくい等あってあまり好きではありません。なので、Delegateを使わずにやってみたいと思ってました。
同じようなニーズを、UIAlertView等のiOS標準のクラスでやっているのがBlocksKitです。
iOSコーディングスタイルを変えてしまうBlocksKitの紹介

BlocksKitがやってること

BlocksKitはUIAlertViewのDelegateをblockで置き換えてます。どうやっているのかソースコードを見ると、A2DynamicDelegateというライブラリを使っていました。
UIAlertView+BlocksKit.m
A2DynamicDelegate←BlocksKitに同梱

仕組みが分からないけどパクってみる

A2DynamicDelegateの仕組みは、今の脳みそでは難しくて理解できません。ですがBlocksKitでの使い方をパクりながら、blockを使ったCLLocationManagerを実装してみました。

CLLocationManager+block.h

# import <Foundation/Foundation.h>
# import <CoreLocation/CoreLocation.h>

@interface CLLocationManager(block)

# pragma mark - Responding to Location Events
//– locationManager:didUpdateLocations:
@property (nonatomic, copy) void (^didUpdteLocations)(CLLocationManager *,NSArray *);
@end
CLLocationManager+block.m


# import "CLLocationManager+block.h"
# import "A2BlockDelegate.h"


@interface A2DynamicCLLocationManagerDelegate : A2DynamicDelegate

@end
@implementation A2DynamicCLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager
     didUpdateLocations:(NSArray *)locations
{
    id realDelegate = self.realDelegate;
    if (realDelegate && [realDelegate respondsToSelector:@selector(locationManager:didUpdateLocations:)])
        [realDelegate locationManager:manager didUpdateLocations:locations];

    void (^block)(CLLocationManager *,NSArray *) = [self blockImplementationForMethod:_cmd];
    if (block)
        block(manager, locations);

    return;
}
@end

@implementation CLLocationManager(block)
@dynamic didUpdteLocations;
+ (void)load {
    @autoreleasepool {
        [self registerDynamicDelegate];
        [self linkDelegateMethods: @{
                // self property : Delegate methods
                @"didUpdteLocations": @"locationManager:didUpdateLocations:",
        }];
    }
}

@end

呼び出し元のViewControllerを書きます。

ViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
    self.manager = [[CLLocationManager alloc] init];
    self.manager.didUpdteLocations = ^(CLLocationManager *m,NSArray *a){
        NSLog(@"%@", [a objectAtIndex:0]);
    };
    [self.manager startUpdatingLocation];
}

エミュレータを起動して、NSLogがはき出される事を確認しました。
拍子抜けするぐらいあっさり動きました。

ソースコードがすごいシンプルになる可能性

位置情報を扱うアプリのControllerは、Delegateメソッドが多数生えて「下に長く」なっていきます。ですがDelegateの代わりにblockを使うこの方法ならば、シンプルに書いていけそうです。

おまけ:BlocksKit入れるならCocoaPodが楽

Podfile
platform :ios, '5.0'
pod 'BlocksKit'

を用意してpod install

8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?