সুইফট-ল্যাঙ্গুয়েজে ত্রুটি-পরিচালনা


190

আমি সুইফটে খুব বেশি পড়িনি তবে একটি জিনিস আমি লক্ষ্য করেছি যে এর ব্যতিক্রম নেই। তাহলে তারা কীভাবে সুইফটে পরিচালনা করতে ত্রুটি করবেন? ত্রুটি-পরিচালনা সম্পর্কিত কেউ কি কিছু পেয়েছেন?


1
আমি
ওবজ

13
@ আরবিটুর ভাল পুরানো সেগফল্ট উপায়?
পেকো

সুইফটে একটি এনএসটিমার তৈরি করেছিলাম এবং যখন আমি ফাংশনটি ভুল করে ফেলেছিলাম তখন এটি ক্র্যাশ হয়ে গিয়েছিল এবং আমাকে ত্রুটি দিয়েছিল যে এটি পদ্ধতিটি খুঁজে পাবে না :)
আরবিটুর

3
আপনি এই নিবন্ধের নির্দেশাবলী অনুসরণ করে সুইফট-এর জন্য ট্রাই-ক্যাচ সমর্থন যুক্ত করতে পারেন: मध्यम.com
উইলিয়াম ফ্যালকন

@ পেকো আপনি কীভাবে সুইফটে একটি সেগফোল্ট পরিচালনা করবেন? আমি এখনই এটি সম্ভব বলে মনে করি না, যা দুঃখের সাথে কিছু ত্রুটি অপরিবর্তনযোগ্য করে তোলে
অরলিন জর্জিভ

উত্তর:


148

সুইফট 2 এবং 3

সুইফট ২-এ নতুন কিছু ত্রুটি-হ্যান্ডলিং ব্যবস্থা রয়েছে বলে কিছু পরিবর্তন হয়েছে, এটি ব্যতিক্রমগুলির সাথে কিছুটা বেশি মিলছে তবে বিস্তারিতভাবে ভিন্ন।

1. ত্রুটি সম্ভাবনা ইঙ্গিত

যদি ফাংশন / পদ্ধতিটি এটি একটি ত্রুটি ছুঁড়ে দিতে পারে তা নির্দেশ করতে চায় তবে এতে throwsকীওয়ার্ড থাকা উচিত

func summonDefaultDragon() throws -> Dragon

দ্রষ্টব্য: ফাংশনটি আসলে ফেলে দিতে পারে এমন ধরণের ত্রুটির কোনও নির্দিষ্টকরণ নেই। এই ঘোষণাটি সহজভাবে জানিয়েছে যে ফাংশনটি কোনও ধরণের ত্রুটি টাইপ প্রয়োগের উদাহরণ ফেলতে পারে বা একেবারেই নিক্ষেপ করছে না।

2. ত্রুটি নিক্ষেপ করতে পারে যে ফাংশন চালানো

ক্রিয়াকলাপটি চালনার জন্য আপনার এই জাতীয় চেষ্টা করে চেষ্টা করুন

try summonDefaultDragon()

এই লাইনে সাধারণত ডু-ক্যাচ ব্লক উপস্থিত থাকতে হবে

do {
    let dragon = try summonDefaultDragon() 
} catch DragonError.dragonIsMissing {
    // Some specific-case error-handling
} catch DragonError.notEnoughMana(let manaRequired) {
    // Other specific-case error-handlng
} catch {
    // Catch all error-handling
}

দ্রষ্টব্য: ক্যাচ ক্লজটি সুইফ্ট প্যাটার্নের মিলের সমস্ত শক্তিশালী বৈশিষ্ট্য ব্যবহার করে যাতে আপনি এখানে খুব নমনীয়।

আপনি throwsকীওয়ার্ডের সাহায্যে চিহ্নিত হওয়া কোনও ফাংশন থেকে কোনও নিক্ষেপ ফাংশনটি কল করে যদি আপনি ত্রুটিটি প্রচার করার সিদ্ধান্ত নিতে পারেন :

func fulfill(quest: Quest) throws {
    let dragon = try summonDefaultDragon()
    quest.ride(dragon)
} 

বিকল্পভাবে, আপনি ব্যবহার করে নিক্ষেপ ফাংশন কল করতে পারেন try?:

let dragonOrNil = try? summonDefaultDragon()

এইভাবে আপনি যদি কোনও ত্রুটি ঘটে থাকে তবে আপনি রিটার্ন মান বা শূন্য পাবেন। এইভাবে ব্যবহার করে আপনি ত্রুটিযুক্ত জিনিসটি পাবেন না।

যার অর্থ হল আপনি try?দরকারী বিবৃতিগুলির সাথে একত্রিত করতে পারেন যেমন:

if let dragon = try? summonDefaultDragon()

অথবা

guard let dragon = try? summonDefaultDragon() else { ... }

অবশেষে, আপনি সিদ্ধান্ত নিতে পারেন যে আপনি জানেন যে ত্রুটিটি আসলে ঘটবে না (যেমন আপনি ইতিমধ্যে যাচাই করেছেন পূর্বশর্তগুলি) এবং try!কীওয়ার্ডটি ব্যবহার করুন :

let dragon = try! summonDefaultDragon()

