সুইফট 2 এ একটি কাস্টম বার্তা সহ ত্রুটি / ব্যতিক্রম ছোঁড়ার সহজ উপায়?


136

আমি সুইফট 2-তে এমন কিছু করতে চাই যা আমি একাধিক অন্যান্য ভাষায় করতে অভ্যস্ত: একটি কাস্টম বার্তা সহ একটি রানটাইম ব্যতিক্রম নিক্ষেপ করুন। উদাহরণস্বরূপ (জাভাতে):

throw new RuntimeException("A custom message here")

আমি বুঝতে পারি যে আমি এনাম টাইপ করতে পারি যা ত্রুটি টাইপ প্রোটোকলের সাথে সামঞ্জস্যপূর্ণ তবে আমি নিক্ষেপ করি না এমন প্রতিটি ধরণের ত্রুটির জন্য এনামগুলি সংজ্ঞায়িত করতে চাই। আদর্শভাবে, আমি উপরের উদাহরণটি যথাসম্ভব ঘনিষ্ঠভাবে অনুকরণ করতে সক্ষম হতে চাই। আমি একটি কাস্টম ক্লাস তৈরি করে দেখেছি যা ত্রুটি টাইপ প্রোটোকল প্রয়োগ করে, তবে আমি বুঝতেও পারি না যে সেই প্রোটোকলের কী প্রয়োজন ( ডকুমেন্টেশন দেখুন )। ধারনা?


2
সুইফট 2 থ্রো / ক্যাচ ব্যতিক্রম নয়।
জাফ

উত্তর:


194

সবচেয়ে সহজ পদ্ধতির সম্ভবত সংজ্ঞায়িত হয় এক কাস্টম enumমাত্র এক সঙ্গে caseকরে একটি হয়েছে Stringএটি সংযুক্ত:

enum MyError: ErrorType {
    case runtimeError(String)
}

বা, সুইফট 4 হিসাবে:

enum MyError: Error {
    case runtimeError(String)
}

উদাহরণ ব্যবহারের কিছু হবে:

func someFunction() throws {
    throw MyError.runtimeError("some message")
}
do {
    try someFunction()
} catch MyError.runtimeError(let errorMessage) {
    print(errorMessage)
}

আপনি যদি বিদ্যমান Errorধরণের ব্যবহার করতে চান তবে সর্বাধিক সাধারণ একটি হবেন NSErrorএবং আপনি একটি কাস্টম বার্তা তৈরি এবং নিক্ষেপ করার জন্য একটি কারখানা পদ্ধতি তৈরি করতে পারেন।


হাই, আমি জানি আপনি এই উত্তরটি পোস্ট করেছেন এক বছর হয়ে গেছে, তবে আমি জানতে চাই যে Stringআপনার অভ্যন্তরটি পাওয়া সম্ভব errorMessageকিনা, যদি তা হয় তবে আমি কীভাবে এটি করব?
রেনান কামাফেরে

1
@ রেনানক্যামফোরে আমি দুঃখিত, আমি প্রশ্নটি বুঝতে পারি না? Stringএখানে যুক্ত করা হয় MyError.RuntimeError(সময় সেট throw), এবং আপনি এটা অ্যাক্সেস লাভ catch(সঙ্গে let errorMessage)।
আরক্কু

1
আপনাকে সহজতম সমাধানের জন্য জিজ্ঞাসা করা হয়েছিল। সমাধান আপনি কাস্টম এনাম, ফাংশন এবং ইত্যাদি তৈরি করার সময় সহজ নয়। আমি কমপক্ষে একটি উপায় জানি তবে আমি এটি সেখানে পোস্ট করব না কারণ এটি উদ্দেশ্য-সি-এর জন্য
ভাইচাসলভ গের্চিকভ

