ฉันไม่ได้อ่าน Swift มากเกินไป แต่สิ่งหนึ่งที่ฉันสังเกตเห็นคือไม่มีข้อยกเว้น ดังนั้นพวกเขาจะจัดการข้อผิดพลาดใน Swift อย่างไร มีใครพบสิ่งที่เกี่ยวข้องกับการจัดการข้อผิดพลาดหรือไม่?
ฉันไม่ได้อ่าน Swift มากเกินไป แต่สิ่งหนึ่งที่ฉันสังเกตเห็นคือไม่มีข้อยกเว้น ดังนั้นพวกเขาจะจัดการข้อผิดพลาดใน Swift อย่างไร มีใครพบสิ่งที่เกี่ยวข้องกับการจัดการข้อผิดพลาดหรือไม่?
คำตอบ:
ทุกอย่างเปลี่ยนไปเล็กน้อยใน Swift 2 เนื่องจากมีกลไกการจัดการข้อผิดพลาดใหม่ซึ่งค่อนข้างคล้ายกับข้อยกเว้น แต่มีรายละเอียดแตกต่างกัน
หากฟังก์ชัน / เมธอดต้องการระบุว่าอาจเกิดข้อผิดพลาดควรมีthrows
คำหลักเช่นนี้
func summonDefaultDragon() throws -> Dragon
หมายเหตุ: ไม่มีข้อกำหนดสำหรับประเภทของข้อผิดพลาดที่จริง ๆ แล้วฟังก์ชันสามารถโยนได้ การประกาศนี้ระบุเพียงว่าฟังก์ชั่นสามารถส่งตัวอย่างของการใช้งาน ErrorType หรือการโยนไม่ได้เลย
ในการเรียกใช้ฟังก์ชันคุณต้องใช้คำหลักลองเช่นนี้
try summonDefaultDragon()
โดยปกติบรรทัดนี้ควรเป็นบล็อก do-catch ปัจจุบันเช่นนี้
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
}
หมายเหตุ: catch clause ใช้คุณลักษณะที่มีประสิทธิภาพทั้งหมดของการจับคู่รูปแบบ Swift เพื่อให้คุณมีความยืดหยุ่นที่นี่
คุณอาจตัดสินใจที่จะเผยแพร่ข้อผิดพลาดหากคุณกำลังเรียกฟังก์ชั่นการขว้างปาจากฟังก์ชั่นที่ถูกทำเครื่องหมายด้วย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()
หากฟังก์ชั่นเกิดข้อผิดพลาดจริง ๆ คุณจะได้รับข้อผิดพลาดรันไทม์ในแอปพลิเคชันของคุณและแอปพลิเคชันจะยุติ
เพื่อที่จะโยนข้อผิดพลาดคุณใช้การโยนคำหลักเช่นนี้
throw DragonError.dragonIsMissing
คุณสามารถโยนอะไรก็ได้ที่สอดคล้องกับErrorType
โปรโตคอล สำหรับ starters เป็นNSError
ไปตามโปรโตคอลนี้ แต่คุณอาจต้องการใช้ enum ErrorType
ซึ่งช่วยให้คุณสามารถจัดกลุ่มข้อผิดพลาดที่เกี่ยวข้องหลายอย่างพร้อมกับข้อมูลเพิ่มเติมเช่นนี้
enum DragonError: ErrorType {
case dragonIsMissing
case notEnoughMana(requiredMana: Int)
...
}
ความแตกต่างที่สำคัญระหว่างกลไกข้อผิดพลาด Swift 2 & 3 ใหม่และข้อยกเว้นสไตล์ Java / C # / C ++ มีดังนี้:
do-catch
+ try
+ defer
vs ดั้งเดิมtry-catch-finally
ไวยากรณ์do-catch
บล็อกของคุณจะไม่จับ NSException ใด ๆ และในทางกลับกันคุณต้องใช้ ObjCNSError
ระเบียบวิธีการCocoa ของการส่งคืนอย่างใดอย่างหนึ่งfalse
(สำหรับBool
ฟังก์ชั่นการกลับมา) หรือnil
(สำหรับAnyObject
ฟังก์ชั่นการกลับมา) และผ่านNSErrorPointer
กับรายละเอียดข้อผิดพลาดในฐานะที่เป็นน้ำตาล syntatic พิเศษเพื่อลดความผิดพลาดในการจัดการมีสองแนวคิดเพิ่มเติม
defer
คำหลัก) ซึ่งช่วยให้คุณได้รับผลเช่นเดียวกับในที่สุดบล็อกใน Java / C # / ฯลฯguard
คำหลัก) ซึ่งช่วยให้คุณเขียนน้อยกว่าถ้า / อื่น ๆ รหัสกว่าในการตรวจสอบข้อผิดพลาดปกติ / รหัสการส่งสัญญาณข้อผิดพลาดรันไทม์:
ตามที่ Leandros แนะนำสำหรับการจัดการข้อผิดพลาดรันไทม์ (เช่นปัญหาการเชื่อมต่อเครือข่าย, การแยกวิเคราะห์ข้อมูล, การเปิดไฟล์, ฯลฯ ) คุณควรใช้NSError
อย่างที่เคยทำใน ObjC, เพราะ Foundation, AppKit, UIKit, ฯลฯ รายงานข้อผิดพลาดด้วยวิธีนี้ ดังนั้นมันจึงเป็นโครงงานมากกว่าเรื่องภาษา
อีกรูปแบบที่ใช้บ่อยคือความสำเร็จของตัวแยก / บล็อกความล้มเหลวเช่นใน AFNetworking:
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
เช่นอธิบายข้อผิดพลาด
ข้อผิดพลาดของโปรแกรมเมอร์:
สำหรับข้อผิดพลาดของโปรแกรมเมอร์ (เช่นไม่สามารถเข้าถึงองค์ประกอบอาร์เรย์ได้อาร์กิวเมนต์ที่ไม่ถูกต้องถูกส่งผ่านไปยังการเรียกใช้ฟังก์ชัน ฯลฯ ) คุณใช้ข้อยกเว้นใน ObjC ดูเหมือนว่าภาษา Swift จะไม่สนับสนุนภาษาใด ๆ สำหรับข้อยกเว้น (เช่นthrow
, catch
คำหลัก ฯลฯ ) อย่างไรก็ตามตามเอกสารแนะนำว่ามันกำลังทำงานอยู่ในรันไทม์เดียวกับ ObjC และดังนั้นคุณยังสามารถโยนNSExceptions
ดังนี้:
NSException(name: "SomeName", reason: "SomeReason", userInfo: nil).raise()
คุณไม่สามารถจับพวกมันด้วย Swift ล้วนๆได้แม้ว่าคุณจะสามารถจับข้อยกเว้นในรหัส ObjC
คำถามคือคุณควรโยนข้อยกเว้นสำหรับข้อผิดพลาดของโปรแกรมเมอร์หรือใช้การยืนยันตามที่ Apple แนะนำในคู่มือภาษา
fatalError(...)
เป็นเช่นเดียวกับดี
อัปเดต 9 มิถุนายน 2558 - สำคัญมาก
สวิฟท์ 2.0 มาพร้อมกับtry
, throw
และcatch
คำหลักและที่น่าตื่นเต้นที่สุดคือ:
Swift แปลวิธีการ Objective-C โดยอัตโนมัติซึ่งสร้างข้อผิดพลาดเป็นวิธีการที่ทำให้เกิดข้อผิดพลาดตามฟังก์ชันการจัดการข้อผิดพลาดดั้งเดิมของ Swift
หมายเหตุ: วิธีการที่ใช้ข้อผิดพลาดเช่นวิธีการมอบสิทธิ์หรือวิธีการที่ใช้ตัวจัดการความสมบูรณ์ด้วยอาร์กิวเมนต์วัตถุ NSError ไม่กลายเป็นวิธีการที่โยนเมื่อนำเข้าโดย Swift
ข้อความที่ตัดตอนมาจาก: Apple Inc. “ การใช้ Swift กับ Cocoa และ Objective-C (Swift 2 Prerelease)” 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);
}
ค่าที่เทียบเท่าใน swift จะเป็น:
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)
จากหนังสือ Apple ภาษา Swift Programming Language ดูเหมือนว่าควรจัดการข้อผิดพลาดโดยใช้ enum
นี่คือตัวอย่างจากหนังสือ
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)"
}
จาก: Apple Inc. “ ภาษาการเขียนโปรแกรม Swift” iBooks https://itun.es/br/jEUH0.l
ปรับปรุง
จากหนังสือข่าวของ Apple "การใช้ Swift กับ Cocoa และ Objective-C" ข้อยกเว้นรันไทม์ไม่ได้เกิดขึ้นโดยใช้ภาษาที่รวดเร็วดังนั้นนั่นเป็นเหตุผลว่าทำไมคุณถึงไม่ลองดู แทนที่จะใช้ตัวเลือกการเชื่อมโยงแบบแทน
นี่คือยืดจากหนังสือ:
ตัวอย่างเช่นในรายการรหัสด้านล่างบรรทัดแรกและบรรทัดที่สองจะไม่ถูกดำเนินการเนื่องจากคุณสมบัติความยาวและเมธอด characterAtIndex: ไม่มีอยู่ในวัตถุ NSDate ค่าคงที่ myLength นั้นอนุมานว่าเป็นตัวเลือก Int และตั้งค่าเป็นศูนย์ คุณยังสามารถใช้คำสั่ง if – let เพื่อแกะผลของวิธีการที่วัตถุไม่ตอบสนองตามที่แสดงในบรรทัดที่สาม
let myLength = myObject.length?
let myChar = myObject.characterAtIndex?(5)
if let fifthCharacter = myObject.characterAtIndex(5) {
println("Found \(fifthCharacter) at index 5")
}
ข้อความที่ตัดตอนมาจาก: Apple Inc. “ การใช้ Swift กับ Cocoa และ Objective-C” iBooks https://itun.es/br/1u3-0.l
และหนังสือยังสนับสนุนให้คุณใช้รูปแบบข้อผิดพลาดโกโก้จาก Objective-C (NSError Object)
การรายงานข้อผิดพลาดใน Swift เป็นไปตามรูปแบบเดียวกับที่ทำใน Objective-C พร้อมสิทธิประโยชน์เพิ่มเติมในการนำเสนอค่าตอบแทนที่เป็นทางเลือก ในกรณีที่ง่ายที่สุดคุณคืนค่า Bool จากฟังก์ชันเพื่อระบุว่าสำเร็จหรือไม่ เมื่อคุณต้องการรายงานสาเหตุของข้อผิดพลาดคุณสามารถเพิ่มฟังก์ชัน NSError out พารามิเตอร์ประเภท NSErrorPointer ประเภทนี้เทียบเท่ากับ NSError ** ของ Objective-C โดยมีความปลอดภัยของหน่วยความจำเพิ่มเติมและการพิมพ์เสริม คุณสามารถใช้คำนำหน้า & โอเปอเรเตอร์เพื่อส่งผ่านการอ้างอิงไปยังประเภท NSError ที่เป็นตัวเลือกเป็นวัตถุ NSErrorPointer ดังที่แสดงในรายการรหัสด้านล่าง
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)")
}
}
ข้อความที่ตัดตอนมาจาก: Apple Inc. “ การใช้ Swift กับ Cocoa และ Objective-C” iBooks https://itun.es/br/1u3-0.l
ไม่มีข้อยกเว้นใน Swift ซึ่งคล้ายกับวิธีการของ C-Objective
ในการพัฒนาคุณสามารถใช้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)")
}
f();g();
กลายเป็นf(&err);if(err) return;g(&err);if(err) return;
เดือนแรกแล้วมันก็กลายเป็นf(nil);g(nil);hopeToGetHereAlive();
คำแนะนำ 'Swift Way' คือ:
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
}
รายชื่อของ TryBool คือ:
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)
}
}
คุณสามารถเขียนคลาสที่คล้ายกันเพื่อทดสอบค่าที่ส่งคืนซึ่งเป็นทางเลือกแทนค่า Bool:
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)
}
}
รุ่น TryOptional บังคับใช้ชนิดส่งคืนที่ไม่ใช่ตัวเลือกซึ่งทำให้การเขียนโปรแกรมที่ตามมาง่ายขึ้นเช่น 'Swift Way:
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
ใช้ TryOptional:
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
}
หมายเหตุการแกะอัตโนมัติ
แก้ไข:ถึงแม้ว่าคำตอบนี้จะได้ผล แต่ก็มีอะไรมากกว่าคำแปลของ Objective-C ใน Swift มันล้าสมัยจากการเปลี่ยนแปลงใน Swift 2.0 คำตอบของ Guilherme Torres Castro ด้านบนเป็นคำแนะนำที่ดีมากเกี่ยวกับวิธีจัดการข้อผิดพลาดใน Swift VOS
มันคิดออกเล็กน้อย แต่ฉันคิดว่าฉัน sussed มัน ดูเหมือนว่าน่าเกลียด ไม่มีอะไรยิ่งไปกว่าสกินผอมกว่ารุ่น Objective-C
การเรียกฟังก์ชันด้วยพารามิเตอร์ NSError ...
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...
}
เสื้อคลุมพื้นฐานรอบ C วัตถุประสงค์ที่ให้คุณลองจับคุณสมบัติ https://github.com/williamFalcon/SwiftTryCatch
ใช้เช่น:
SwiftTryCatch.try({ () -> Void in
//try something
}, catch: { (error) -> Void in
//handle error
}, finally: { () -> Void in
//close resources
})
นี่คือคำตอบสำหรับการอัปเดตสำหรับ swift 2.0 ฉันกำลังมองหารูปแบบการจัดการข้อผิดพลาดที่อุดมไปด้วยคุณลักษณะเช่นใน java ในที่สุดพวกเขาก็ประกาศข่าวดี ที่นี่
การจัดการรูปแบบข้อผิดพลาด: รูปแบบการจัดการข้อผิดพลาดใหม่ในสวิฟท์ 2.0 ทันทีจะรู้สึกธรรมชาติที่คุ้นเคยลองโยนและจับคำหลัก เหนือสิ่งอื่นใดมันถูกออกแบบมาเพื่อทำงานอย่างสมบูรณ์แบบกับ Apple SDK และ NSError อันที่จริง NSError เป็นไปตาม ErrorType ของ Swift แน่นอนคุณจะต้องการชมเซสชัน WWDC เกี่ยวกับมีอะไรใหม่ใน Swift เพื่อฟังข้อมูลเพิ่มเติม
เช่น :
func loadData() throws { }
func test() {
do {
try loadData()
} catch {
print(error)
}}
ในฐานะที่เป็น Guilherme Torres คาสโตรกล่าวว่าในสวิฟท์ 2.0 try
, catch
,do
สามารถนำมาใช้ในการเขียนโปรแกรม
ยกตัวอย่างเช่นใน CoreData เรียกวิธีการข้อมูลแทนการใส่&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 Beta แล้ว ลองค้นหาข้อผิดพลาดในการโยนเอกสารและอ้างอิง APIและเลือกผลลัพธ์ที่แสดงเป็นครั้งแรกมันให้แนวคิดพื้นฐานที่สามารถทำได้สำหรับไวยากรณ์ใหม่นี้ อย่างไรก็ตามเอกสารทั้งหมดยังไม่ได้โพสต์สำหรับ API จำนวนมาก
เทคนิคการจัดการข้อผิดพลาดแฟนซีเพิ่มเติมสามารถพบได้ใน
มีอะไรใหม่ในสวิฟท์ (2015 เซสชัน 106 28m30s)
การจัดการข้อผิดพลาดเป็นคุณสมบัติใหม่ของ Swift 2.0 มันใช้try
,throw
และcatch
คำหลัก
ดูประกาศApple Swift 2.0 บนบล็อกอย่างเป็นทางการของ Apple Swift
lib ที่ดีและง่ายต่อการจัดการข้อยกเว้น: TryCatchFinally-Swift
มันคล้ายกับคุณสมบัติข้อยกเว้นของ C วัตถุประสงค์
ใช้แบบนี้:
try {
println(" try")
}.catch { e in
println(" catch")
}.finally {
println(" finally")
}
การเริ่มต้นด้วย Swift 2 อย่างที่คนอื่น ๆ พูดถึงแล้วการจัดการข้อผิดพลาดทำได้ดีที่สุดผ่านการใช้ do / try / catch และ ErrorType enums วิธีนี้ใช้ได้ดีสำหรับวิธีการแบบซิงโครนัส แต่ต้องใช้ความฉลาดเล็กน้อยสำหรับการจัดการข้อผิดพลาดแบบอะซิงโครนัส
บทความนี้มีแนวทางที่ดีในการแก้ไขปัญหานี้:
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
}
})
ดูเหมือนว่าจะสะอาดกว่าการแยก callHandler errorHandler แยกต่างหากซึ่งเป็นวิธีจัดการสิ่งนี้ก่อน Swift 2
สิ่งที่ฉันได้เห็นก็คือเนื่องจากลักษณะของอุปกรณ์ที่คุณไม่ต้องการทิ้งข้อความแสดงข้อผิดพลาดที่เป็นความลับจำนวนมากให้กับผู้ใช้ นั่นคือเหตุผลที่ฟังก์ชั่นส่วนใหญ่ส่งคืนค่าที่เป็นทางเลือกจากนั้นคุณเพียงแค่โค้ดที่จะละเว้นตัวเลือก หากฟังก์ชั่นกลับมาไม่มีความหมายมันล้มเหลวคุณสามารถป๊อปอัพข้อความหรืออะไรก็ได้