যদি ফাংশনটি আসলে ত্রুটি ছুড়ে দেয় তবে আপনি আপনার অ্যাপ্লিকেশনটিতে একটি রানটাইম ত্রুটি পাবেন এবং অ্যাপ্লিকেশনটি সমাপ্ত হবে।

3. একটি ত্রুটি নিক্ষেপ করা

কোনও ত্রুটি ছুঁড়ে ফেলার জন্য আপনি এই জাতীয় থ্রো কীওয়ার্ডটি ব্যবহার করেন

throw DragonError.dragonIsMissing

ErrorTypeপ্রোটোকলের সাথে সঙ্গতিপূর্ণ এমন কোনও কিছু আপনি ফেলে দিতে পারেন । প্রারম্ভিকদের NSErrorজন্য এই প্রোটোকলটির সাথে সঙ্গতিপূর্ণ তবে আপনি সম্ভবত এনাম-বেসডের সাথে যেতে চান ErrorTypeযা আপনাকে একাধিক সম্পর্কিত ত্রুটিগুলি গোষ্ঠী করতে সক্ষম করে, সম্ভাব্যত এই অতিরিক্ত ডেটার টুকরা সহ

enum DragonError: ErrorType {
    case dragonIsMissing
    case notEnoughMana(requiredMana: Int)
    ...
}

নতুন সুইফট 2 এবং 3 ত্রুটি প্রক্রিয়া এবং জাভা / সি # / সি ++ শৈলিক ব্যতিক্রমগুলির মধ্যে প্রধান পার্থক্যগুলি নিম্নলিখিত:

  • : সিনট্যাক্স একটু ভিন্ন do-catch+ + try+ + deferঐতিহ্যগত বনাম try-catch-finallyসিনট্যাক্স।
  • ব্যতিক্রম হ্যান্ডলিং সাধারণত সাফল্যের পাথের চেয়ে ব্যতিক্রম পথে কার্যকর মৃত্যুর সময় অনেক বেশি সময় দেয়। এটি সুইফট ২.০ ত্রুটিগুলির ক্ষেত্রে নয়, যেখানে সাফল্যের পাথ এবং ত্রুটির পথে প্রায় একই খরচ হয়।
  • সমস্ত ত্রুটি নিক্ষেপ করার কোডটি অবশ্যই ঘোষণা করতে হবে, যদিও ব্যতিক্রমগুলি কোথাও থেকে ছুঁড়ে দেওয়া হয়েছে। সমস্ত ত্রুটিগুলি জাভা নামকরণে "ব্যতিক্রমগুলি পরীক্ষা করা"। তবে জাভার বিপরীতে, আপনি সম্ভাব্য নিক্ষিপ্ত ত্রুটিগুলি নির্দিষ্ট করে না।
  • সুইফট ব্যতিক্রমগুলি ওবিজসি ব্যতিক্রমগুলির সাথে সামঞ্জস্যপূর্ণ নয়। আপনার do-catchব্লকটি কোনও এনএসইসিপশন ধরবে না এবং বিপরীতে এটির জন্য আপনাকে অবশ্যই ওজেজেসি ব্যবহার করতে হবে।
  • সুইফট ব্যতিক্রমগুলি NSErrorফিরতি false( Boolফাংশন প্রত্যাবর্তনের জন্য ) বা nil( AnyObjectফাংশন ফিরিয়ে দেওয়ার জন্য ) এবং NSErrorPointerত্রুটির বিবরণ সহকারে পাস করার কোকো পদ্ধতি প্রচলনের সাথে সামঞ্জস্যপূর্ণ ।

ত্রুটি পরিচালনা করা সহজ করার জন্য অতিরিক্ত সিনট্যাটিক-চিনি হিসাবে, আরও দুটি ধারণা রয়েছে

  • স্থগিত ক্রিয়া ( deferকীওয়ার্ড ব্যবহার করে ) যা আপনাকে জাভা / সি # / ইত্যাদিতে অবশেষে ব্লকগুলির মতো একই প্রভাব অর্জন করতে দেয়
  • গার্ড স্টেটমেন্ট ( guardকীওয়ার্ড ব্যবহার করে ) যা আপনাকে / অন্য কোডে সাধারণ ত্রুটি পরীক্ষার / সিগন্যালিং কোডের চেয়ে কম কোড লিখতে দেয়।

সুইফট ঘ

রানটাইম ত্রুটি:

লেয়ানড্রস যেমন রানটাইম ত্রুটিগুলি পরিচালনা করার জন্য পরামর্শ দেয় (যেমন নেটওয়ার্ক সংযোগ সমস্যা, ডেটা পার্সিং, ফাইল খোলার ইত্যাদি) আপনার NSErrorযেমন ওবজেসি-তে করা উচিত, কারণ ফাউন্ডেশন, অ্যাপকিট, ইউআইকিট ইত্যাদি তাদের ত্রুটিগুলি এভাবে রিপোর্ট করে। সুতরাং এটি ভাষা জিনিস চেয়ে কাঠামোর জিনিস।

আর একটি ঘন ঘন নিদর্শন ব্যবহৃত হচ্ছে যা এএফ নেটওয়ার্কিংয়ের মতো পৃথককারী সাফল্য / ব্যর্থতা ব্লক:

