2017年03月21日

[Swift2]NSCalendarUnitの合成


NSDateから年・月・日などの数字だけを抜き出すときにNSDateComonentsを使うんだけど、Swiftでちょっと書き方が変わった部分がある。

Objective-C時代はこんな書き方でした。リファレンスからの抜粋。


unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDate *date = [NSDate date];
NSDateComponents *comps = [gregorian components:unitFlags fromDate:date];


これがSiwft2では以下のようになるとリファレンスには書かれている。これだとObjective-Cとさほど代わりはない。


let flags: NSCalendarUnit = .DayCalendarUnit | .MonthCalendarUnit | .YearCalendarUnit
let date = NSDate()
let components = gregorian.components(flags, fromDate: date)


ところがこれを Xcode 7.2.1 で書くと、エラーになってしまってコンパイルできない。


Type of expression is ambiguous without more context


型が分からないというなら直接的に指定するしかないと指定する。


let flags2: NSCalendarUnit = NSCalendarUnit.Day | NSCalendarUnit.Month | NSCalendarUnit.Year


が、するとまた別のエラーになる。


Binary operator '|' cannot be applied to two 'NSCalendarUnit' operands'



じゃあ、一体どう指定するんだよ?と強引に指定するとこんな風になる。


let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
let flags = NSCalendarUnit(rawValue: NSCalendarUnit.Year.rawValue
+ NSCalendarUnit.Month.rawValue
+ NSCalendarUnit.Day.rawValue
)
guard let comps = calendar?.components(flags, fromDate: date) else {
return
}
let year = comps.year, month = comps.month, day = comps.day


確かにこれだと正常に実行できるんだけど、あまりにも強引すぎてもっときれいな書き方があっていいはずなんだけど。

Swift3ではこんな書き方になる(クラス名等はSwift2のまま)。


let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
guard let comps = calendar?.components([.Year,.Month,.Day], fromDate: date) else {
return
}


そしてこれがまたコンパイルが通って正常に実行される。Swift3ではメソッドがSetで定義されているのでこれでもいいのだが、Swift2ではcomponents(flags:NSCalendarUnit, fromDate: NSDate)とNSCalendarUnitで定義されているので[NSCalendarUnit]で渡して渡せる理由がわからない。

そこでこんな書き方をしてみたら、ようやくなぜだかわかった。


let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
let flags = NSCalendarUnit([.Year,.Month,.Day])
guard let comps = calendar?.components(flags, fromDate: date) else {
return
}


リファレンスとかからはわからないけどNSCalendarUnitのコンストラクタに配列を取るものがあるってことなんでしょう。

posted by 永遠製作所 at 15:16| 東京 ☔| Comment(0) | TrackBack(0) | Swift | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

※ブログオーナーが承認したコメントのみ表示されます。

この記事へのトラックバック