स्विफ्ट 3 में अपना त्रुटि कोड उत्पन्न करें


91

मैं जो प्राप्त करने की कोशिश कर रहा हूं वह URLSessionतेजी से एक अनुरोध कर रहा है। 3. मैं एक अलग फ़ंक्शन में यह क्रिया कर रहा हूं (ताकि जीईटी और पीओएसटी के लिए अलग से कोड न लिखूं) और वापस लौटने URLSessionDataTaskऔर बंद होने में सफलता और विफलता को संभालना। इस तरह क्रमबद्ध करें-

let task = URLSession.shared.dataTask(with: request) { (data, uRLResponse, responseError) in

     DispatchQueue.main.async {

          var httpResponse = uRLResponse as! HTTPURLResponse

          if responseError != nil && httpResponse.statusCode == 200{

               successHandler(data!)

          }else{

               if(responseError == nil){
                     //Trying to achieve something like below 2 lines
                     //Following line throws an error soo its not possible
                     //var errorTemp = Error(domain:"", code:httpResponse.statusCode, userInfo:nil)

                     //failureHandler(errorTemp)

               }else{

                     failureHandler(responseError!)
               }
          }
     }
}

मैं इस फ़ंक्शन में त्रुटि स्थिति को संभालना नहीं चाहता हूं और प्रतिक्रिया कोड का उपयोग करके एक त्रुटि उत्पन्न करना चाहता हूं और इस फ़ंक्शन को जहां से कॉल किया जाता है, उसे संभालने के लिए इस त्रुटि को वापस लौटाएं। क्या कोई मुझे बता सकता है कि इस बारे में कैसे जाना है? या इस तरह की स्थितियों से निपटने के लिए "स्विफ्ट" रास्ता नहीं है?


घोषणा के NSErrorस्थान पर उपयोग करने का प्रयास करें Error( var errorTemp = NSError(...))
लुका

यह समस्या हल करता है, लेकिन मुझे लगा कि स्विफ्ट 3 एनएस का उपयोग करने की इच्छा नहीं रखता है?
रिख

यह आईओएस विकास में करता है। शुद्ध स्विफ्ट विकास के लिए आपको Errorप्रोटोकॉल के अनुरूप अपनी त्रुटि का उदाहरण तैयार करना चाहिए
Luca D'Alberti

@ LucaD'Alberti खैर आपके समाधान ने समस्या को हल किया, इसे एक उत्तर के रूप में जोड़ने के लिए स्वतंत्र महसूस करें ताकि मैं इसे स्वीकार कर सकूं!
रिख

जवाबों:


74

आप LocalizedErrorइन मूल्यों के साथ स्विफ्ट प्रोटोकॉल के अनुरूप एक प्रोटोकॉल बना सकते हैं :

protocol OurErrorProtocol: LocalizedError {

    var title: String? { get }
    var code: Int { get }
}

यह तब हमें इस तरह की ठोस त्रुटियाँ पैदा करने में सक्षम बनाता है:

struct CustomError: OurErrorProtocol {

    var title: String?
    var code: Int
    var errorDescription: String? { return _description }
    var failureReason: String? { return _description }

    private var _description: String

    init(title: String?, description: String, code: Int) {
        self.title = title ?? "Error"
        self._description = description
        self.code = code
    }
}

3
a) OurErrorProtocol को बनाना आवश्यक नहीं है, बस CustomError को Error को सीधे कार्यान्वित करना है। ख) यह काम नहीं करता है (कम से कम स्विफ्ट 3 में: स्थानीयकृत डिस्क्रिप्शन को कभी नहीं बुलाया जाता है और आपको "ऑपरेशन पूरा नहीं हो सकता है")। आपको इसके बजाय LocalizedError को लागू करने की आवश्यकता है; मेरा जवाब देखिए।
Prewett

@prewett मैंने अभी देखा लेकिन आप सही हैं! स्थानीयकृत त्रुटि में एररडिस्क्रिप्शन फ़ील्ड को कार्यान्वित करना वास्तव में ऊपर बताए अनुसार मेरी विधि का उपयोग करने के बजाय संदेश सेट करता है। मैं अभी भी "OurErrorProtocol" रैपर रख रहा हूं, क्योंकि मुझे स्थानीयकृत फ़ील्ड की आवश्यकता है। यह बात बताने के लिए धन्यवाद!
हैरी ब्लूम

107