var sessionManager = AFHTTPSessionManager(baseURL: NSURL(string: "yavin4.yavin.planets"))
sessionManager.HEAD("/api/destoryDeathStar", parameters: xwingSquad,
    success: { (NSURLSessionDataTask) -> Void in
        println("Success")
    },
    failure:{ (NSURLSessionDataTask, NSError) -> Void in
        println("Failure")
    })

তবুও ব্যর্থতা ব্লকটি প্রায়শই NSErrorত্রুটিটি বর্ণনা করে উদাহরণ পেয়ে যায় ।

প্রোগ্রামার ত্রুটি:

প্রোগ্রামার ত্রুটির জন্য (অ্যারের উপাদানটির সীমা অতিক্রমের মতো, কোনও ফাংশন কলকে অবৈধ আর্গুমেন্ট প্রেরণ করা ইত্যাদি) আপনি ওবিজিতে ব্যতিক্রম ব্যবহার করেছেন। সুইফট ভাষা ব্যতিক্রম জন্য কোনো ভাষা সমর্থন আছে বলে মনে হচ্ছে না (যেমন throw, catchইত্যাদি শব্দ)। যাইহোক, ডকুমেন্টেশনের পরামর্শ অনুসারে এটি ওজজির মতো একই রানটাইমটিতে চলছে এবং তাই আপনি এখনও NSExceptionsএইরকম নিক্ষেপ করতে সক্ষম হন :

NSException(name: "SomeName", reason: "SomeReason", userInfo: nil).raise()

আপনি কেবল খাঁটি সুইফটে তাদের ধরতে পারবেন না, যদিও আপনি ওজেসি কোডে ব্যতিক্রম ধরা পছন্দ করতে পারেন।

প্রশ্নগুলি হ'ল আপনাকে প্রোগ্রামার ত্রুটির জন্য ব্যতিক্রম ছুঁড়ে ফেলা উচিত, বা পরিবর্তিত ভাষা নির্দেশিকাতে অ্যাপলের পরামর্শ অনুসারে দৃ use়তাগুলি ব্যবহার করা উচিত।


20
"নেটওয়ার্ক সংযোগ সমস্যা" এবং কোকো এপিআই (এনএসফিলহ্যান্ডল) ব্যবহার করে "ফাইলগুলি খোলার" ব্যতিক্রমগুলি ছুঁড়ে ফেলতে পারে যা ধরা দরকার। সুইফটে ব্যতিক্রম ছাড়াই আপনাকে আপনার প্রোগ্রামের এই অংশটি অবজেক্টিভ-সি তে বাস্তবায়ন করতে হবে বা বিএসডি সি এপিআই ব্যবহার করে আপনার সমস্ত কাজ সম্পাদন করতে হবে (উভয়ই দুর্বল কাজের দিক দিয়ে)। আরও জন্য NSFileHandle.writeData এর জন্য ডকুমেন্টেশন দেখুন ... বিকাশকারী / অ্যাপ্লিকেশন / লাইব্রেরি / আইস / ডকুমেন্টেশন / কোকো / রেফারেন্স / ::
ম্যাট গ্যালাগার

5
আবার কোনও ব্যতিক্রম হ্যান্ডলিংয়ের অর্থ তার সমস্ত সহজাত সমস্যা সহ দ্বি-পর্যায়ের অবজেক্ট নির্মাণ। Stroustrup.com/except.pdf দেখুন ।
ফিল

2
fatalError(...)পাশাপাশি একই।
হোলএক্স

8
আমি সুইফটকে যতটা পছন্দ করি, আমার মনে হয় এটি একটি বিপর্যয়কর পছন্দ এবং এর কিছু পরিণতির স্বাদ পেয়ে তারা এই বাদ দিয়ে আগুন নিয়ে খেলছে ...
রব

2
হ্যাঁ, চেক করা ব্যতিক্রমগুলি এখন অল্প পরিমাণে ব্যবহৃত হয়, কারণ এটি পাওয়া গিয়েছিল যে প্রোগ্রামারকে ব্যতিক্রমগুলি ধরতে বাধ্য করা তাদের একক দায়িত্বের নীতি ভঙ্গ পদ্ধতিতে দূষণের কোড থেকে পুনরুদ্ধার খুব কম আশা রয়েছে। একটি ডোমেন স্তরের শ্রেণি অবকাঠামো স্তর ব্যতিক্রমগুলি মোকাবেলা করতে চায় না। সুতরাং এখন, চেক না করা ব্যতিক্রমগুলির পক্ষে প্রবণতা রয়েছে এবং আগ্রহী পক্ষ উপযুক্ত হলে এগুলি ধরতে পারে। । পরীক্ষিত = অবশ্যই পুনরুদ্ধারযোগ্য। চেক না করা = অ / সম্ভাব্য পুনরুদ্ধারযোগ্য।
জ্যাস্পার ব্লুজ

69

আপডেট জুন 9 ই 2015 - খুব গুরুত্বপূর্ণ

সুইফট 2.0 দিয়ে আসে try, throwএবং catchকীওয়ার্ড এবং সবচেয়ে উত্তেজনাপূর্ণ হল:

সুইফট স্বয়ংক্রিয়ভাবে উদ্দেশ্য-সি পদ্ধতিগুলিতে অনুবাদ করে যা পদ্ধতিগুলিতে ত্রুটি তৈরি করে যা সুইফ্টের নেটিভ ত্রুটি হ্যান্ডলিং কার্যকারিতা অনুযায়ী ত্রুটি ফেলে।

