我創建了一個最小的,完整的,並且可驗證的例子(MCVE)出來的原代碼,和我做了它在斯威夫特3遊樂場工作
import UIKit
import XCTest
extension Date
{
init?(year: Int, month: Int, day: Int) {
var dateComponents = DateComponents()
dateComponents.day = day
dateComponents.month = month
dateComponents.year = year
guard let date = Calendar.current.date(from: dateComponents)
else { return nil }
self = date
}
}
struct MyObject {
var created: Date
}
protocol MyProtocol {
var myArray: [MyObject] { get set }
}
extension MyProtocol {
mutating func sortArrayByCreationTime() {
myArray.sort {
$0.created > $1.created
}
}
}
struct ArrayContainer: MyProtocol {
var myArray: [MyObject]
}
let objects = [
MyObject(created: Date(year: 2016, month: 9, day: 1)!),
MyObject(created: Date(year: 2016, month: 11, day: 1)!),
MyObject(created: Date(year: 2016, month: 4, day: 1)!),
MyObject(created: Date(year: 2016, month: 8, day: 1)!),
]
var container = ArrayContainer(myArray: objects)
var dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMdd"
XCTAssertEqual(["0901", "1101", "0401", "0801"],
container.myArray.map { dateFormatter.string(from: $0.created) })
container.sortArrayByCreationTime()
XCTAssertEqual(["1101", "0901", "0801", "0401"],
container.myArray.map { dateFormatter.string(from: $0.created) })
我舉兩個選擇:
選項1:改進
在選項1中,擴展Array結構,以便您可以創建變異方法sortByCreationDate
。存在需要被拉出一個帽子以延長[MyObject來](爲MyObject的陣列)
protocol MyObjectProtocol { var created: Date { get set } }
extension MyObject: MyObjectProtocol { }
extension Array where Element: MyObjectProtocol {
mutating func sortByCreationTime() {
self.sort {
$0.created > $1.created
}
}
}
var container2 = ArrayContainer(myArray: objects)
XCTAssertEqual(["0901", "1101", "0401", "0801"],
container2.myArray.map { dateFormatter.string(from: $0.created) })
container2.myArray.sortByCreationTime()
XCTAssertEqual(["1101", "0901", "0801", "0401"],
container2.myArray.map { dateFormatter.string(from: $0.created) })
選項2特技:更好
在選項2,延伸序列。一個序列將允許您排序數組的對象和其他類型的對象,例如字典。更好的是,它不會創建變異方法。但老實說MyProtocol
是一個令人困惑的API。用這種方法,MyProtocol
不再是必需的。
extension Sequence where Iterator.Element == MyObject {
func sortedByCreationTime() -> [Iterator.Element] {
return self.sorted {
$0.created > $1.created
}
}
}
var container3 = ArrayContainer(myArray: objects)
XCTAssertEqual(["0901", "1101", "0401", "0801"],
container3.myArray.map { dateFormatter.string(from: $0.created) })
XCTAssertEqual(["1101", "0901", "0801", "0401"],
container3.myArray.sortedByCreationTime().map { dateFormatter.string(from: $0.created) })
你的代碼永遠不會編譯,因爲它保證編譯器有一個數組元素具有'created'屬性嗎? – matt
@matt顯然編譯器可以從'MyObject'類型推斷'created'屬性。 – vadian
@vadian我的觀點是OP應該顯示MyObject作爲問題的一部分。 MCVE需要足夠的代碼進行編譯。 – matt