search
LoginSignup
7

More than 5 years have passed since last update.

Organization

オブジェクトを文字列化するときの書式を変える

NSDateクラスの内容を任意の書式で文字列化したいとき、毎度毎度NSDateFormatterクラスを通すのはしんどいです。
かと言って、カテゴリで新たにメソッドを実装しても、毎度毎度それを呼び出すのは正直面倒いです。これはひどい。

NSObjectクラスは、文字列化されるときこっそりとdescriptionメソッドを呼び出します。
MethodSwizzlingでそれを差し替えてやれば、デフォルトの書式を変えられそう。

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

int main(int argc, char *argv[]) {
    @autoreleasepool {
        NSLog(@"%@", [NSDate distantFuture]); // 4001-01-01 00:00:00 +0000

        Class nsdate = [NSDate class];

        // と言いつつ今回差し替えるのは`descriptionWithLocale:`
        // NSDateは他に`description`と`descriptionWithCalendarFormat:timeZone:locale:`がある
        SEL name = @selector(descriptionWithLocale:);

        // 新しい`descriptionWithLocale:`メソッド、Blocksの第一引数が`self`の代わりになる
        IMP description = imp_implementationWithBlock(^NSString*(id obj, id locale) {
            NSDateFormatter* format = [[NSDateFormatter alloc] init];
            [format setDateFormat:@"yyyy/MM/dd HH:mm:ss"];
            return [format stringFromDate:obj];
        });

        class_replaceMethod(nsdate, name, description,
            method_getTypeEncoding(class_getInstanceMethod(nsdate, name)));

        NSLog(@"%@", [NSDate distantFuture]); // 4001/01/01 09:00:00

        return 0;
    }
}

実用性は投げ捨てるもの。

BlockからSelector(メソッド)を作る - Qiita
Methodの処理を差し替える - MethodSwizzling - Qiita
NSDate Class Reference - Mac Developer Library

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
What you can do with signing up
7