দ্রষ্টব্য: যে পদ্ধতিগুলি ত্রুটি গ্রাস করে, যেমন ডেলিগেট পদ্ধতি বা এমন পদ্ধতিগুলি যেগুলি NSError অবজেক্ট আর্গুমেন্টের সাথে একটি সম্পূর্ণতা হ্যান্ডলার গ্রহণ করে, এমন পদ্ধতিতে পরিণত হয় না যা সুইফট দ্বারা আমদানি করার সময় নিক্ষেপ করে।

এর উত্স: অ্যাপল ইনক। "কোকো এবং অবজেক্টিভ-সি (সুইফট 2 প্রিরিলিজ) সহ সুইফ্ট ব্যবহার করা।" iBooks।

উদাহরণ: (বই থেকে)

NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *URL = [NSURL fileURLWithPath:@"/path/to/file"];
NSError *error = nil;
BOOL success = [fileManager removeItemAtURL:URL error:&error];
if (!success && error){
    NSLog(@"Error: %@", error.domain);
}

দ্রুত সমতুল্য হবে:

let fileManager = NSFileManager.defaultManager()
let URL = NSURL.fileURLWithPath("path/to/file")
do {
    try fileManager.removeItemAtURL(URL)
} catch let error as NSError {
    print ("Error: \(error.domain)")
}

একটি ত্রুটি নিক্ষেপ করা:

*errorPtr = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCannotOpenFile userInfo: nil]

কলারে স্বয়ংক্রিয়ভাবে প্রচার করা হবে:

throw NSError(domain: NSURLErrorDomain, code: NSURLErrorCannotOpenFile, userInfo: nil)

অ্যাপল বই থেকে, সুইফ্ট প্রোগ্রামিং ল্যাঙ্গুয়েজ থেকে মনে হয় এনুম ব্যবহার করে ত্রুটিগুলি পরিচালনা করা উচিত।

এখানে বইয়ের একটি উদাহরণ রয়েছে।

enum ServerResponse {
    case Result(String, String)
    case Error(String)
}

let success = ServerResponse.Result("6:00 am", "8:09 pm")
let failure = ServerResponse.Error("Out of cheese.")

switch success {
case let .Result(sunrise, sunset):
    let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)."
case let .Error(error):
    let serverResponse = "Failure...  \(error)"
}

থেকে: অ্যাপল ইনক। "দ্য সুইফ্ট প্রোগ্রামিং ভাষা।" iBooks। https://itun.es/br/jEUH0.l

হালনাগাদ

অ্যাপল নিউজ বইগুলি থেকে, "সুইফট উইথ কোকো এবং অবজেক্টিভ-সি" ব্যবহার করা। সুইফ ভাষা ব্যবহার করে রানটাইম ব্যতিক্রম ঘটে না, তাই আপনার চেষ্টা করে না। পরিবর্তে আপনি ptionচ্ছিক চেইন ব্যবহার করুন ।

এখানে বইয়ের একটি প্রসার রয়েছে:

উদাহরণস্বরূপ, নীচের কোড তালিকায়, প্রথম এবং দ্বিতীয় লাইনগুলি কার্যকর করা হয় না কারণ এনএসডিট অবজেক্টে দৈর্ঘ্যের সম্পত্তি এবং অক্ষরআটিআইডেক্স: পদ্ধতিটি বিদ্যমান নেই। MyLength ধ্রুবকটি একটি alচ্ছিক INT হিসাবে অনুমিত হয়, এবং শূন্য করা হয়েছে। তিনটি লাইনে দেখানো হয়েছে এমন কোনও পদ্ধতির ফলাফল যা শর্ত সাপেক্ষে প্রতিক্রিয়া জানাতে পারে না তার ফলাফলটি শর্তসাপেক্ষে মোড়ক করতে আপনি যদি একটি if statement বিবৃতি ব্যবহার করতে পারেন

let myLength = myObject.length?
let myChar = myObject.characterAtIndex?(5)
if let fifthCharacter = myObject.characterAtIndex(5) {
    println("Found \(fifthCharacter) at index 5")
}

এর থেকে অংশ: অ্যাপল ইনক। "কোকো এবং উদ্দেশ্য-সি সহ সুইফ্ট ব্যবহার করা।" iBooks। https://itun.es/br/1u3-0.l


এবং বইগুলি আপনাকে উদ্দেশ্য-সি (এনএসইরর অবজেক্ট) থেকে কোকো ত্রুটি নমুনা ব্যবহার করতে উত্সাহিত করে

Iftচ্ছিক রিটার্ন মান দেওয়ার অতিরিক্ত বেনিফিট সহ সুইফ্টে ত্রুটি জানানো ওজেক্টিভ-সি তে একই ধাঁচ অনুসরণ করে। সর্বাধিক সহজ ক্ষেত্রে, আপনি সফল হয়েছে কি না তা নির্দেশ করার জন্য আপনি ফাংশন থেকে একটি বুল মান ফিরিয়ে দেন। যখন আপনাকে ত্রুটির কারণ জানাতে হবে তখন আপনি এনএসইররর আউট প্যারামিটারটি এনএসইররর পয়েন্টার ফাংশনে যুক্ত করতে পারেন। এই ধরণের অতিরিক্ত মেমরি সুরক্ষা এবং alচ্ছিক টাইপিং সহ অবজেক্টিক-সি এর এনএসইরর ** এর সমান। নীচের কোড তালিকায় যেমন দেখানো হয়েছে তেমন কোনও এনএসইররপয়েন্টার অবজেক্ট হিসাবে alচ্ছিক এনএসইররর প্রকারের প্রসঙ্গে পাস করার জন্য আপনি উপসর্গ এবং অপারেটরটি ব্যবহার করতে পারেন।

