JSON के अनुरोध के लिए अलामोफायर अतुल्यकालिक पूर्णहैंडलर


80

AlamoFire फ्रेमवर्क का उपयोग करने के बाद मैंने देखा है कि पूर्णहैंडलर मुख्य धागे पर चलाया जाता है। Im सोच रहा था कि नीचे दिए गए कोड को पूरा करने वाले हैंडलर के भीतर कोर डेटा आयात कार्य बनाने के लिए एक अच्छा अभ्यास है:

Alamofire.request(.GET, "http://myWebSite.com", parameters: parameters)
            .responseJSON(options: .MutableContainers) { (_, _, JSON, error) -> Void in
                dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), { () -> Void in
                    if let err = error{
                        println("Error:\(error)")
                        return;
                    }

                    if let jsonArray = JSON as? [NSArray]{                       
                        let importer = CDImporter(incomingArray: jsonArray entity: "Artist", map: artistEntityMap);

                    }
                });
            }

जवाबों:


156

यह वास्तव में एक अच्छा सवाल है। आपका दृष्टिकोण पूरी तरह से मान्य है। हालाँकि, अलामॉफायर वास्तव में आपको इसे और भी अधिक कारगर बनाने में मदद कर सकता है।

आपका उदाहरण कोड डिस्पैच क्यू ब्रेकडाउन

आप उदाहरण कोड में, आप निम्न प्रेषण कतारों के बीच कूद रहे हैं:

  1. NSURLSession प्रेषण कतार
  2. टास्कडेलेगेट सत्यापन और धारावाहिक प्रसंस्करण के लिए कतार भेजते हैं
  3. अपने पूर्ण हैंडलर को बुलाने के लिए मुख्य प्रेषण कतार
  4. JSON हैंडलिंग के लिए उच्च प्राथमिकता कतार
  5. उपयोगकर्ता इंटरफ़ेस को अपडेट करने के लिए मुख्य प्रेषण कतार (यदि आवश्यक हो)

जैसा कि आप देख सकते हैं, आप सभी जगह रुक रहे हैं। आइए एक वैकल्पिक दृष्टिकोण पर एक नज़र डालें, जो आलमोफायर के अंदर एक शक्तिशाली विशेषता का लाभ उठाता है।

अल्मोफायर रिस्पांस डिस्पैच क्यु

Alamofire में एक इष्टतम दृष्टिकोण है जो स्वयं के निम्न स्तर के प्रसंस्करण में बनाया गया है। responseयदि आप इसका उपयोग करना चुनते हैं, तो एक ही विधि, जिसे अंततः सभी कस्टम प्रतिक्रिया क्रमकारों द्वारा बुलाया जाता है, एक कस्टम प्रेषण कतार के लिए समर्थन है।

जबकि जीसीडी प्रेषण कतारों के बीच hopping में अद्भुत है, आप एक कतार में कूदने से बचना चाहते हैं जो व्यस्त है (उदाहरण के लिए मुख्य धागा)। Async प्रसंस्करण के बीच में मुख्य थ्रेड पर वापस कूद को समाप्त करके, आप संभावित रूप से चीजों को काफी गति दे सकते हैं। निम्न उदाहरण दर्शाता है कि यह कैसे करना है अल्मॉफेयर तर्क का उपयोग सीधे आउट-ऑफ-द-बॉक्स।

आलमोफायर 1.x

let queue = dispatch_queue_create("com.cnoon.manager-response-queue", DISPATCH_QUEUE_CONCURRENT)

let request = Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
request.response(
    queue: queue,
    serializer: Request.JSONResponseSerializer(options: .AllowFragments),
    completionHandler: { _, _, JSON, _ in

        // You are now running on the concurrent `queue` you created earlier.
        println("Parsing JSON on thread: \(NSThread.currentThread()) is main thread: \(NSThread.isMainThread())")

        // Validate your JSON response and convert into model objects if necessary
        println(JSON)

        // To update anything on the main thread, just jump back on like so.
        dispatch_async(dispatch_get_main_queue()) {
            println("Am I back on the main thread: \(NSThread.isMainThread())")
        }
    }
)

अलमोफायर 3.x (स्विफ्ट 2.2 और 2.3)

let queue = dispatch_queue_create("com.cnoon.manager-response-queue", DISPATCH_QUEUE_CONCURRENT)

let request = Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
request.response(
    queue: queue,
    responseSerializer: Request.JSONResponseSerializer(options: .AllowFragments),
    completionHandler: { response in
        // You are now running on the concurrent `queue` you created earlier.
        print("Parsing JSON on thread: \(NSThread.currentThread()) is main thread: \(NSThread.isMainThread())")

        // Validate your JSON response and convert into model objects if necessary
        print(response.result.value)

        // To update anything on the main thread, just jump back on like so.
        dispatch_async(dispatch_get_main_queue()) {
            print("Am I back on the main thread: \(NSThread.isMainThread())")
        }
    }
)

अल्मोफायर 4.x (स्विफ्ट 3)

let queue = DispatchQueue(label: "com.cnoon.response-queue", qos: .utility, attributes: [.concurrent])

