2015-06-09 9 views
126

Xcode 7 beta sürümünü yükledikten sonra swift kodumu Swift 2'ye dönüştürdüğümde, alabileceğim kodla ilgili bir sorunla karşılaştım. Anlamayacağım. Swift 2'nin yeni olduğunu biliyorum, bu yüzden onun hakkında hiçbir şey olmadığından arama yapıp, bir soru yazmalıyım. İşte Swift 2: Çağrı atabilir, ancak 'try' ile işaretlenmez ve hata işlenmez.

hatadır:

Call can throw, but it is not marked with 'try' and the error is not handled

Kodu:

func deleteAccountDetail(){ 
     let entityDescription = NSEntityDescription.entityForName("AccountDetail", inManagedObjectContext: Context!) 
     let request = NSFetchRequest() 
     request.entity = entityDescription 

     //The Line Below is where i expect the error 
     let fetchedEntities = self.Context!.executeFetchRequest(request) as! [AccountDetail] 

     for entity in fetchedEntities { 
     self.Context!.deleteObject(entity) 
     } 

     do { 
      try self.Context!.save() 
     } catch _ { 
     } 

    } 

Anlık: Sen sen tıpkı hatayı yakalamak zorundayız enter image description here

cevap

135

zaten f yapıyor veya save() çağrısı ve burada birden fazla hata işleme konum beri yapabilirsiniz try birden çok çağrı gibi pek tek do-catch bloğunda sırayla,:

func deleteAccountDetail() { 
    let entityDescription = NSEntityDescription.entityForName("AccountDetail", inManagedObjectContext: Context!) 
    let request = NSFetchRequest() 
    request.entity = entityDescription 

    do { 
     let fetchedEntities = try self.Context!.executeFetchRequest(request) as! [AccountDetail] 

     for entity in fetchedEntities { 
      self.Context!.deleteObject(entity) 
     } 

     try self.Context!.save() 
    } catch { 
     print(error) 
    } 
} 

Ya @ bames53 aşağıdaki yorum belirttiği gibi, bunu atıldığı yerde hatayı yakalamamak genellikle daha iyi bir uygulamadır. Yöntemi çağırmak için yöntemi throws ve try olarak işaretleyebilirsiniz. Örneğin: Swift içinde throws ile bildirilmiş bir işlevi ararken

func deleteAccountDetail() throws { 
    let entityDescription = NSEntityDescription.entityForName("AccountDetail", inManagedObjectContext: Context!) 
    let request = NSFetchRequest() 

    request.entity = entityDescription 

    let fetchedEntities = try Context.executeFetchRequest(request) as! [AccountDetail] 

    for entity in fetchedEntities { 
     self.Context!.deleteObject(entity) 
    } 

    try self.Context!.save() 
} 
+0

Bu, çözmeme yardımcı oluyor, Teşekkürler. – Xrait

+5

Aslında, istisnanın burada yakalanması gerekli değildir. 'Try' anahtar sözcüğünü işlev çağrısına eklemek ve bu işlevi“ func deleteAccountDetail() throw ”olarak bildirmek mümkündür. Ya da fonksiyonun verilen giriş için atmayacağını garanti ederseniz, 'try!' Kullanabilirsiniz. – bames53

+4

Bunu nitpick'e getirmiyorum, ancak istisnai durumların gerçekleştiği yerlerin çoğunun istisnaları yakalamadığı konusunda iyi bir istisna tabanlı hata işleme için aslında çok önemli olduğu için. Yakalama istisnasının uygun olduğu üç tür yer vardır. Diğer tüm yerlerde, kod, istisnaları açıkça ele almamalı ve temizlik yapmak için örtük 'deinit()' çağrılarına (yani RAII) güvenmeli veya bazen geçici temizlik yapmak için 'erteleme' kullanmalıdır. Daha fazlası için exceptionsafecode.com adresine bakın (C++ hakkında konuşur, ancak temel prensipler Swift istisnaları için de geçerlidir.) – bames53

33

, sen try veya try! ile işlev çağrısı siteyi açıklamak gerekir. gibi

func willOnlyThrowIfTrue(value: Bool) throws { 
    if value { throw someError } 
} 

bu fonksiyon çağrılabilir:: Biz try ile görüşmesi açıklama İşte

func foo(value: Bool) throws { 
    try willOnlyThrowIfTrue(value) 
} 