var writeError : NSError?
let written = myString.writeToFile(path, atomically: false,
    encoding: NSUTF8StringEncoding,
    error: &writeError)
if !written {
    if let error = writeError {
        println("write failure: \(error.localizedDescription)")
    }
}

এর থেকে অংশ: অ্যাপল ইনক। "কোকো এবং উদ্দেশ্য-সি সহ সুইফ্ট ব্যবহার করা।" iBooks। https://itun.es/br/1u3-0.l


শেষ বক্তব্যটির জন্য এটি হওয়া উচিত: my myString.writeToFile (পথ, পরমাণু: সত্য, এনকোডিং: NSUTF8 স্ট্রিং এঙ্কোডিং) চেষ্টা করুন N এনএসিররর হিসাবে ত্রুটি ধরুন {মুদ্রণ (ত্রুটি)}
জ্যাকি

1
@ জ্যাকি হ্যাঁ, এটি সুইফট ২.০-এর ক্ষেত্রে সত্য, যদিও এই উত্তরটি সুইফট ২.০ প্রকাশের আগে লেখা হয়েছিল, আমি উত্তরটি আপডেট করেছিলাম সুইফট ২.০-তে নতুন উপায় হ্যান্ডেল ত্রুটিগুলি দেখানোর জন্য updated আমি এইভাবে রেফারেন্সের জন্য দেওয়ার কথা ভাবছিলাম, তবে আমি কেবলমাত্র সুইফট ২.০ ব্যবহারের সম্পূর্ণ উত্তরটি আপডেট করার বিষয়টি বিবেচনা করব
গিলহার্ম টরেস কাস্ত্রো

12

উদ্দেশ্য-সি এর পদ্ধতির অনুরূপ সুইফটে কোনও ব্যতিক্রম নেই।

বিকাশে, আপনি assertপ্রদর্শিত হতে পারে এমন কোনও ত্রুটি ধরতে ব্যবহার করতে পারেন , এবং উত্পাদনে যাওয়ার আগে এটি সংশোধন করা দরকার।

ক্লাসিক NSErrorপদ্ধতির পরিবর্তন করা হয়নি, আপনি একটি প্রেরণ করুন NSErrorPointerযা জনবহুল হয়।

সংক্ষিপ্ত উদাহরণ:

var error: NSError?
var contents = NSFileManager.defaultManager().contentsOfDirectoryAtPath("/Users/leandros", error: &error)
if let error = error {
    println("An error occurred \(error)")
} else {
    println("Contents: \(contents)")
}

6
এটি দুটি প্রশ্ন উত্থাপন করে: যখন আমরা সুইফট থেকে ওবিজেসি কোডটি কল করি তখন কী ঘটে যখন প্রকৃতপক্ষে একটি ব্যতিক্রম ছুঁড়ে ফেলা হয় এবং এনএসইররর আমাদের সর্বজনীন ত্রুটিযুক্ত বস্তু যেমন ওবজির মতো?
এমডিজে

1
এটি কি সুইফটের সাথে জীবনের এমন একটি সত্য যা প্রারম্ভিকরা ব্যর্থ হতে পারে না বা করতে পারে না?
ফিল

11
ব্যতিক্রম হ্যান্ডলিংটি বরং নোংরা বলে মনে হচ্ছে
তাশ পেমিভা

27
হ্যাঁ, আপনি কেবল ক্র্যাশ করতে পারলে কাদের ব্যতিক্রম দরকার? বা আপনার ঘোষণা করা সমস্ত কার্যক্রমে একটি এনএসইরর ** যুক্তি হিসাবে রাখবেন? যাতে প্রতিটি প্রথম মাসের জন্য f();g();হয়ে যায় f(&err);if(err) return;g(&err);if(err) return;, তারপরে এটি ঠিক হয়ে যায়f(nil);g(nil);hopeToGetHereAlive();
হ্যারিসেলডন 78