Alamofire.request("http://httpbin.org/get", parameters: ["foo": "bar"])
    .response(
        queue: queue,
        responseSerializer: DataRequest.jsonResponseSerializer(),
        completionHandler: { response in
            // You are now running on the concurrent `queue` you created earlier.
            print("Parsing JSON on thread: \(Thread.current) is main thread: \(Thread.isMainThread)")

            // Validate your JSON response and convert into model objects if necessary
            print(response.result.value)

            // To update anything on the main thread, just jump back on like so.
            DispatchQueue.main.async {
                print("Am I back on the main thread: \(Thread.isMainThread)")
            }
        }
    )

अल्मोफायर डिस्पैच क्यू ब्रेकडाउन

यहाँ इस दृष्टिकोण के साथ शामिल विभिन्न प्रेषण कतारों का टूटना है।

  1. NSURLSession प्रेषण कतार
  2. टास्कडेलेगेट सत्यापन और धारावाहिक प्रसंस्करण के लिए कतार भेजते हैं
  3. JSON हैंडलिंग के लिए कस्टम प्रबंधक समवर्ती प्रेषण कतार
  4. उपयोगकर्ता इंटरफ़ेस को अपडेट करने के लिए मुख्य प्रेषण कतार (यदि आवश्यक हो)

सारांश

मुख्य डिस्पैच कतार में पहले हॉप को समाप्त करके, आपने एक संभावित अड़चन को समाप्त कर दिया है और साथ ही साथ आपने अपने पूरे अनुरोध और प्रसंस्करण को अतुल्यकालिक बना दिया है। बहुत बढ़िया!

इसके साथ ही, मैं यह पर्याप्त तनाव नहीं कर सकता कि अल्मोफायर वास्तव में कैसे काम करता है, के आंतरिक से परिचित होना कितना महत्वपूर्ण है। आप कभी नहीं जानते हैं कि आपको कुछ ऐसा मिल सकता है जो वास्तव में आपको अपना कोड सुधारने में मदद कर सकता है।


3
पूरी तरह से स्पष्टीकरण के लिए धन्यवाद, @cnoon। ऐसा प्रतीत होता है कि responseविधि के लिए दूसरा पैरामीटर अब (अलामोफायर 3.0 में) के responseSerializerबजाय कहा जाता है serializer। उस Cannot call value of non-function type 'NSHTTPURLResponse?'त्रुटि के कारण मुझे थोड़ी उलझन हुई।
हेलेन मार्टिन

कृपया, परिवर्तन अपलोड करें, कोड काम करने योग्य नहीं है। स्विफ्ट 2.1,
एक्सकोड

प्रतिक्रिया के बारे में क्या? मैं कतार पैरामीटर में कैसे पास कर सकता हूं
OMGPOP

अगर आप स्विफ्ट 3 के लिए भी अपडेट जोड़ते हैं तो @cnoon, अच्छा हो सकता है।
माइक। 08

अब स्विफ्ट 3 के लिए भी काम करता है। शानदार
dejavu89 19

2

स्विफ्ट 3.0, अल्मोफायर (4.0.1) के लिए छोटा अपडेट, @cnoon उत्तर के लिए संपादित करें:

let queue = DispatchQueue(label: "com.cnoon.manager-response-queue",
                          qos: .userInitiated,
                          attributes:.concurrent)
Alamofire?.request(SERVER_URL, method: .post,
parameters: ["foo": "bar"], 
encoding: JSONEncoding.default,//by default
headers: ["Content-Type":"application/json; charset=UTF-8"])
.validate(statusCode: 200..<300).//by default
responseJSON(queue: queue, options: .allowFragments, 
completionHandler: { (response:DataResponse<Any>) in

        switch(response.result) {
        case .success(_):
            break
        case .failure(_):
            print(response.result.error)
            if response.result.error?._code == NSURLErrorTimedOut{
                //TODO: Show Alert view on netwok connection.
            }
            break
        }
    })

1

बस @cnoon से सही उत्तर को पूरक करना, अगर आप मुझे पसंद कर रहे हैं तो आप ResponseObjectSerializableअनुरोध के विस्तार पर इस समवर्ती व्यवहार को एम्बेड कर सकते हैं:

extension Request {
    public func responseObject<T: ResponseObjectSerializable>(completionHandler: Response<T, NSError> -> Void) -> Self {
        let responseSerializer = ResponseSerializer<T, NSError> { request, response, data, error in
            guard error == nil else { return .Failure(error!) }

            let JSONResponseSerializer = Request.JSONResponseSerializer(options: .AllowFragments)
            let result = JSONResponseSerializer.serializeResponse(request, response, data, error)

            switch result {
            case .Success(let value):
                if let
                    response = response,
                    responseObject = T(response: response, representation: value)
                {
                    return .Success(responseObject)
                } else {
                    let failureReason = "JSON could not be serialized into response object: \(value)"
                    let error = Error.errorWithCode(.JSONSerializationFailed, failureReason: failureReason)
                    return .Failure(error)
                }
            case .Failure(let error):
                return .Failure(error)
            }
        }

        let queue = dispatch_queue_create("my.queue", DISPATCH_QUEUE_CONCURRENT)
        return response(queue: queue, responseSerializer: responseSerializer) { response in
            dispatch_async(dispatch_get_main_queue()) {
                completionHandler(response)
            }
        }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.