आपके मामले में, त्रुटि यह है कि आप एक Errorउदाहरण उत्पन्न करने का प्रयास कर रहे हैं । Errorस्विफ्ट 3 में एक प्रोटोकॉल है जिसका उपयोग कस्टम त्रुटि को परिभाषित करने के लिए किया जा सकता है। यह विशेषता विशेष रूप से शुद्ध स्विफ्ट अनुप्रयोगों के लिए विभिन्न ओएस पर चलने के लिए है।

आईओएस विकास में NSErrorवर्ग अभी भी उपलब्ध है और यह Errorप्रोटोकॉल के अनुरूप है ।

इसलिए, यदि आपका उद्देश्य केवल इस त्रुटि कोड का प्रचार करना है, तो आप आसानी से बदल सकते हैं

var errorTemp = Error(domain:"", code:httpResponse.statusCode, userInfo:nil)

साथ में

var errorTemp = NSError(domain:"", code:httpResponse.statusCode, userInfo:nil)

अन्यथा कस्टम त्रुटि प्रकार बनाने के बारे में संदीप भंडारी के उत्तर की जाँच करें


15
मैं सिर्फ त्रुटि मिलती है: Error cannot be created because it has no accessible initializers
सुपरटेकनोफॉफ़

@AbhishekThapliyal क्या आप कृपया अपनी टिप्पणी को थोड़ा और विस्तृत कर सकते हैं? मैं समझ नहीं पा रहा हूं कि आपका क्या मतलब है।
लुका डी'अल्बर्टी

2
@ LucaD'Alberti Swift 4 में इसकी त्रुटि दिखाते हुए बनाया नहीं जा सकता, क्योंकि इसमें एरर ऑब्जेक्ट को बनाते समय कोई एक्सेसिबल इनिशियलाइज़र नहीं है।
महीप

1
@ मेरे जवाब में जो मैं सुझा रहा हूं, उसका उपयोग नहीं करना है Error, लेकिन NSError। बेशक Errorएक त्रुटि का उपयोग कर ।
लुका

त्रुटि प्रोटोकॉल है। कैंट को तुरंत चालू किया जाए।
स्लोबोडन

52

आप त्रुटियों से निपटने के लिए एनम बना सकते हैं :)

enum RikhError: Error {
    case unknownError
    case connectionError
    case invalidCredentials
    case invalidRequest
    case notFound
    case invalidResponse
    case serverError
    case serverUnavailable
    case timeOut
    case unsuppotedURL
 }

और फिर http प्रतिक्रिया कोड प्राप्त करने के लिए enum के अंदर एक विधि बनाएं और बदले में संबंधित त्रुटि वापस करें :)

static func checkErrorCode(_ errorCode: Int) -> RikhError {
        switch errorCode {
        case 400:
            return .invalidRequest
        case 401:
            return .invalidCredentials
        case 404:
            return .notFound
        //bla bla bla
        default:
            return .unknownError
        }
    }

अंत में RikhError के एकल पैरामीटर को स्वीकार करने के लिए अपनी विफलता ब्लॉक को अपडेट करें :)

मेरे पास पारंपरिक उद्देश्य के पुनर्गठन के बारे में एक विस्तृत ट्यूटोरियल है - सी आधारित ऑब्जेक्ट ओरिएंटेड नेटवर्क मॉडल टू मॉडर्न प्रोटोकॉल ओरिएंटेड मॉडल Swift3 का उपयोग करके यहां https://learnwithmehere.blogspot.in पर एक नज़र डालें :)

आशा है कि इससे सहायता मिलेगी :)


आह, लेकिन यह मुझे मैन्युअल रूप से सभी मामलों को संभालने के लिए नहीं होगा? वह त्रुटि कोड है?
रिख

हाँ, आपको यह करना होगा: D लेकिन एक ही समय में आप प्रत्येक त्रुटि स्थिति के लिए विशिष्ट विभिन्न कार्य कर सकते हैं :) अब आपके पास त्रुटि मॉडल पर एक अच्छा नियंत्रण है यदि आप ऐसा नहीं करना चाहते हैं तो आप केस 400 ... 404 का उपयोग कर सकते हैं {...} केवल सामान्य मामलों को संभालें :)
संदीप भंडारी

आह हाँ! धन्यवाद
Rikh

कई http कोडों को मानने की जरूरत नहीं है कि एक ही मामले में आपको केवल RumError करने में सक्षम होना चाहिए: Int, Error {case अमान्यRequest = 400} और फिर इसे RikhError (rawValue, httpCode) बनाने के लिए
ब्रायन एफ लेइटी

