Po pierwsze, twój "tradycyjny sposób" nie jest równoważny "Swift".
Dostęp do wersji SwiftyJSON ma 45 subscript
, ale dostęp natywny ma tylko 23 subscript
.
Aby "natywny sposób" odpowiednik, powinno być coś takiego:
let openDescription = attraction["OpeningHours"]!["OpeningHoursGenericExceptions"] as String
let monOpen = (attraction["OpeningHours"]!["Monday"]!!["From"] as String).componentsSeparatedByString(":")
let monClose = (attraction["OpeningHours"]!["Monday"]!!["To"] as String).componentsSeparatedByString(":")
let tueOpen = (attraction["OpeningHours"]!["Tuesday"]!!["From"] as String).componentsSeparatedByString(":")
let tueClose = (attraction["OpeningHours"]!["Tuesday"]!!["To"]! as String).componentsSeparatedByString(":")
// ...
lub "Swifty sposób" powinno być:
let openHours = json[0]["OpeningHours"]
var day:JSON
day = openHours["Monday"]
if let open = day["From"].string {
monOpen = open.componentsSeparatedByString(":")
}
if let close = day["To"].string {
monClose = close.componentsSeparatedByString(":")
}
day = openHours["Tuesday"]
if let open = day["From"].string {
tueOpen = open.componentsSeparatedByString(":")
}
if let close = day["To"].string {
tueClose = close.componentsSeparatedByString(":")
}
// ...
Zresztą Tak, SwiftyJSON jest powolny. Załóżmy miara:
import Foundation
import XCTest
let orgJson:AnyObject = [
[
"OpeningHours": [
"OpeningHoursGenericExceptions": "test",
"Monday": ["From":"1:2:3","To":"1:2:3"],
"Tuesday": ["From":"1:2:3","To":"1:2:3"],
"Wednesday": ["From":"1:2:3","To":"1:2:3"],
"Thursday": ["From":"1:2:3","To":"1:2:3"],
"Friday": ["From":"1:2:3","To":"1:2:3"],
"Saturday": ["From":"1:2:3","To":"1:2:3"],
"Sunday": ["From":"1:2:3","To":"1:2:3"],
]
]
]
let json = JSON(orgJson)
class JSONTestTests: XCTestCase {
func testNativeSubscript() {
measureBlock {() -> Void in
for _ in 0 ..< 400 {
autoreleasepool {
if let attraction = orgJson[0] as? NSDictionary {
let openDescription = attraction["OpeningHours"]!["OpeningHoursGenericExceptions"] as String
let monOpen = (attraction["OpeningHours"]!["Monday"]!!["From"] as String).componentsSeparatedByString(":")
let monClose = (attraction["OpeningHours"]!["Monday"]!!["To"] as String).componentsSeparatedByString(":")
let tueOpen = (attraction["OpeningHours"]!["Tuesday"]!!["From"] as String).componentsSeparatedByString(":")
let tueClose = (attraction["OpeningHours"]!["Tuesday"]!!["To"] as String).componentsSeparatedByString(":")
let wedOpen = (attraction["OpeningHours"]!["Wednesday"]!!["From"] as String).componentsSeparatedByString(":")
let wedClose = (attraction["OpeningHours"]!["Wednesday"]!!["To"] as String).componentsSeparatedByString(":")
let thuOpen = (attraction["OpeningHours"]!["Thursday"]!!["From"] as String).componentsSeparatedByString(":")
let thuClose = (attraction["OpeningHours"]!["Thursday"]!!["To"] as String).componentsSeparatedByString(":")
let friOpen = (attraction["OpeningHours"]!["Friday"]!!["From"] as String).componentsSeparatedByString(":")
let friClose = (attraction["OpeningHours"]!["Friday"]!!["To"] as String).componentsSeparatedByString(":")
let satOpen = (attraction["OpeningHours"]!["Saturday"]!!["From"] as String).componentsSeparatedByString(":")
let satClose = (attraction["OpeningHours"]!["Saturday"]!!["To"] as String).componentsSeparatedByString(":")
let sunOpen = (attraction["OpeningHours"]!["Sunday"]!!["From"] as String).componentsSeparatedByString(":")
let sunClose = (attraction["OpeningHours"]!["Sunday"]!!["To"] as String).componentsSeparatedByString(":")
XCTAssertEqual(monOpen, ["1","2","3"], "")
XCTAssertEqual(openDescription, "test")
}
}
}
}
}
func testJSONSubscript() {
measureBlock {() -> Void in
for _ in 0 ..< 400 {
autoreleasepool {
let attraction = json[0]
let openDescription:String = attraction["OpeningHours"]["OpeningHoursGenericExceptions"].string!
let monOpen:[String] = attraction["OpeningHours"]["Monday"]["From"].string!.componentsSeparatedByString(":")
let monClose:[String] = attraction["OpeningHours"]["Monday"]["To"].string!.componentsSeparatedByString(":")
let tueOpen:[String] = attraction["OpeningHours"]["Tuesday"]["From"].string!.componentsSeparatedByString(":")
let tueClose:[String] = attraction["OpeningHours"]["Tuesday"]["To"].string!.componentsSeparatedByString(":")
let wedOpen:[String] = attraction["OpeningHours"]["Wednesday"]["From"].string!.componentsSeparatedByString(":")
let wedClose:[String] = attraction["OpeningHours"]["Wednesday"]["To"].string!.componentsSeparatedByString(":")
let thuOpen:[String] = attraction["OpeningHours"]["Thursday"]["From"].string!.componentsSeparatedByString(":")
let thuClose:[String] = attraction["OpeningHours"]["Thursday"]["To"].string!.componentsSeparatedByString(":")
let friOpen:[String] = attraction["OpeningHours"]["Friday"]["From"].string!.componentsSeparatedByString(":")
let friClose:[String] = attraction["OpeningHours"]["Friday"]["To"].string!.componentsSeparatedByString(":")
let satOpen:[String] = attraction["OpeningHours"]["Saturday"]["From"].string!.componentsSeparatedByString(":")
let satClose:[String] = attraction["OpeningHours"]["Saturday"]["To"].string!.componentsSeparatedByString(":")
let sunOpen:[String] = attraction["OpeningHours"]["Sunday"]["From"].string!.componentsSeparatedByString(":")
let sunClose:[String] = attraction["OpeningHours"]["Sunday"]["To"].string!.componentsSeparatedByString(":")
XCTAssertEqual(monOpen, ["1","2","3"], "")
}
}
}
}
func testNativeBinding() {
measureBlock {() -> Void in
for _ in 0 ..< 400 {
autoreleasepool {
var monOpen:[String] = []
var monClose:[String] = []
var tueOpen:[String] = []
var tueClose:[String] = []
var wedOpen:[String] = []
var wedClose:[String] = []
var thuOpen:[String] = []
var thuClose:[String] = []
var friOpen:[String] = []
var friClose:[String] = []
var satOpen:[String] = []
var satClose:[String] = []
var sunOpen:[String] = []
var sunClose:[String] = []
var openDescription:String = ""
if let attractionsArray = orgJson as? NSArray{
if let attraction = attractionsArray[0] as? NSDictionary{
if let openHours = attraction["OpeningHours"] as? NSDictionary{
if let day = openHours["Monday"] as? NSDictionary{
if let open = day["From"] as? String{
monOpen = open.componentsSeparatedByString(":")
}
if let close = day["To"] as? String{
monClose = close.componentsSeparatedByString(":")
}
}
if let day = openHours["Tuesday"] as? NSDictionary{
if let open = day["From"] as? String{
tueOpen = open.componentsSeparatedByString(":")
}
if let close = day["To"] as? String{
tueClose = close.componentsSeparatedByString(":")
}
}
if let day = openHours["Wednesday"] as? NSDictionary{
if let open = day["From"] as? String{
wedOpen = open.componentsSeparatedByString(":")
}
if let close = day["To"] as? String{
wedClose = close.componentsSeparatedByString(":")
}
}
if let day = openHours["Thursday"] as? NSDictionary{
if let open = day["From"] as? String{
thuOpen = open.componentsSeparatedByString(":")
}
if let close = day["To"] as? String{
thuClose = close.componentsSeparatedByString(":")
}
}
if let day = openHours["Friday"] as? NSDictionary{
if let open = day["From"] as? String{
friOpen = open.componentsSeparatedByString(":")
}
if let close = day["To"] as? String{
friClose = close.componentsSeparatedByString(":")
}
}
if let day = openHours["Saturday"] as? NSDictionary{
if let open = day["From"] as? String{
satOpen = open.componentsSeparatedByString(":")
}
if let close = day["To"] as? String{
satClose = close.componentsSeparatedByString(":")
}
}
if let day = openHours["Sunday"] as? NSDictionary{
if let open = day["From"] as? String{
sunOpen = open.componentsSeparatedByString(":")
}
if let close = day["To"] as? String{
sunClose = close.componentsSeparatedByString(":")
}
}
if let desc = openHours["OpeningHoursGenericExceptions"] as? String{
openDescription = desc
}
}
}
}
XCTAssertEqual(monOpen, ["1","2","3"], "")
}
}
}
}
func testJSONBinding() {
measureBlock {() -> Void in
for _ in 0 ..< 400 {
autoreleasepool {
var monOpen:[String] = []
var monClose:[String] = []
var tueOpen:[String] = []
var tueClose:[String] = []
var wedOpen:[String] = []
var wedClose:[String] = []
var thuOpen:[String] = []
var thuClose:[String] = []
var friOpen:[String] = []
var friClose:[String] = []
var satOpen:[String] = []
var satClose:[String] = []
var sunOpen:[String] = []
var sunClose:[String] = []
var openDescription:String = ""
let openHours = json[0]["OpeningHours"]
var day:JSON
day = openHours["Monday"]
if let open = day["From"].string {
monOpen = open.componentsSeparatedByString(":")
}
if let close = day["To"].string {
monClose
= close.componentsSeparatedByString(":")
}
day = openHours["Tuesday"]
if let open = day["From"].string {
tueOpen = open.componentsSeparatedByString(":")
}
if let close = day["To"].string {
tueClose = close.componentsSeparatedByString(":")
}
day = openHours["WednesDay"]
if let open = day["From"].string {
wedOpen = open.componentsSeparatedByString(":")
}
if let close = day["To"].string {
wedClose = close.componentsSeparatedByString(":")
}
day = openHours["Thursday"]
if let open = day["From"].string {
thuOpen = open.componentsSeparatedByString(":")
}
if let close = day["To"].string {
thuClose = close.componentsSeparatedByString(":")
}
day = openHours["Friday"]
if let open = day["From"].string {
friOpen = open.componentsSeparatedByString(":")
}
if let close = day["To"].string {
friClose = close.componentsSeparatedByString(":")
}
day = openHours["Saturday"]
if let open = day["From"].string {
satOpen = open.componentsSeparatedByString(":")
}
if let close = day["To"].string {
satClose = close.componentsSeparatedByString(":")
}
day = openHours["Sunday"]
if let open = day["From"].string {
sunOpen = open.componentsSeparatedByString(":")
}
if let close = day["To"].string {
sunClose = close.componentsSeparatedByString(":")
}
XCTAssertEqual(monOpen, ["1","2","3"], "")
}
}
}
}
}
Wyjścia:
<unknown>:0: Test Case '-[JSONTestTests.JSONTestTests testJSONBinding]' measured [Time, seconds] average: 0.804, relative standard deviation: 5.592%, values: [0.835687, 0.814827, 0.819685, 0.841900, 0.764961, 0.845202, 0.691442, 0.779255, 0.818213, 0.830698], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100
<unknown>:0: Test Case '-[JSONTestTests.JSONTestTests testJSONSubscript]' measured [Time, seconds] average: 4.247, relative standard deviation: 3.496%, values: [4.019640, 4.004123, 4.146146, 4.194535, 4.487171, 4.300971, 4.310613, 4.408405, 4.318354, 4.279362], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100
<unknown>:0: Test Case '-[JSONTestTests.JSONTestTests testNativeBinding]' measured [Time, seconds] average: 0.223, relative standard deviation: 2.773%, values: [0.221099, 0.227395, 0.218860, 0.225989, 0.227128, 0.222370, 0.229956, 0.214535, 0.210818, 0.229868], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100
<unknown>:0: Test Case '-[JSONTestTests.JSONTestTests testNativeSubscript]' measured [Time, seconds] average: 0.362, relative standard deviation: 17.528%, values: [0.346285, 0.316185, 0.333650, 0.339416, 0.330243, 0.354034, 0.378730, 0.269519, 0.486904, 0.467607], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100
- Twój SwiftyJSON: 4,247
- swój ojczysty: 0,223
- Moja SwiftyJSON: 0,804
- mojego rodzinnego: 0,362
Nawiasem mówiąc, gdybym był tobą, chciałbym zrobić coś takiego:
if let hours = orgJson[0]?["OpeningHours"] as? NSDictionary {
let openDescription = hours["OpeningHoursGenericExceptions"] as? String ?? ""
let monOpen = hours["Monday"]?["From"]??.componentsSeparatedByString?(":") as? [String] ?? []
let monClose = hours["Monday"]?["To"]??.componentsSeparatedByString?(":") as? [String] ?? []
let tueOpen = hours["Tuesday"]?["From"]??.componentsSeparatedByString?(":") as? [String] ?? []
let tueClose = hours["Tuesday"]?["To"]??.componentsSeparatedByString?(":") as? [String] ?? []
let wedOpen = hours["Wednesday"]?["From"]??.componentsSeparatedByString?(":") as? [String] ?? []
let wedClose = hours["Wednesday"]?["To"]??.componentsSeparatedByString?(":") as? [String] ?? []
let thuOpen = hours["Thursday"]?["From"]??.componentsSeparatedByString?(":") as? [String] ?? []
let thuClose = hours["Thursday"]?["To"]??.componentsSeparatedByString?(":") as? [String] ?? []
let friOpen = hours["Friday"]?["From"]??.componentsSeparatedByString?(":") as? [String] ?? []
let friClose = hours["Friday"]?["To"]??.componentsSeparatedByString?(":") as? [String] ?? []
let satOpen = hours["Saturday"]?["From"]??.componentsSeparatedByString?(":") as? [String] ?? []
let satClose = hours["Saturday"]?["To"]??.componentsSeparatedByString?(":") as? [String] ?? []
let sunOpen = hours["Sunday"]?["From"]??.componentsSeparatedByString?(":") as? [String] ?? []
let sunClose = hours["Sunday"]?["To"]??.componentsSeparatedByString?(":") as? [String] ?? []
// ...
}
To dość szybki, bezpieczny, nie tak skomplikowane.
Dlaczego SwiftyJSON jest wolny?
Na subscript
dostępu SwiftyJSON robi:
- check kluczem jest
String
- indeks ponownie
self[key:sub]
- czeku bazowy obiekt jest
NSDictionary
- indeks bazowego
NSDictionary
pomocą dostarczonego klucza
- skonstruuj obiekt
JSON
z wynikiem
return
Może kompilator optymalizuje pewne kroki, ale „wolniejszy niż natywny” jest nieco nieuniknione :)
Dziękuję za bardzo dokładny odpowiedź! I z benchmarkami! Ponieważ jestem bardzo nowy w Swift (przypuszczam, że wiele osób jest :) wiele kodowania to first-try-trial-and-error i zrobiłem parsowanie JSON zgodnie z sugestią w pliku SwiftyJSON README. Patrząc na różne przykłady metod analizowania, nie żałuję, że szybko wycofałem się z mojego projektu, złożoność "natywnego" analizowania nie stanowi problemu i dodaje różnicę wydajności, której nie widzę jako opcji. – Simpa
Mam na myśli bez obrazy dla twórcy Swifty, myślę, że może on mieć wielkie zastosowanie dla wielu programistów. Ale "szybka analiza JSONA", która tylko daje wyniki przy użyciu sprytności, dała mi wrażenie, że jest to właściwa droga. Ale może to nie jest dla wszystkich? :) – Simpa
@Simpa w świecie Swift, wielu hitu w Google nie można ufać. Można odnieść wrażenie, że Objective-C nie żyje, Cocoapods jest akceptowany jako standard, itp. Itd. ... w rzeczywistości, wydaje mi się, że wiele z tych zjawisk jest problematycznych. Czy jednak SwiftyJSON jest zbyt wolny w użyciu? To kolejne pytanie, ale gdybyś uzyskał te wyniki pierwotnie, mógłbyś tego nie zauważyć. –