2016-01-22 9 views
5

मैं बहुत सारे एसिंक नेटवर्क अनुरोध का उपयोग कर रहा हूं (आईओएस में किसी भी नेटवर्क अनुरोध को एएसआईएनसी द्वारा की आवश्यकता है) और मुझे ऐप्पल के dataTaskWithRequest से त्रुटियों को बेहतर तरीके से संभालने का तरीका मिल रहा है जो throws का समर्थन नहीं करता है।स्विफ्ट 2 में एसिंक बंद करने से त्रुटियों को संभालने का सबसे अच्छा तरीका?

मैं उस तरह कोड है:

func sendRequest(someData: MyCustomClass?, completion: (response: NSData?) ->()) { 
    let request = NSURLRequest(URL: NSURL(string: "http://google.com")!) 

    if someData == nil { 
     // throw my custom error 
    } 

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { 
     data, response, error in 

     // here I want to handle Apple's error 
    } 
    task.resume() 
} 

मैं अपने संभव कस्टम पार्स त्रुटियाँ और dataTaskWithRequest से संभावित संबंध त्रुटियों को संभालने की जरूरत है। स्विफ्ट 2 ने throws पेश किया, लेकिन आप ऐप्पल के बंद होने से फेंक नहीं सकते क्योंकि उनके पास कोई फेंक समर्थन नहीं है और एसिंक चल रहा है।

मुझे अपने पूरा होने वाले ब्लॉक NSError में जोड़ने का एकमात्र तरीका दिखाई देता है, लेकिन जैसा कि मुझे पता है कि NSError पुराने शैली का उद्देश्य-सी तरीका है। ErrorType केवल फेंकने के साथ ही उपयोग किया जा सकता है (afaik)।

ऐप्पल नेटवर्क बंद करने का उपयोग करते समय त्रुटि को संभालने के लिए सबसे अच्छी और सबसे आधुनिक विधि क्या है? जैसा कि मैं समझता हूं किसी भी एसिंक नेटवर्क फ़ंक्शंस में कोई उपयोग नहीं होता है?

+0

आप फेंकता बिना ERRORTYPE उपयोग कर सकते हैं:

अब, आप इसे इस रूप में इस्तेमाल कर सकते हैं। यानी इसे अपने पूरा करने वाले हैंडलर में लौटाना। हो सकता है कि आप यह देखना चाहें कि अलामोफायर प्रतिक्रियाओं/त्रुटियों के साथ कैसे कार्य करता है https: // github।com/Alamofire/Alamofire/ब्लॉब/मास्टर/स्रोत/Result.swift – doschi

उत्तर

13

आप इसे हल करने के कई तरीके हैं, लेकिन मैं एक पूर्णता ब्लॉक का उपयोग करने की अनुशंसा करता हूं जो Result Enum की अपेक्षा करता है। यह शायद सबसे अधिक 'स्विफ्ट' तरीका होगा।

परिणाम enum में वास्तव में दो राज्य, सफलता और त्रुटि है, जो सामान्य दो वैकल्पिक वापसी मूल्यों (डेटा और त्रुटि) का एक बड़ा लाभ है जो 4 संभावित राज्यों का कारण बनती है।

enum Result<T> { 
    case Success(T) 
    case Error(String, Int) 
} 

एक पूर्णता ब्लॉक में परिणाम enum का उपयोग पहेली को खत्म करता है।

let InvalidURLCode = 999 
let NoDataCode = 998 
func getFrom(urlString: String, completion:Result<NSData> -> Void) { 
    // make sure the URL is valid, if not return custom error 
    guard let url = NSURL(string: urlString) else { return completion(.Error("Invalid URL", InvalidURLCode)) } 

    let request = NSURLRequest(URL: url) 
    NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in 
     // if error returned, extract message and code then pass as Result enum 
     guard error == nil else { return completion(.Error(error!.localizedDescription, error!.code)) } 

     // if no data is returned, return custom error 
     guard let data = data else { return completion(.Error("No data returned", NoDataCode)) } 

     // return success 
     completion(.Success(data)) 
    }.resume() 
} 

क्योंकि वापसी मूल्य एक enum है, तो आपको इसे बंद करना चाहिए।

getFrom("http://www.google.com") { result in 
    switch result { 
    case .Success(let data): 
     // handle successful data response here 
     let responseString = String(data:data, encoding: NSASCIIStringEncoding) 
     print("got data: \(responseString)"); 
    case .Error(let msg, let code): 
     // handle error here 
     print("Error [\(code)]: \(msg)") 
    } 
} 

एक और समाधान दो समापन ब्लॉक, एक सफलता के लिए और एक त्रुटि के लिए होगा। की तर्ज पर कुछ:

func getFrom(urlString: String, successHandler:NSData -> Void, errorHandler:(String, Int) -> Void) 
0

वहाँ एक सुरुचिपूर्ण दृष्टिकोण के लिए JavaScript की तरह वादा लाइब्रेरी या स्काला की तरह "भविष्य और वादा" पुस्तकालय का उपयोग है।

स्काला शैली वायदा और वादों का उपयोग करना, यह कुछ ऐसा नज़र हो सकता है:

आपका मूल कार्य

func sendRequest(someData: MyCustomClass?, completion: (response: NSData?) ->())

जैसा कि नीचे दिखाया लागू किया जा सकता है। यह भी पता चलता है,, एक वादा बनाने का तरीका एक असफल भविष्य और कैसे पूरा/के साथ जल्दी वापसी एक वादा अस्वीकार:

func sendRequest(someData: MyCustomClass) -> Future<NSData> { 
    guard let url = ... else { 
    return Future.failure(MySessionError.InvalidURL) // bail out early with a completed future 
    } 
    let request = ... // setup request 
    let promise = Promise<NSData>() 
    NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in 
    guard let error = error else { 
     promise.reject(error) // Client error 
    } 
    // The following assertions should be true, unless error != nil 
    assert(data != nil) 
    assert(response != nil) 

    // We expect HTTP protocol: 
    guard let response = response! as NSHTTPURLResponse else { 
     promise.reject(MySessionError.ProtocolError) // signal that we expected HTTP. 
    } 

    // Check status code: 
    guard myValidStatusCodeArray.contains(response.statusCode) else { 
     let message: String? = ... // convert the response data to a string, if any and if possible 
     promise.reject(MySessionError.InvalidStatusCode(statusCode: response.statusCode, message: message ?? "")) 
    } 

    // Check MIME type if given: 
    if let mimeType = response.MIMEType { 
     guard myValidMIMETypesArray.contains(mimeType) else { 
     promise.reject(MySessionError.MIMETypeNotAccepted(mimeType: mimeType)) 
     } 
    } else { 
     // If we require a MIMEType - reject the promise. 
    } 
    // transform data to some other object if desired, can be done in a later, too. 

    promise.fulfill(data!) 
    }.resume() 

    return promise.future! 
} 

आप प्रतिक्रिया के रूप में एक JSON उम्मीद कर सकते हैं - यदि अनुरोध सफल होता है।

sendRequest(myObject).map { data in 
    return try NSJSONSerialization.dataWithJSONObject(data, options: []) 
} 
.map { object in 
    // the object returned from the step above, unless it failed. 
    // Now, "process" the object: 
    ... 
    // You may throw an error if something goes wrong: 
    if failed { 
     throw MyError.Failed 
    } 
} 
.onFailure { error in 
    // We reach here IFF an error occurred in any of the 
    // previous tasks. 
    // error is of type ErrorType. 
    print("Error: \(error)") 
} 
संबंधित मुद्दे

 संबंधित मुद्दे