2
এই উত্তরটি উভয় পুরানো (সুইফট এখন ব্যতিক্রম সমর্থন করে) ও ভুল (সমর্থন ব্যতিক্রম উদ্দেশ্য সি নেই।
রহিম করিমের

11

প্রস্তাবিত 'সুইফট ওয়ে' হ'ল:

func write(path: String)(#error: NSErrorPointer) -> Bool { // Useful to curry error parameter for retrying (see below)!
    return "Hello!".writeToFile(path, atomically: false, encoding: NSUTF8StringEncoding, error: error)
}

var writeError: NSError?
let written = write("~/Error1")(error: &writeError)
if !written {
    println("write failure 1: \(writeError!.localizedDescription)")
    // assert(false) // Terminate program
}

তবে আমি চেষ্টা করা / ধরা পছন্দ করি কারণ এটি অনুসরণ করা সহজ বলে মনে হয় কারণ এটি ত্রুটিটি পরিচালনা করে শেষ পর্যন্ত একটি পৃথক ব্লকে স্থানান্তরিত করে, এই বিন্যাসটিকে কখনও কখনও "গোল্ডেন পাথ" বলা হয়। ভাগ্যবান আপনি ক্লোজার দিয়ে এটি করতে পারেন:

TryBool {
    write("~/Error2")(error: $0) // The code to try
}.catch {
    println("write failure 2: \($0!.localizedDescription)") // Report failure
    // assert(false) // Terminate program
}

এছাড়াও পুনরায় চেষ্টা করার সুবিধা যুক্ত করা সহজ:

TryBool {
    write("~/Error3")(error: $0) // The code to try
}.retry {
    println("write failure 3 on try \($1 + 1): \($0!.localizedDescription)")
    return write("~/Error3r")  // The code to retry
}.catch {
    println("write failure 3 catch: \($0!.localizedDescription)") // Report failure
    // assert(false) // Terminate program
}

ট্রাইবুলের তালিকাটি হ'ল:

class TryBool {
    typealias Tryee = NSErrorPointer -> Bool
    typealias Catchee = NSError? -> ()
    typealias Retryee = (NSError?, UInt) -> Tryee

    private var tryee: Tryee
    private var retries: UInt = 0
    private var retryee: Retryee?

    init(tryee: Tryee) {
        self.tryee = tryee
    }

    func retry(retries: UInt, retryee: Retryee) -> Self {
        self.retries = retries
        self.retryee = retryee
        return self
    }
    func retry(retryee: Retryee) -> Self {
        return self.retry(1, retryee)
    }
    func retry(retries: UInt) -> Self {
        // For some reason you can't write the body as "return retry(1, nil)", the compiler doesn't like the nil
        self.retries = retries
        retryee = nil
        return self
    }
    func retry() -> Self {
        return retry(1)
    }

    func catch(catchee: Catchee) {
        var error: NSError?
        for numRetries in 0...retries { // First try is retry 0
            error = nil
            let result = tryee(&error)
            if result {
                return
            } else if numRetries != retries {
                if let r = retryee {
                    tryee = r(error, numRetries)
                }
            }
        }
        catchee(error)
    }
}

আপনি বুল মানের পরিবর্তে ptionচ্ছিক রিটার্ন মান পরীক্ষা করার জন্য একই শ্রেণি লিখতে পারেন:

class TryOptional<T> {
    typealias Tryee = NSErrorPointer -> T?
    typealias Catchee = NSError? -> T
    typealias Retryee = (NSError?, UInt) -> Tryee

    private var tryee: Tryee
    private var retries: UInt = 0
    private var retryee: Retryee?

    init(tryee: Tryee) {
        self.tryee = tryee
    }

    func retry(retries: UInt, retryee: Retryee) -> Self {
        self.retries = retries
        self.retryee = retryee
        return self
    }
    func retry(retryee: Retryee) -> Self {
        return retry(1, retryee)
    }
    func retry(retries: UInt) -> Self {
        // For some reason you can't write the body as "return retry(1, nil)", the compiler doesn't like the nil
        self.retries = retries
        retryee = nil
        return self
    }
    func retry() -> Self {
        return retry(1)
    }

    func catch(catchee: Catchee) -> T {
        var error: NSError?
        for numRetries in 0...retries {
            error = nil
            let result = tryee(&error)
            if let r = result {
                return r
            } else if numRetries != retries {
                if let r = retryee {
                    tryee = r(error, numRetries)
                }
            }
        }
        return catchee(error)
    }
}

ট্রাইঅપ્শনাল সংস্করণটি একটি অ-ptionচ্ছিক রিটার্ন প্রকার প্রয়োগ করে যা পরবর্তী প্রোগ্রামিংগুলিকে সহজ করে তোলে, যেমন 'সুইফট ওয়ে:

struct FailableInitializer {
    init?(_ id: Int, error: NSErrorPointer) {
        // Always fails in example
        if error != nil {
            error.memory = NSError(domain: "", code: id, userInfo: [:])
        }
        return nil
    }
    private init() {
        // Empty in example
    }
    static let fallback = FailableInitializer()
}

func failableInitializer(id: Int)(#error: NSErrorPointer) -> FailableInitializer? { // Curry for retry
    return FailableInitializer(id, error: error)
}

var failError: NSError?
var failure1Temp = failableInitializer(1)(error: &failError)
if failure1Temp == nil {
    println("failableInitializer failure code: \(failError!.code)")
    failure1Temp = FailableInitializer.fallback
}
let failure1 = failure1Temp! // Unwrap

ট্রায়োশনাল ব্যবহার করে:

let failure2 = TryOptional {
    failableInitializer(2)(error: $0)
}.catch {
    println("failableInitializer failure code: \($0!.code)")
    return FailableInitializer.fallback
}

let failure3 = TryOptional {
    failableInitializer(3)(error: $0)
}.retry {
    println("failableInitializer failure, on try \($1 + 1), code: \($0!.code)")
    return failableInitializer(31)
}.catch {
    println("failableInitializer failure code: \($0!.code)")
    return FailableInitializer.fallback
}

স্বতঃ-মোড়ক নোট করুন।


7

সম্পাদনা করুন: যদিও এই উত্তরটি কার্যকর হয় তবে এটি উদ্দেশ্য-সি এর চেয়ে বেশি সুইফটে রূপান্তরিত। এটি সুইফট ২.০ এর পরিবর্তন করে অচল করে দেওয়া হয়েছে। উপরের গিলহর্মে টরেস কাস্ত্রোর উত্তরটি সুইফটে ত্রুটিগুলি পরিচালনা করার পছন্দের পদ্ধতির খুব ভাল পরিচয়। VOS

এটি বের করার জন্য এটি কিছুটা সময় নিয়েছিল তবে আমি মনে করি এটি সাস করেছি। যদিও এটি কুৎসিত মনে হচ্ছে। উদ্দেশ্য-সি সংস্করণে পাতলা ত্বক ছাড়া আর কিছুই নয়।

একটি এনএসইরর পরামিতি সহ একটি ফাংশন কল করা হচ্ছে ...

var fooError : NSError ? = nil

let someObject = foo(aParam, error:&fooError)

// Check something was returned and look for an error if it wasn't.
if !someObject {
   if let error = fooError {
      // Handle error
      NSLog("This happened: \(error.localizedDescription)")
   }
} else {
   // Handle success
}`

একটি ত্রুটি প্যারামিটার লাগে এমন ফাংশনটি লেখা হচ্ছে ...

func foo(param:ParamObject, error: NSErrorPointer) -> SomeObject {

   // Do stuff...

   if somethingBadHasHappened {
      if error {
         error.memory = NSError(domain: domain, code: code, userInfo: [:])
      }
      return nil
   }

   // Do more stuff...
}


5

উদ্দেশ্য সি এর চারপাশে বেসিক মোড়ক যা আপনাকে চেষ্টা করার বৈশিষ্ট্যটি দেয়। https://github.com/williamFalcon/SwiftTryCatch

এর মতো ব্যবহার করুন:

SwiftTryCatch.try({ () -> Void in
        //try something
     }, catch: { (error) -> Void in
        //handle error
     }, finally: { () -> Void in
        //close resources
})

ভাল ধারণা. তবে কে এটি ব্যবহার করার সিদ্ধান্ত নেবেন তা অবশ্যই মনে রাখতে হবে যে কোনও ব্যতিক্রম ছুঁড়ে ফেলা হলে ট্রাই ব্লকে বরাদ্দকৃত বস্তুগুলি হ্রাস করা হয় না। এটি জম্বি অবজেক্টগুলির সমস্যা সৃষ্টি করতে পারে এবং RAII এর প্রতিটি ব্যবহার আপস করা (অটো-আনলক, অটো-এসকিএল-কমিট, অটো-এসকিএল-রোলব্যাক ...)। হয়তো সি ++ আমাদের "রানআটএক্সিট" এর কোনও ফর্মের সাথে সহায়তা করতে পারে?
hariseldon78

আপডেট: আমি সবেমাত্র খুঁজে পেয়েছি যে ব্যতিক্রম ছোঁড়াতে অবজেক্টগুলির প্রকাশ সক্ষম করতে ঝাঁকুনিতে একটি পতাকা রয়েছে: -fobjc-arc- ব্যতিক্রম। এটি আবশ্যক সংস্করণ দিয়ে এখনও কাজ করে থাকলে আমার অবশ্যই চেষ্টা করা উচিত (আমার মনে হয় এটি হওয়া উচিত)
hariseldon78

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

1
আপনার নিয়ন্ত্রণের বাইরে পরিস্থিতি থাকতে পারে। উদাহরণস্বরূপ, ভুল ফর্ম্যাটে json পার্স করা।
উইলিয়াম ফ্যালকন

3

এটি সুইফট ২.০ এর আপডেট আপডেট। আমি জাভা এর মতো বৈশিষ্ট্যযুক্ত সমৃদ্ধ ত্রুটি হ্যান্ডলিং মডেলটির অপেক্ষায় রয়েছি। অবশেষে, তারা সুসংবাদটি ঘোষণা করেছিল। এখানে

ত্রুটি পরিচালনা করার মডেল: সুইফট ২.০-তে নতুন ত্রুটি হ্যান্ডলিং মডেলটি তাত্ক্ষণিকভাবে প্রাকৃতিকভাবে অনুভব করবে, পরিচিত চেষ্টা, নিক্ষেপ এবং কীওয়ার্ডগুলি ধরা হবে । সর্বোপরি, এটি অ্যাপল এসডিকে এবং এনএসইররারের সাথে নিখুঁতভাবে কাজ করার জন্য ডিজাইন করা হয়েছিল। আসলে, এনএসইরর একটি সুইফটের ত্রুটি টাইপ অনুসারে কাজ করে। এ সম্পর্কে আরও শুনতে আপনি সুইডটে নতুন কী বিষয়ে ডাব্লুডাব্লুডিসি অধিবেশনটি অবশ্যই দেখতে চাইবেন।

যেমন:

func loadData() throws { }
func test() {
do {
    try loadData()
} catch {
    print(error)
}}

3

হিসাবে Guilherme টরেস কাস্ত্রো বলেন, সুইফট 2.0 এ, try, catch,do প্রোগ্রামিং ব্যবহার করা যাবে।

উদাহরণস্বরূপ, কোরেডাটা তথ্য পদ্ধতিটি আনার পরিবর্তে, &errorপ্যারামিটার হিসাবে রাখার পরিবর্তে managedContext.executeFetchRequest(fetchRequest, error: &error)এখন আমাদের কেবল ব্যবহারটি ব্যবহার করতে হবে managedContext.executeFetchRequest(fetchRequest)এবং তারপরে ত্রুটিটি পরিচালনা করতে হবে try, catch( অ্যাপল ডকুমেন্ট লিংক )

do {
   let fetchedResults = try managedContext.executeFetchRequest(fetchRequest) as? [NSManagedObject]
   if let results = fetchedResults{
      people = results
   }
} catch {
   print("Could not fetch")
}

আপনি যদি ইতিমধ্যে xcode7 বিটা ডাউনলোড করেন। অনুসন্ধান করার চেষ্টা করুন ত্রুটি নিক্ষেপ মধ্যে নথি এবং API রেফারেন্স এবং প্রথম দেখানো ফলাফলের চয়ন, এটি একটি মৌলিক ধারণা কি এই নতুন সিনট্যাক্স জন্য কাজ করা যেতে পারে দেয়। তবে পুরোপুরি ডকুমেন্টেশন এখনও অনেকগুলি এপিআইয়ের জন্য পোস্ট করে না।

আরও অভিনব ত্রুটি পরিচালনার কৌশলগুলি পাওয়া যেতে পারে

সুইফটে নতুন কী আছে (2015 সেশন 106 28m30s)



1

ব্যতিক্রম হ্যান্ডেল করার জন্য দুর্দান্ত এবং সাধারণ lib: ট্রাইচ্যাচফিনালি-সুইফ্ট

অন্য কয়েকজনের মতো এটি উদ্দেশ্য সি ব্যতিক্রম বৈশিষ্ট্যগুলি জুড়ে দেয়।

এটি এর মতো ব্যবহার করুন:

try {
    println("  try")
}.catch { e in
    println("  catch")
}.finally {
    println("  finally")
}

আমি একটি নমুনা যুক্ত করেছি :)
মর্টেন হল্মগার্ড

এটি সম্ভবত লেখকদের মতামতের উল্লেখ করার মতো: "সতর্কতা: এটি মজা এবং মন্দের জন্য একটি হ্যাক it এটি ব্যবহার করার প্রলোভনের বিরুদ্ধে লড়াই করুন।"
jbat100

1

সুইফট 2 দিয়ে শুরু করে, অন্যরা ইতিমধ্যে উল্লেখ করেছে যে, ত্রুটি পরিচালনার কাজটি কর / চেষ্টা / ধরা এবং ত্রুটি টাইপ এনামগুলির মাধ্যমে সবচেয়ে ভাল করা যায়। এটি সিঙ্ক্রোনাস পদ্ধতিগুলির জন্য বেশ ভাল কাজ করে তবে অ্যাসিঙ্ক্রোনাস ত্রুটি পরিচালনার জন্য একটু চালাকতার প্রয়োজন।

এই নিবন্ধটি এই সমস্যার একটি দুর্দান্ত পদ্ধতির রয়েছে:

https://jeremywsherman.com/blog/2015/06/17/using-swift-throws-with-completion-callbacks/

সংক্ষেপ:

// create a typealias used in completion blocks, for cleaner code
typealias LoadDataResult = () throws -> NSData

// notice the reference to the typealias in the completionHandler
func loadData(someID: String, completionHandler: LoadDataResult -> Void)
    {
    completionHandler()
    }

তারপরে, উপরোক্ত পদ্ধতিতে কলটি নিম্নলিখিতভাবে হবে:

self.loadData("someString",
    completionHandler:     
        { result: LoadDataResult in
        do
            {
            let data = try result()
            // success - go ahead and work with the data
            }
        catch
            {
            // failure - look at the error code and handle accordingly
            }
        })

এটি একটি পৃথক ত্রুটিহীন হ্যান্ডলার কলব্যাক অ্যাসিঙ্ক্রোনাস ফাংশনে পাস হওয়ার চেয়ে কিছুটা পরিচ্ছন্ন বলে মনে হচ্ছে, এটি কীভাবে সুইফট 2-এর আগে পরিচালনা করা হবে।


0

আমি যা দেখেছি তা হ'ল ডিভাইসের প্রকৃতির কারণে আপনি ব্যবহারকারীর কাছে বার্তা হ্যান্ডলিংয়ের গুচ্ছটি ছুঁড়ে ফেলতে চান না। এজন্য বেশিরভাগ ফাংশন alচ্ছিক মানগুলি ফেরত দেয় তবে thenচ্ছিক উপেক্ষা করার জন্য আপনি কেবল কোড করেন। যদি কোনও ফাংশন ফিরে আসে তবে এর অর্থ ব্যর্থ হয় আপনি কোনও বার্তা বা যা কিছু পপ করতে পারেন।


1
শূন্যস্থান ফিরে আসা ত্রুটির প্রকৃতি সম্পর্কে কোনও তথ্য দেয় না। ত্রুটির উপর নির্ভর করে যদি কোনও ত্রুটি ঘটে তখন যদি ত্রুটিযুক্ত বস্তুটি ফিরে আসে তবে প্রোগ্রামার এটিকে উপেক্ষা করতে, পরিচালনা করতে, এটি বুদবুদ করতে বা "বার্তা পপ করতে বা যেকোনো কিছু" বেছে নিতে পারে। জ্ঞানই শক্তি.
ভিন্স ও'সুলিভান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.