সুইফটে ত্রুটির ধরণের সাথে স্থানীয়করণের বিবরণটি কীভাবে সরবরাহ করবেন?


202

আমি সুইফট 3 সিনট্যাক্সের সাথে একটি কাস্টম ত্রুটির ধরণটি সংজ্ঞায়িত করছি এবং আমি ত্রুটির একটি ব্যবহারকারী-বান্ধব বিবরণ দিতে চাই যা বস্তুর localizedDescriptionসম্পত্তি দ্বারা ফিরে আসে Error। আমি এটা কিভাবে করবো?

public enum MyError: Error {
  case customError

  var localizedDescription: String {
    switch self {
    case .customError:
      return NSLocalizedString("A user-friendly description of the error.", comment: "My error")
    }
  }
}

let error: Error = MyError.customError
error.localizedDescription
// "The operation couldn’t be completed. (MyError error 0.)"

localizedDescriptionআমার কাস্টম ত্রুটি বর্ণনা ("ত্রুটির ব্যবহারকারী-বান্ধব বিবরণ") ফিরিয়ে দেওয়ার জন্য কি কোনও উপায় আছে ? মনে রাখবেন যে এখানে ত্রুটিযুক্ত বস্তুটি টাইপযুক্ত Errorএবং না MyError। আমি অবশ্যই বস্তুটি MyError এ কাস্ট করতে পারি

(error as? MyError)?.localizedDescription

তবে আমার ত্রুটির ধরণ ছাড়াই এটিকে কাজ করার কোনও উপায় আছে?

উত্তর:


401

এক্সকোড 8 বিটা 6 রিলিজ নোটগুলিতে বর্ণিত হিসাবে,

সুইফ্ট-সংজ্ঞায়িত ত্রুটি প্রকারগুলি নতুন লোকালাইজড ইরর প্রোটোকল গ্রহণ করে স্থানীয় ত্রুটি বিবরণ সরবরাহ করতে পারে।

তোমার ক্ষেত্রে:

public enum MyError: Error {
    case customError
}

extension MyError: LocalizedError {
    public var errorDescription: String? {
        switch self {
        case .customError:
            return NSLocalizedString("A user-friendly description of the error.", comment: "My error")
        }
    }
}

let error: Error = MyError.customError
print(error.localizedDescription) // A user-friendly description of the error.

ত্রুটিটি রূপান্তরিত হলে আপনি আরও বেশি তথ্য সরবরাহ করতে পারেন NSError(যা সর্বদা সম্ভব):

extension MyError : LocalizedError {
    public var errorDescription: String? {
        switch self {
        case .customError:
            return NSLocalizedString("I failed.", comment: "")
        }
    }
    public var failureReason: String? {
        switch self {
        case .customError:
            return NSLocalizedString("I don't know why.", comment: "")
        }
    }
    public var recoverySuggestion: String? {
        switch self {
        case .customError:
            return NSLocalizedString("Switch it off and on again.", comment: "")
        }
    }
}

let error = MyError.customError as NSError
print(error.localizedDescription)        // I failed.
print(error.localizedFailureReason)      // Optional("I don\'t know why.")
print(error.localizedRecoverySuggestion) // Optional("Switch it off and on again.")

CustomNSErrorপ্রোটোকল গ্রহণ করে ত্রুটি একটি userInfoঅভিধান সরবরাহ করতে পারে (এবং এছাড়াও একটি domainএবং code)। উদাহরণ:

extension MyError: CustomNSError {

    public static var errorDomain: String {
        return "myDomain"
    }

    public var errorCode: Int {
        switch self {
        case .customError:
            return 999
        }
    }

    public var errorUserInfo: [String : Any] {
        switch self {
        case .customError:
            return [ "line": 13]
        }
    }
}

let error = MyError.customError as NSError

if let line = error.userInfo["line"] as? Int {
    print("Error in line", line) // Error in line 13
}

print(error.code) // 999
print(error.domain) // myDomain

7
আপনি প্রথমে তৈরি করার পরে এটির পরে প্রসারিত করার MyErrorকোনও কারণ আছে কি ? যদি আপনি এটি প্রথম স্থানে তৈরি করেন তবে কোনও পার্থক্য আছে ? ErrorLocalizedErrorLocalizedError
Gee.E

9
@ জি.আই.ই: এতে কোনও তফাত হয় না। কোডটি সাজানোর একমাত্র উপায় (প্রতিটি প্রোটোকলের জন্য একটি এক্সটেনশন)। তুলনা করুন stackoverflow.com/questions/36263892/... , stackoverflow.com/questions/40502086/... , অথবা natashatherobot.com/using-swift-extensions
মার্টিন আর

4
আহ, চেক। আপনি এখন যা বলছেন তা আমি পেয়েছি। নাতাশাতেরোবোট . com/ ব্যবহার- সুইফট-এক্সটেনশানগুলির "প্রোটোকল কনফরমেন্স" বিভাগটি আসলে আপনি কী বোঝাতে চেয়েছেন তা একটি দুর্দান্ত উদাহরণ। ধন্যবাদ!
জিই.ই

