下のUIViewにイベントを通過させる

重なった2つのビューのうち、上のビューのイベントを下のビューに送りたい。

上のビューAをタッチした場合に、何もしないで下に位置するビューBにイベントを送りたい場合があります。Bは単にAの下に重なっているだけで、Aのサブビューではありません。

こんな場合は、Aの側で

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView *view = [super hitTest:point withEvent:event];
    if (view == self) {
        return nil;
    }
    return view;
}

とすればいいようです。もっと単純に

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    return NO;
}

でもうまくいくようです。

以下のサイトを参考にしました。

iOSアプリ「TravelOn」をリリース

3つ目のアプリ「TravelOn」をリリースしました。iPhone用です。
約560の都市の天気・通貨レート・カレンダー・時刻を表示できます。

1220

解説ページも用意しました(まだ作業中のところもありますが)。

このアプリはインターフェースも単純だし、簡単な気持ちで作り始めたのですが、通貨レートの情報サイトを選んだり、気象情報データサイトを選ん、カレンダーを選んだりと完成までに時間がかかってしまいました。当初の計画もずいぶんと変更しました。

アプリを作るにはずいぶんといろんなサイトの情報を利用させていただきました。得られた知識はこのブログで公開していきたいと思っているのですが、整理して記事にするにもこなれた知識が必要なんだと痛感しています。

NSDecimalNumberの簡単なまとめ

NSDecimalNumberの扱いを簡単にまとめました。
生成や変換は、文字列との相性が良いようです。

文字列から作成

NSDecimalNumber *dNum = [NSDecimalNumber decimalNumberWithString:@"1.234"];
NSDecimalNumber *dZero = [NSDecimalNumber zero];

文字列に変換

NSString *dNumStr = [dNum stringValue];

加減乗除

NSDecimalNumber *dNum1 = [NSDecimalNumber decimalNumberWithString:@"1.234"];
NSDecimalNumber *dNum2 = [NSDecimalNumber decimalNumberWithString:@"5.678"];

// dNum1 + dNum2
NSDecimalNumber *sum = [dNum1 decimalNumberByAdding:dNum2];
// dNum1 - dNum2
NSDecimalNumber *sub = [dNum1 decimalNumberBySubtracting:dNum2];
// dNum1 * dNum2
NSDecimalNumber *times = [dNum1 decimalNumberByMultiplyingBy:dNum2];
// dNum1 / dNum2
NSDecimalNumber *div = [dNum1 decimalNumberByDividingBy:dNum2];

四捨五入(小数点以下2桁の例)

NSDecimalNumberHandler *round = [NSDecimalNumberHandler
                                 decimalNumberHandlerWithRoundingMode:NSRoundPlain
                                 scale:2
                                 raiseOnExactness:NO
                                 raiseOnOverflow:NO
                                 raiseOnUnderflow:NO
                                 raiseOnDivideByZero:YES];
NSDecimalNumber *rounded = [dNum1 decimalNumberByMultiplyingBy:dNum2 withBehavior:round];

比較

NSComparisonResult result = [dNum1 compare:dNum2];
if (result == NSOrderedAscending) {
    NSLog(@"dNum1 < dNum2");
} else if (result == NSOrderedSame) {
    NSLog(@"dNum1 == dNum2");
} else if (result == NSOrderedDescending) {
    NSLog(@"dNum1 > dNum2");
}

NSMutableDictionaryをNSUserDefaultsで保存・取り出し

ここを参照して単純な例を作ってみました。ほとんどそのままです。

NSMutableDictionaryはNSUserDefaultsで保存するとimmutableになってしまうので、取り出すときmutableCopyを使ってmutalbeに戻してやればいいようです。

// 辞書を適当に作る
NSMutableDictionary *mDict1 = [@{@"key1":@1, @"key2":@2} mutableCopy];

// 保存
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:mDict1 forKey:@"Dic"];

// 読み込みんでmutableにする
NSDictionary *dict = [defaults objectForKey:@"Dic"];
NSMutableDictionary *mDict2 = [dict mutableCopy];

// 値を足してみる
mDict2[@"key3"] = @3;
mDict2[@"key4"] = @4;

for (NSString *key in [mDict2 allKeys]) {
    NSLog(@"key:%@, value:%@", key, [mDict2 objectForKey:key]);
}

Objective-Cで簡単な正規表現を使う

Objective-Cで正規表現を使うのrubyなどに比べてちょっと面倒ですが、単純なものなら簡単に処理できるようです。

文字列「あいう(えお)」からカッコ前と、カッコの中を取り出す
正規表現/(.+)\s*((.+))/だとすると、必要な文字列は

@"(.+)\\s*\\((.+)\\)";

になります。バックスペースは「\」となります。あとはパターンに当てはめてば良いだけでした。


NSString *regexpStr = @"(.+)\\s*\\((.+)\\)";
NSRegularExpression *regexp 
= [NSRegularExpression regularExpressionWithPattern:regexpStr options:0 error:nil];
NSTextCheckingResult *match 
= [regexp firstMatchInString:itemStr options:0 range:NSMakeRange(0, str.length)];
if (match.numberOfRanges) {    // マッチした全体    
    NSString *str0 = [itemStr substringWithRange:[match rangeAtIndex:0]]; // 最初のカッコの中
    NSString *str1 = [itemStr substringWithRange:[match rangeAtIndex:1]]; // 2番目のカッコ の中
    NSString *str2 = [itemStr substringWithRange:[match rangeAtIndex:2]];  
    ...