人生ずっと勉強

人生ずっと勉強ですね。 https://twitter.com/KiyotakaGoto

レシーバが nil だった場合の戻り値

ハマったのでメモ。
詳解 Objective-C 2.0 第3版 の63ページより。

返り値の型 返り値
オブジェクト nil
ポインタ NULL
整数 0
それ以外 OS のバージョンなどで異なるため、不定と考えるのが無難

背景

UILocalNotification に設定した通知を削除するために、設定時に userInfo に適当な値を設定して、
キーをもとに通知を消す以下の様なコードを書いた。

- (void) setNotification {
    UILocalNotification *notification = [[UILocalNotification alloc] init];
    
    notification.fireDate = [[NSDate date] addTimeInterval:60]; 
    notification.timeZone = [NSTimeZone defaultTimeZone];
    notification.alertBody = @"Notification";
    notification.alertAction = @"Open";
    notification.soundName = UILocalNotificationDefaultSoundName;
    notification.applicationIconBadgeNumber = 1;
    [ notification.userInfo setValue:@"set" forKey:@"notificationTime" ];

    [[UIApplication sharedApplication] scheduleLocalNotification:notification];
}

- (void) deleteNotification {

    for(UILocalNotification *notification in [[UIApplication sharedApplication] scheduledLocalNotifications]) {

        if(  [notification.userInfo objectForKey:@"notificationTime"]  ) {
            [[UIApplication sharedApplication] cancelLocalNotification:notification];
        }
    }

}

しかし、エラーも何も起こらず、 if 内に分岐しない。
デバッグしてみると、そもそも notification.userInfo プロパティは NSDictionary 型で、何らかのNSDictionary 型のインスタンスを生成して値として設定しない限り nil であることがわかった。

同時に、そういえばレシーバが nil のときの挙動について何かで見たぞと思いだし、詳解 objective-c を調べてみると、やはりそうだった、というオチ。
なので、以下のように修正。

notification.userInfo = @{ @"notificationTime":@"set" };