Stringのpath操作系のメソッドをExtensionで復活させる

*(2016/09/19: 投稿をSwift3.0に対応)*

*stringByAppendingPathComponent:* といったpath操作系のメソッドがSwift2.0以降 **String**から直接呼び出すことができない(メソッドがなくなった)ので、これを **Extension** で生やしてみます。
(厳密には、 **URL**でこれらのメソッドが使えますが、毎回 `String→URL→String` とするのはおそろしくだるいので、こちらのほうがお手軽です。

## Swift 3.0

```swift
import Foundation

extension String {
    
    private var ns: NSString {
        return (self as NSString)
    }
    
    public func substring(from index: Int) -> String {
        return ns.substring(from: index)
    }
    
    public func substring(to index: Int) -> String {
        return ns.substring(to: index)
    }
    
    public func substring(with range: NSRange) -> String {
        return ns.substring(with: range)
    }
    
    public var lastPathComponent: String {
        return ns.lastPathComponent
    }
    
    public var pathExtension: String {
        return ns.pathExtension
    }
    
    public var deletingLastPathComponent: String {
        return ns.deletingLastPathComponent
    }
    
    public var deletingPathExtension: String {
        return ns.deletingPathExtension
    }
    
    public var pathComponents: [String] {
        return ns.pathComponents
    }
    
    public func appendingPathComponent(_ str: String) -> String {
        return ns.appendingPathComponent(str)
    }
    
    public func appendingPathExtension(_ str: String) -> String? {
        return ns.appendingPathExtension(str)
    }
}
```

**ポイント**は、一度**String**を**NSString**にしてから、NSStringのメソッドとしてそれぞれ呼び出してあげます。

```swift

// ---
    let dir = "path/to/foo"
    let path = dir.appendingPathComponent("test.txt") // OK!
    print(path) // "path/to/foo/test.txt"
```

## 〜Swift2.3
```swift:StringExtensions.swift
//  StringExtensions.swift

import Foundation

extension String {
    
    /// String -> NSString に変換する
    func to_ns() -> NSString {
        return (self as NSString)
    }
    
    func substringFromIndex(index: Int) -> String {
        return to_ns().substringFromIndex(index)
    }
    
    func substringToIndex(index: Int) -> String {
        return to_ns().substringToIndex(index)
    }
    
    func substringWithRange(range: NSRange) -> String {
        return to_ns().substringWithRange(range)
    }
    
    var lastPathComponent: String {
        return to_ns().lastPathComponent
    }
    
    var pathExtension: String {
        return to_ns().pathExtension
    }
    
    var stringByDeletingLastPathComponent: String {
        return to_ns().stringByDeletingLastPathComponent
    }
    
    var stringByDeletingPathExtension: String {
        return to_ns().stringByDeletingPathExtension
    }
    
    var pathComponents: [String] {
        return to_ns().pathComponents
    }
    
    var length: Int {
        return self.characters.count
    }
        
    func stringByAppendingPathComponent(path: String) -> String {
        return to_ns().stringByAppendingPathComponent(path)
    }
    
    func stringByAppendingPathExtension(ext: String) -> String? {
        return to_ns().stringByAppendingPathExtension(ext)
    }

}
```

```swift

// ---
    let dir = "path/to/foo"
    let path = dir.stringByAppendingPathComponent("test.txt") // OK!
    print(path) // "path/to/foo/test.txt"
```