51

आपको NSError ऑब्जेक्ट का उपयोग करना चाहिए।

let error = NSError(domain:"", code:401, userInfo:[ NSLocalizedDescriptionKey: "Invalid access token"])

फिर NSError को Error ऑब्जेक्ट में डाले


29

विवरण

  • Xcode संस्करण 10.2.1 (10E1001)
  • स्विफ्ट 5

एक ऐप में त्रुटियों को व्यवस्थित करने का समाधान

import Foundation

enum AppError {
    case network(type: Enums.NetworkError)
    case file(type: Enums.FileError)
    case custom(errorDescription: String?)

    class Enums { }
}

extension AppError: LocalizedError {
    var errorDescription: String? {
        switch self {
            case .network(let type): return type.localizedDescription
            case .file(let type): return type.localizedDescription
            case .custom(let errorDescription): return errorDescription
        }
    }
}

// MARK: - Network Errors

extension AppError.Enums {
    enum NetworkError {
        case parsing
        case notFound
        case custom(errorCode: Int?, errorDescription: String?)
    }
}

extension AppError.Enums.NetworkError: LocalizedError {
    var errorDescription: String? {
        switch self {
            case .parsing: return "Parsing error"
            case .notFound: return "URL Not Found"
            case .custom(_, let errorDescription): return errorDescription
        }
    }

    var errorCode: Int? {
        switch self {
            case .parsing: return nil
            case .notFound: return 404
            case .custom(let errorCode, _): return errorCode
        }
    }
}

// MARK: - FIle Errors

extension AppError.Enums {
    enum FileError {
        case read(path: String)
        case write(path: String, value: Any)
        case custom(errorDescription: String?)
    }
}

extension AppError.Enums.FileError: LocalizedError {
    var errorDescription: String? {
        switch self {
            case .read(let path): return "Could not read file from \"\(path)\""
            case .write(let path, let value): return "Could not write value \"\(value)\" file from \"\(path)\""
            case .custom(let errorDescription): return errorDescription
        }
    }
}

प्रयोग

//let err: Error = NSError(domain:"", code: 401, userInfo: [NSLocalizedDescriptionKey: "Invaild UserName or Password"])
let err: Error = AppError.network(type: .custom(errorCode: 400, errorDescription: "Bad request"))

switch err {
    case is AppError:
        switch err as! AppError {
        case .network(let type): print("Network ERROR: code \(type.errorCode), description: \(type.localizedDescription)")
        case .file(let type):
            switch type {
                case .read: print("FILE Reading ERROR")
                case .write: print("FILE Writing ERROR")
                case .custom: print("FILE ERROR")
            }
        case .custom: print("Custom ERROR")
    }
    default: print(err)
}

16

स्थानीयकृत लागू करें:

struct StringError : LocalizedError
{
    var errorDescription: String? { return mMsg }
    var failureReason: String? { return mMsg }
    var recoverySuggestion: String? { return "" }
    var helpAnchor: String? { return "" }

    private var mMsg : String

    init(_ description: String)
    {
        mMsg = description
    }
}

ध्यान दें कि उदाहरण के लिए, त्रुटि को लागू करने के लिए, जैसा कि किसी एक उत्तर में वर्णित है, विफल हो जाएगा (कम से कम स्विफ्ट 3 में), और स्थानीयकरण कॉल करने से परिणाम स्ट्रिंग में हो जाएगा "ऑपरेशन पूरा नहीं किया जा सका। (.StringError त्रुटि 1. "


चाहिए कि mMsg = msg
Brett

1
उफ़, सही है। मैंने "संदेश" को "विवरण" में बदल दिया, जो उम्मीद है कि मेरे मूल से थोड़ा स्पष्ट है।
प्रीवेट

4
आप इसे कम कर सकते हैं struct StringError : LocalizedError { public let errorDescription: String? }, और बस के रूप में उपयोग करेंStringError(errorDescription: "some message")
Koen।

7
 let error = NSError(domain:"", code:401, userInfo:[ NSLocalizedDescriptionKey: "Invaild UserName or Password"]) as Error
            self.showLoginError(error)

एक NSError ऑब्जेक्ट बनाएं और उसे एरर में टाइप करें, इसे कहीं भी दिखाएं