1
@ মার্টিনআর যদি আমার ত্রুটিটি এনএসইরআরে রূপান্তরিত হয় তবে কীভাবে আমি ত্রুটি থেকে এমন একটি অভিধান পাস করতে পারি যা এনএসইররর ব্যবহারকারী হিসাবে ব্যবহার করা যেতে পারে?
BangOperator

18
var errorDescription: String?পরিবর্তে টাইপ করতে সাবধান String। লোকালাইজড ইরর বাস্তবায়নের ক্ষেত্রে একটি ত্রুটি রয়েছে। দেখুন এসআর-5858
ইথানহুং 13

35

আমিও যুক্ত করব, যদি আপনার ত্রুটির মতো প্যারামিটার থাকে

enum NetworkError: LocalizedError {
  case responseStatusError(status: Int, message: String)
}

আপনি আপনার স্থানীয় বর্ণনায় এই পরামিতিগুলিকে কল করতে পারেন:

extension NetworkError {
  public var errorDescription: String? {
    switch self {
    case .responseStatusError(status: let status, message: let message):
      return "Error with status \(status) and message \(message) was thrown"
  }
}

আপনি এইটিকে আরও ছোট করে তুলতে পারেন:

extension NetworkError {
  public var errorDescription: String? {
    switch self {
    case let .responseStatusError(status, message):
      return "Error with status \(status) and message \(message) was thrown"
  }
}

4

উদ্দেশ্য-সি - লোকালাইজড এরির এবং কাস্টমএনএসররকে অতিরিক্ত তথ্য সরবরাহ করার জন্য এখন দুটি ত্রুটি-গ্রহণ প্রোটোকল রয়েছে যা আপনার ত্রুটি প্রকারটি গ্রহণ করতে পারে। এখানে একটি উদাহরণ ত্রুটি যা উভয়কেই গ্রহণ করে:

enum MyBetterError : CustomNSError, LocalizedError {
    case oops

    // domain
    static var errorDomain : String { return "MyDomain" }
    // code
    var errorCode : Int { return -666 }
    // userInfo
    var errorUserInfo: [String : Any] { return ["Hey":"Ho"] };

    // localizedDescription
    var errorDescription: String? { return "This sucks" }
    // localizedFailureReason
    var failureReason: String? { return "Because it sucks" }
    // localizedRecoverySuggestion
    var recoverySuggestion: String? { return "Give up" }

}

2
আপনি একটি সম্পাদনা করতে পারেন? আপনার উদাহরণগুলি প্রতিটিটির মান বুঝতে খুব বেশি সহায়তা করে না। অথবা শুধু এটি মুছে কারণ MartinR এর উত্তর এই ঠিক উপলব্ধ করা হয় ...
মধু

3

কাঠামো ব্যবহার করা বিকল্প হতে পারে। স্থির স্থানীয়করণ সহ কিছুটা কমনীয়তা:

import Foundation

struct MyError: LocalizedError, Equatable {

   private var description: String!

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

   var errorDescription: String? {
       return description
   }

   public static func ==(lhs: MyError, rhs: MyError) -> Bool {
       return lhs.description == rhs.description
   }
}

extension MyError {

   static let noConnection = MyError(description: NSLocalizedString("No internet connection",comment: ""))
   static let requestFailed = MyError(description: NSLocalizedString("Request failed",comment: ""))
}

func throwNoConnectionError() throws {
   throw MyError.noConnection
}

do {
   try throwNoConnectionError()
}
catch let myError as MyError {
   switch myError {
   case .noConnection:
       print("noConnection: \(myError.localizedDescription)")
   case .requestFailed:
       print("requestFailed: \(myError.localizedDescription)")
   default:
      print("default: \(myError.localizedDescription)")
   }
}

0

এখানে আরও মার্জিত সমাধান:

  enum ApiError: String, LocalizedError {

    case invalidCredentials = "Invalid credentials"
    case noConnection = "No connection"

    var localizedDescription: String { return NSLocalizedString(self.rawValue, comment: "") }

  }

4
রানটাইমে এটি আরও মার্জিত হতে পারে, তবে স্থির স্থানীয়করণের পদক্ষেপটি অনুবাদকদের জন্য এই স্ট্রিংগুলি বের করতে ব্যর্থ হবে; আপনি "Bad entry in file – Argument is not a literal string"যখন চালাবেন তখন exportLocalizationsবা genstringsআপনার অনুবাদযোগ্য পাঠ্যের তালিকা তৈরি করতে আপনি একটি ত্রুটি দেখতে পাবেন ।
savinola

@ সাভিণোলা একমত, স্থির স্থানীয়করণ এ জাতীয় ক্ষেত্রে কার্যকর হবে না। সম্ভবত ব্যবহার switch + caseকরা একমাত্র বিকল্প ...
ভিটালিয়ি গোঝেনকো

কাঁচা মানগুলি ব্যবহার করা আপনার যে কোনও ত্রুটির সাথে সম্পর্কিত মানগুলির ব্যবহারকেও প্রতিরোধ করবে
ব্রডি রবার্টসন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.