3
@ ভাইচাস্লাভ জের্চিকভ আপনি যদি সুইফটের পক্ষে প্রশ্নটির মধ্যেও নির্দিষ্ট করে দেওয়া সহজ উপায় না জানেন তবে এটি সবচেয়ে সহজ উপায়, এমনকি আপনারা এটিকে আরও সাধারণ প্রেক্ষাপটে সাধারণ হিসাবে বিবেচনা করবেন না যাতে উদ্দেশ্য-সি অন্তর্ভুক্ত থাকবে । (এছাড়াও, এই উত্তরটি মূলত এনামের এক-লাইনের এক-সময়ের সংজ্ঞা, ফাংশন এবং তার কলটি সমাধানের অংশ নয়, এটি ব্যবহারের উদাহরণ))
আরক্কু

1
@ ওটার হ্যাঁ, তবে ... আপনি এমন কথা বলছেন try!যা এখানে ব্যবহার হয় না। আপনি প্রকৃতপক্ষে কোনও প্রকারের ছাড়াও সম্ভাব্য নিক্ষেপ কল করতে পারবেন না try। (এছাড়াও
কোডটির

136

সহজ উপায় করা হয় Stringসাথে সামঞ্জস্য Error:

extension String: Error {}

তারপরে আপনি কেবল একটি স্ট্রিং নিক্ষেপ করতে পারেন:

throw "Some Error"

স্ট্রিংটিকে নিজেই localizedStringত্রুটি হিসাবে চিহ্নিত করার পরিবর্তে আপনি প্রসারিত করতে পারেন LocalizedError:

extension String: LocalizedError {
    public var errorDescription: String? { return self }
}

এটি চালাক, তবে এটির localizedDescriptionস্ট্রিংটি তৈরি করার কোনও উপায় আছে কি?
ভিলাপাসু

1
খুব মার্জিত উপায়!
ভিটালিয়া গোঝেনকো

1
সত্যিই মার্জিত! তবে পরীক্ষার লক্ষ্যবস্তুতে এটি আমার জন্য নিম্নলিখিত বার্তাগুলির সাথে ভেঙে যায় Redundant conformance of 'String' to protocol 'Error':(
আলেকজান্ডার বোরিসেনকো

2
কিছু কারণে এটি আমার পক্ষে কাজ করে না। বলে যে error.localizedDescriptionস্ট্রিং নিক্ষেপ করার পরে পার্স করার সময় এটি অপারেশনটি সম্পূর্ণ করতে পারে না ।
নোহ অ্যালেন

1
সতর্কতা: এই এক্সটেনশনটি আমার জন্য বাহ্যিক লাইব্রেরিগুলিতে সমস্যা সৃষ্টি করেছিল। এখানে আমার উদাহরণ । ত্রুটি পরিচালনা করে এমন কোনও তৃতীয় পক্ষের গ্রন্থাগারের পক্ষে এটি সম্ভব; আমি স্ট্রিংকে ত্রুটির সাথে সঙ্গতিপূর্ণ এমন এক্সটেনশনগুলি এড়াতে চাই।
ব্রায়ান ডাব্লু ওয়াগনার

20

@ নিক-কিটসের সমাধানটি সবচেয়ে মার্জিত, তবে নিম্নলিখিত সংকলনের সময় ত্রুটির সাথে পরীক্ষার টার্গেটে এটি আমার জন্য ভেঙে যায়:

Redundant conformance of 'String' to protocol 'Error'

এখানে অন্য পদ্ধতির:

struct RuntimeError: Error {
    let message: String

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

    public var localizedDescription: String {
        return message
    }
}

এবং ব্যবহার করতে:

throw RuntimeError("Error message.")

19

এই দুর্দান্ত সংস্করণটি দেখুন। ধারণাটি হ'ল স্ট্রিং এবং ত্রুটি টাইপ প্রোটোকল উভয়ই প্রয়োগ করা এবং ত্রুটির কাঁচা মূল্য ব্যবহার করা।

enum UserValidationError: String, Error {
  case noFirstNameProvided = "Please insert your first name."
  case noLastNameProvided = "Please insert your last name."
  case noAgeProvided = "Please insert your age."
  case noEmailProvided = "Please insert your email."
}

ব্যবহার:

do {
  try User.define(firstName,
                  lastName: lastName,
                  age: age,
                  email: email,
                  gender: gender,
                  location: location,
                  phone: phone)
}
catch let error as User.UserValidationError {
  print(error.rawValue)
  return
}

এই পদ্ধতির সামান্য উপকার বলে মনে হচ্ছে, যেহেতু আপনার এখনও প্রয়োজন as User.UserValidationErrorএবং এর উপরেও .rawValue। তবে আপনি যদি পরিবর্তে এটি প্রয়োগ CustomStringConvertibleকরেন var description: String { return rawValue }তবে এনাম সিনট্যাক্স ব্যবহার করে কাস্টম বিবরণগুলি ব্যবহার করা কার্যকর হতে পারে rawValueআপনি যেখানেই মুদ্রণ করবেন না সেখানে through
আরক্কু


16

সুইফট 4:

যেমনটি:

https://developer.apple.com/documentation/foundation/nserror

আপনি যদি কোনও কাস্টম ব্যতিক্রম সংজ্ঞায়িত করতে না চান, আপনি নীচের মতো একটি স্ট্যান্ডার্ড এনএসইরর অবজেক্টটি ব্যবহার করতে পারেন:

import Foundation

do {
  throw NSError(domain: "my error description", code: 42, userInfo: ["ui1":12, "ui2":"val2"] ) 
}
catch let error as NSError {
  print("Caught NSError: \(error.localizedDescription), \(error.domain), \(error.code)")
  let uis = error.userInfo 
  print("\tUser info:")
  for (key,value) in uis {
    print("\t\tkey=\(key), value=\(value)")
  }
}

ছাপে:

Caught NSError: The operation could not be completed, my error description, 42
    User info:
        key=ui1, value=12
        key=ui2, value=val2

এটি আপনাকে একটি কাস্টম স্ট্রিং, প্লাস্টিকের একটি সংখ্যাসূচক কোড এবং যে কোনও ধরণের আপনার প্রয়োজনীয় অতিরিক্ত ডেটা সহ একটি অভিধান সরবরাহ করতে দেয়।

এনবি: এটি ওএস = লিনাক্সে (উবুন্টু 16.04 এলটিএস) পরীক্ষিত হয়েছিল।


12

অতিরিক্ত এক্সটেনশন, এনম, ক্লাস এবং ইত্যাদি ছাড়াই সহজ সমাধান .:

NSException(name:NSExceptionName(rawValue: "name"), reason:"reason", userInfo:nil).raise()

2
পুনরায়। আমার জবাব সম্পর্কে আপনার মন্তব্য, এটি কেবলমাত্র সেই অর্থে সহজ যে আপনি কিছুটা নির্বিচারে সিদ্ধান্ত নিয়েছেন যে একবার সংজ্ঞা দেওয়া এবং এনাম বা এক্সটেনশন একবার জটিল। সুতরাং, হ্যাঁ, আপনার উত্তরটিতে "সেটআপ" এর শূন্য লাইন রয়েছে, তবে প্রতিটি ছোঁড়া ব্যতিক্রম একটি ব্যয় একটি জটিল এবং অ-সুইফটলকের ( raise()পরিবর্তে throw) বানান হতে পারে যা মনে রাখা শক্ত। আপনার সমাধানটি তুলনামূলকভাবে যেখানে ব্যতিক্রম ছুঁড়েছে তার সংখ্যার সাথে throw Foo.Bar("baz")বা তার সাথে তুলনা করুন throw "foo"- আইএমও ওয়ান-লাইন এক্সটেনশন বা এনামের এককালীন ফি পছন্দসই জিনিসগুলির চেয়ে অনেক বেশি পছন্দনীয় NSExceptionName
আরক্কু

@ আরক্কু উদাহরণস্বরূপ postNotification২-৩ টি প্যারাম প্রয়োজন এবং এর নির্বাচকও এটির মতো। আপনি কি কম প্রকল্পের প্যারামগুলি গ্রহণ করার জন্য প্রতিটি প্রকল্পে ওভাররাইড Notificationএবং / অথবা NotificationCenterকরছেন?
ব্যচাস্লাভ গের্চিকভ

1
না, এবং আমি নিজের উত্তরটিতে সমাধানটিও ব্যবহার করব না; আমি কেবল এই প্রশ্নের উত্তর দেওয়ার জন্য পোস্ট করেছি, কারণ এটি আমি নিজেই করব would যাইহোক, এটি এই বিষয়টির বাইরেও : আমি এই মতামত দিয়ে দাঁড়িয়েছি যে আপনার উত্তরটি আমার বা নিক কেটসের চেয়ে যে কোনওরকম বেশি জটিল use অবশ্যই অন্যান্য বৈধ পয়েন্টগুলি বিবেচনা করতে হবে যেমন Stringমেনে চলা প্রসারিত Errorহওয়া খুব অবাক হওয়ার মতো বিষয়, বা যদি MyErrorএনাম খুব অস্পষ্ট হয় (ব্যক্তিগতভাবে আমি উভয়কেই হ্যাঁ উত্তর দেব, এবং পরিবর্তে প্রতিটি ত্রুটির জন্য পৃথক এনাম কেস করব, অর্থাৎ, throw ThisTypeOfError.thisParticularCase)।
আরক্কু

6

@ নিক কীটসের উত্তরের উপর ভিত্তি করে, এখানে আরও একটি সম্পূর্ণ উদাহরণ দেওয়া হয়েছে:

extension String: Error {} // Enables you to throw a string

extension String: LocalizedError { // Adds error.localizedDescription to Error instances
    public var errorDescription: String? { return self }
}

func test(color: NSColor) throws{
    if color == .red {
        throw "I don't like red"
    }else if color == .green {
        throw "I'm not into green"
    }else {
        throw "I like all other colors"
    }
}

do {
    try test(color: .green)
} catch let error where error.localizedDescription == "I don't like red"{
    Swift.print ("Error: \(error)") // "I don't like red"
}catch let error {
    Swift.print ("Other cases: Error: \(error.localizedDescription)") // I like all other colors
}

মূলত আমার সুইফ্ট ব্লগে প্রকাশিত: http://eon.codes/blog/2017/09/01/throwing-simple-erferences/


1
Tbh: আমি এখন শুধু নাthrow NSError(message: "err", code: 0)
eonist

সুতরাং আপনি এমনকি আপনার নিজের উদাহরণ ব্যবহার করবেন না? : ডি ওহ, এবং প্রথম যুক্তিটি হওয়া উচিত domain, তাই না message?
এনআরিত

1
আপনার অধিকার, ডোমেন। এবং না, কোডটিতে খুব বেশি চিনি যুক্ত করুন। আমি সাধারণত প্রচুর পরিমাণে ছোট ফ্রেমওয়ার্ক এবং মডিউল তৈরি করি এবং সুবিধাজনক এক্সটেনশান চিনির কম রাখার চেষ্টা করি। আজকাল আমি রেজাল্ট এবং এনএসইররারের মধ্যে একটি মিশ্রণটি ব্যবহার করার চেষ্টা করছি
এপনিস্ট e

6

যদি আপনার ত্রুটিটি ধরার দরকার না হয় এবং আপনি তাত্ক্ষণিকভাবে অ্যাপ্লিকেশনটি বন্ধ করতে চান তবে আপনি একটি মারাত্মক সমস্যা ব্যবহার করতে পারেন: fatalError ("Custom message here")


3
নোট করুন যে এটি কোনও ত্রুটি ফেলবে না যা ধরা পড়ে। এটি অ্যাপটিকে ক্রাশ করবে।
আদিল হুসেন

4

আমি @ আলেকজান্ডার-বোরিসেনকোর উত্তরটি পছন্দ করি তবে ত্রুটি হিসাবে ধরা পড়লে স্থানীয় বর্ণিত বিবরণটি ফিরিয়ে দেওয়া হয়নি। এর পরিবর্তে আপনার কাছে লোকালাইজড এরির ব্যবহার করা দরকার বলে মনে হচ্ছে:

struct RuntimeError: LocalizedError
{
    let message: String

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

    public var errorDescription: String?
    {
        return message
    }
}

আরও তথ্যের জন্য এই উত্তর দেখুন ।

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