private func showLoginError(_ error: Error?) {
    if let errorObj = error {
        UIAlertController.alert("Login Error", message: errorObj.localizedDescription).action("OK").presentOn(self)
    }
}

6

मुझे अब भी लगता है कि हैरी का उत्तर सबसे सरल और पूर्ण है लेकिन अगर आपको कुछ सरल भी चाहिए, तो उपयोग करें:

struct AppError {
    let message: String

    init(message: String) {
        self.message = message
    }
}

extension AppError: LocalizedError {
    var errorDescription: String? { return message }
//    var failureReason: String? { get }
//    var recoverySuggestion: String? { get }
//    var helpAnchor: String? { get }
}

और इसका उपयोग या परीक्षण इस तरह से करें:

printError(error: AppError(message: "My App Error!!!"))

func print(error: Error) {
    print("We have an ERROR: ", error.localizedDescription)
}

3
protocol CustomError : Error {

    var localizedTitle: String
    var localizedDescription: String

}

enum RequestError : Int, CustomError {

    case badRequest         = 400
    case loginFailed        = 401
    case userDisabled       = 403
    case notFound           = 404
    case methodNotAllowed   = 405
    case serverError        = 500
    case noConnection       = -1009
    case timeOutError       = -1001

}

func anything(errorCode: Int) -> CustomError? {

      return RequestError(rawValue: errorCode)
}

1

मुझे पता है कि आप पहले से ही एक जवाब से संतुष्ट हैं, लेकिन अगर आप सही दृष्टिकोण जानना चाहते हैं, तो यह आपके लिए मददगार हो सकता है। मैं त्रुटि ऑब्जेक्ट में त्रुटि कोड के साथ http-response एरर कोड को मिक्स नहीं करना पसंद करूंगा (भ्रमित? कृपया थोड़ा सा पढ़ना जारी रखें ...)।

Http प्रतिक्रिया कोड सामान्य त्रुटि कोड के बारे में मानक त्रुटि कोड हैं, जब प्रतिक्रिया प्राप्त होती है और सामान्य स्थिति को परिभाषित करता है 1xx से 5xx तक (जैसे 200 ओके, 408 अनुरोध टाइम आउट, 504 गेटवे टाइमआउट आदि - http://www.restapitutorial.com/) httpstatuscodes.html )

NSError ऑब्जेक्ट में त्रुटि कोड, एप्लिकेशन / उत्पाद / सॉफ़्टवेयर के किसी विशेष डोमेन के लिए ऑब्जेक्ट का वर्णन करने वाली त्रुटि के लिए बहुत विशिष्ट पहचान प्रदान करता है। उदाहरण के लिए आपका एप्लिकेशन "सॉरी के लिए 1000 का उपयोग कर सकता है, आप इस रिकॉर्ड को एक दिन में एक से अधिक बार अपडेट नहीं कर सकते हैं" या "आपको इस संसाधन तक पहुंचने के लिए प्रबंधक भूमिका की आवश्यकता है" के लिए 1001 कहें ... जो आपके डोमेन / एप्लिकेशन के लिए विशिष्ट हैं तर्क।

एक बहुत छोटे अनुप्रयोग के लिए, कभी-कभी इन दो अवधारणाओं को मिला दिया जाता है। लेकिन वे पूरी तरह से अलग हैं जैसा कि आप देख सकते हैं और बड़े सॉफ्टवेयर के साथ डिजाइन और काम करने के लिए बहुत महत्वपूर्ण और सहायक हैं।

तो, बेहतर तरीके से कोड को संभालने के लिए दो तकनीकें हो सकती हैं:

1. पूरा कॉलबैक सभी चेक का प्रदर्शन करेगा

completionHandler(data, httpResponse, responseError) 

2. आपका तरीका सफलता और त्रुटि की स्थिति तय करता है और फिर संबंधित कॉलबैक को आमंत्रित करता है

if nil == responseError { 
   successCallback(data)
} else {
   failureCallback(data, responseError) // failure can have data also for standard REST request/response APIs
}

मुबारक कोडिंग :)


तो मूल रूप से आप जो कहने की कोशिश कर रहे हैं वह "डेटा" पैरामीटर पास है यदि सर्वर से वापस आने के दौरान विशिष्ट त्रुटि कोड के मामले में कुछ विशिष्ट स्ट्रिंग प्रदर्शित किया जाना है? (क्षमा करें, मैं कई बार थोड़ा धीमा हो सकता हूं!)
ऋख
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.