F13

RSS

Posts tagged with "tech"

CURLで取得したJSONをフォーマットした状態で表示

単にcurlしただけだと、読みにくかったり、Unicodeになっていたりする。 そんなときに、以下のようにaliasを登録しておくと、”| pjson”とつけるだけで、読みやすくなる。

NSErrorで、Potential null dereference エラー

NSErrorで、以下の様なメッセージが出て怒られてしまった。

Potential null dereference. Accordning to coding standards in ‘Creating and Returning NSError Objects’ the parameter maybe null

以下の様な実装をしていたのだが、

- (void)testHoge:(NSError *__autoreleasing *)error {
    ...
    *error = [NSError errorWithDomain:@"ErrorDomain" code:1 userInfo:nil];

}

errorがNullの可能性があるので、errorにNSErrorを代入する前にチェックが必要だった。

if (error) *error = [NSError errorWithDomain:@"ErrorDomain" code:hasLength userInfo:nil];

jinja2のMacroのなかで、Contextに定義した関数が使えなかった

標題の通りはまってしまったのでメモ。

Macroとは

以下の様に、テンプレート内で共通の表示部分をまとめることができる。

{% macro input(name, value='', type='text') -%}
    <input type="{{ type }}" value="{{ value|e }}" name="{{ name }}">
{%- endmacro %} 

そして、以下の様にMacroを呼び出すことができる。

{% import 'forms.html' as forms %}
{{ forms.input('username') }} 

非常に便利なのだが、Macroから、Contextに定義した関数がが使えなかったのだ。

というのにちょっとだけ、はまったのだがドキュメントを見たら書いてあった。

importする際に”with context”を付けてあげる必要がある。

先ほどの例だと以下の様にすれば大丈夫だった。

{% import 'forms.html' as forms with context%}
{{ forms.input('username') }} 

UIViewにグラデーションを設定

UIViewの子クラスを使い、以下の様にawakeFromNibでグラデーションを設定

- (void)awakeFromNib {
    CAGradientLayer *gradient = [CAGradientLayer layer];
    gradient.frame = self.bounds;
    gradient.colors = [NSArray arrayWithObjects:(id)[
        [UIColor whiteColor] CGColor], 
        (id)[[UIColor colorWithRed:0.69 green:0.769 blue:0.871 alpha:1] CGColor], nil];
    [self.layer insertSublayer:gradient atIndex:0];
}

MapViewとAnnotationを使って、ピンをさし、詳細画面へ遷移する方法

Annotationについて

Annotationは、MKANnotation protocolを実装したクラスを自分で作る必要がある。

MyAnnotation.h
@interface MyAnnotation : NSObject 

- (id)initWithCordinate:(CLLocationCoordinate2D)coordinate title:(NSString *)title subtitle:(NSString *)subtitle;

@property (nonatomic) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;

@end 
MyAnnotation.m
@implementation MyAnnotation 

// Properties
@synthesize coordinate = _coordinate;
@synthesize title = _title;
@synthesize subtitle = _subtitle;

#pragma mark - Initializing
- (id)initWithCordinate:(CLLocationCoordinate2D)coordinate title:(NSString *)title subtitle:(NSString *)subtitle {
    self = [super init];
    if (self) {
        self.coordinate = coordinate;
        self.title = title;
        self.subtitle = subtitle;
    }
    return self;
}

@end 

Annotationの追加

以下のように、Annotationを作成し、MapViewに追加を行う。

CLLocationCoordinate2D coordinate =  CLLocationCoordinate2DMake(geoPoint.latitude, geoPoint.longitude);
MyAnnotation *annotation =[[MyAnnotation alloc] initWithCordinate:coordinate title:title subtitle:subtitle];

[mapView addAnnotation:annotation]; 

AnnotationViwについて

Annotationを追加すると以下のメソッドが呼ばれる、ここでAnnotationViewを作成する。

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation {
    
    // if annotation is user location, return the method
    if ([annotation isKindOfClass:[MKUserLocation class]]) {
        return nil;
    }
    
    // make annotation view
    static NSString *identifier = @"PlaceAnnotation";
    MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[self.mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
    if (!annotationView) {
        annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
    }
    // set the some properties
    annotationView.pinColor = MKPinAnnotationColorGreen;
    annotationView.canShowCallout = YES;
    annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
    return annotationView;
} 

ボタンを押された場合は以下のメソッドが呼ばれることになる。 Storyboardを使っている場合は、SegueのIdentifierを渡すことにより、任意の切り替えを行うことができる。

 - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
    // push the detail view
    [self performSegueWithIdentifier:@"presentDetailView" sender:self];
} 

UISearchBarの背景画像を変更する(iOS5以上)

iOS5以上からは、UIApperanceというプロトコルが有効になり、それを使うと非常に簡単に見た目を変えることができる。

今回は、UISearchBarの背景画像を変更してみる。

AppDelegate内で、以下のように指定するだけでアプリ内で使っているUISearchBarの背景画像を一気に変更することが出来る。

UIImage *searchBarImage = [UIImage imageNamed: @"Frame-Background.png"];
[[UISearchBar appearance] setBackgroundImage:searchBarImage];

stackoverflowにUIKitごとに使えるプロパティがまとまってたので、リンクを張っておく。

http://stackoverflow.com/questions/9424112/what-properties-can-i-set-via-an-uiappearance-proxy

Jul 5

Titaniumで、Facebookのログアウトではまった

TitaniumのFacebook連携で、ログアウトしようとしても認証情報が残っているせいで、ログイン状態が続いてしまうという現象にはまった。

// ログアウト時に呼ばれるイベント
Ti.Facebook.addEventListener('logout', function(e) {
    // 何らかの処理

});
// ログアウト
Ti.Facebook.logout();

上記の様に、ログアウト処理を行っているにも関わらず、うまくログアウトできなかった。

調べていると、認証情報が入っているCookieを取得する際のURL指定が間違っているようだ。

ここに詳細の情報が載ってる。

ということで、Facebook.mを上記ページに従って変更し、build/iphone配下を削除後、再実行したらうまくいった。

Jul 4

CocoaPodsでエラーになった(CocoaPodsのアップデート)

久しぶりにCocoaPodsを使い、ライブラリの追加を行おうとしたらエラーになってしまった。

$ pod install
Updating spec repo `master'
Updating spec repo `private'
Oh no, an error occurred. Please run with `--verbose' and report on
 https://github.com/CocoaPods/CocoaPods/issues.

undefined method `osx' for #<:specification for blockskit>

原因がよく分からなかったが、とりあえずアップデートを試みることにした。

$ sudo gem update --system
$ sudo gem update cocoapods

上記で、アップデート自体はうまくいった、試しにバージョンが上がっているか確認

$ pod --version
0.6.1

この後、再度 pod install を試みたら、成功したのでアップデートによって直ったようだ。

Jul 3

iOSで、現在、横向き(Landscape)なのかどうかを知る方法

忘れないようにメモ。

Landscapeかどうか

UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)

Portraitかどうか

UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation)
Jul 2

NSDateを年、月、日から生成する

前回で、NSDateから、年、月、日を取得することはできた。

今度は、年、月、日からNSDateを生成したい。

 + (NSDate *)dateWithYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day {
    NSDateComponents *components = [[NSDateComponents alloc] init];
    [components setDay:day];
    [components setMonth:month];
    [components setYear:year];
    return [[NSCalendar currentCalendar]dateFromComponents:components];    
}