29244


Swift2.2からSwift3に移行しており、NSMakeRangeを書き換える際にエラーが発生しました。  
そのエラーは解消できているのですが、処理でどうしても腑に落ちない点があります。

Swift2.2

[code]

    let data = "あいうえお"dataUsingEncoding(NSShiftJISStringEncoding)
    let subData = data?.subdataWithRange(NSMakeRange(0, 10))
    
[/code]

Swift3

[code]

    let data = "あいうえお".data(using: String.Encoding.shiftJIS) // 10bytes
    let subData = data?.subdata(in: 0 ..< 10)
    
[/code]

この場合、`NSMakeRange(0, 10)`なので`0 ..<
11`にして、0〜10の範囲を取得できるだろうと思っていたらエラーが発生し、以下のログが出力されました。

[code]

    Termination app due to uncaught exception NSRangeException, reason: -[_MSInlineData subdataWithRange:]: range {0, 11} exceeds data length 10
    
[/code]

今までの記憶では  
`0 ..< 10` => `0, 1, 2, 3, 4, 5, 6, 7, 8, 9`  
`0 ... 10` => `0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10`  
と考えていました。

なのでエラーとなったのが理解できません。

`for~in`では今までの記憶通りの動きをしてくれたので、この`data(using:)`の場合のみ違うということでしょうか？


CC BY-SA 3.0
2016-09-29T08:36:45.763
29239
2016-09-29T10:30:10.000
14782
question
swift ios swift3
`..<`の動きについて


すでに nagonsoftware さんのコメントにありますが、もう少しだけご説明を。

`NSMakeRange(0, 10)`で表現される範囲は次のようなものです。

[code]

    |<------------- len = 10 ------------->| 長さが10
    [ 0][ 1][ 2][ 3][ 4][ 5][ 6][ 7][ 8][ 9][10][11]...
     ↑loc(開始位置)が0
    
[/code]

一方Swiftの`..<`演算子は`(開始位置)..<(終了位置の次)`で範囲を表しますので、上記と同じ範囲を表そうと思うと、`0..<10`でなければなりません。

一般的に、

[code]

    NSMakeRange(loc, len)
    
[/code]

で表されていた範囲(`Range<Int>`)を、`..<`で表現すると、

[code]

    loc..<loc+len
    
[/code]

となります。


CC BY-SA 3.0
2016-09-29T10:30:10.000
29244
2016-09-29T10:30:10.000
13972
29239
answer