, bu işlev bir istisna olabileceğini okuyucuya sesleniyor Örneğin, bir atma fonksiyonu verilmiş ve aşağıdaki kod satırları yürütülemeyebilir. Biz de bu fonksiyon (bir özel durum willOnlyThrowIfTrue() atar yani, o zaman foo otomatik yukarı istisnayı yeniden atması, çünkü throws ile bu işlevi açıklama gerekiyor.

muhtemelen atma olarak ilan edilen bir işlevi çağırmak isterseniz ama bunu doğru giriş veriyoruz çünkü sizin durumda atmaz biliyorum ki, sen try! kullanabilirsiniz.

func bar() { 
    try! willOnlyThrowIfTrue(false) 
} 

Bu şekilde, bu kod atmaz garanti zaman, sen yok istisnai yayılımı devre dışı bırakmak için fazladan boilerkut kodu koymak için

try!, çalışma zamanında zorlanır: try! kullanırsanız ve işlev sonlandırılıyorsa, programın yürütülmesi bir çalışma zamanı hatasıyla sonlandırılır.

Çoğu özel durum işleme kodu, yukarıdaki gibi görünmelidir: yalnızca özel durumları oluştuğunda yukarı doğru yayıyorsunuz veya olası istisnaların dışarıda bırakılacağı durumlar ayarlıyorsunuz. Kodunuzdaki diğer kaynakların temizlenmesi, nesne imhasıyla (yani deinit()) veya bazen defer ed koduyla gerçekleşmelidir.

func baz(value: Bool) throws { 

    var filePath = NSBundle.mainBundle().pathForResource("theFile", ofType:"txt") 
    var data = NSData(contentsOfFile:filePath) 

    try willOnlyThrowIfTrue(value) 

    // data and filePath automatically cleaned up, even when an exception occurs. 
} 

çalıştırmak gerekiyor ancak bir deinit() işlevinde değildir kodunu temizlemek zorunda sebebi ne olursa olsun, sen defer kullanabilirsiniz olmasaydı. istisnalar ile ilgilenen

func qux(value: Bool) throws { 
    defer { 
    print("this code runs when the function exits, even when it exits by an exception") 
    } 

    try willOnlyThrowIfTrue(value) 
} 

Çoğu kod basitçe onları deinit() veya defer aracılığıyla yolda temizliyorum, arayanlar yukarı yaymak olmuştur. Bunun nedeni çoğu kodun hatalarla ne yapacağını bilmemesidir; Neyin yanlış gittiğini biliyor, ancak hata hakkında ne yapacağını bilmek için bazı üst düzey kodların yapmaya çalıştığı hakkında yeterli bilgiye sahip değil. Kullanıcıya bir diyalog sunmanın uygun olup olmadığı veya tekrar denenmesi veya başka bir şeyin uygun olup olmadığı bilinmemektedir. Bununla birlikte, daha yüksek seviye kodu, herhangi bir hata durumunda tam olarak ne yapılması gerektiğini bilmelidir. Bu nedenle istisnalar, belirli hataların başlangıçta nerede işlenebileceğine kadar balonlanmasına izin verir.

Kullanım istisnaları, catch ifadeleri üzerinden gerçekleştirilir.

func quux(value: Bool) { 
    do { 
    try willOnlyThrowIfTrue(value) 
    } catch { 
    // handle error 
    } 
} 

Her biri farklı bir özel durum yakalayan birden fazla catch ifadesine sahip olabilirsiniz.

do { 
    try someFunctionThatThowsDifferentExceptions() 
    } catch MyErrorType.errorA { 
    // handle errorA 
    } catch MyErrorType.errorB { 
    // handle errorB 
    } catch { 
    // handle other errors 
    } 
istisna dışında en iyi uygulamalar hakkında daha detaylı bilgi için

, http://exceptionsafecode.com/ bakın. Özellikle C++'yı hedefliyor, ancak Swift istisna modelini inceledikten sonra, temellerin Swift'e de uygulanacağına inanıyorum.

Swift sözdizimi ve hata işleme modeli hakkında ayrıntılı bilgi için, bkz. The Swift Programming Language (Swift 2 Prerelease).

+0

Temelde kendi kendine hata yakalayabilir mi?ya da giriş işlevi – Xrait

+1

@BrianS Özellikle 'giriş işlevi' ile ilgili olarak tam olarak ne istediğinden emin değilim, ancak 'yakalama' aslında istisnalar bağlamında 'tanıtıcı' ile eşanlamlıdır. Yani, programlama dilleri söz konusu olduğunda, bir istisnayı yakalamak ve bir istisnayı ele almak aynı şeydir. – bames53

+0

Ne demek istediğimi – Xrait