Zugriff auf Code in Swift 3-Fehler

73

Neu in Xcode 8 Beta 4, NSErrorist mit dem Swift- ErrorProtokolltyp verbunden. Dies wirkt sich auf StoreKit aus, wenn fehlerhafte SKPaymentTransactions behandelt werden. Sie sollten überprüfen, ob der Fehler nicht aufgetreten ist, da die Transaktion abgebrochen wurde, um festzustellen, ob dem Benutzer eine Fehlermeldung angezeigt werden soll. Sie tun dies, indem Sie die Fehler untersuchen code. Aber mit Errorstatt NSErrorgibt es keine codedefiniert. Ich konnte nicht herausfinden, wie ich den Fehlercode richtig abrufen kann Error.

Dies funktionierte in der vorherigen Version von Swift 3:

func failedTransaction(_ transaction: SKPaymentTransaction) {
    if let transactionError = transaction.error {
        if transactionError.code != SKErrorCode.paymentCancelled.rawValue {
            //show error to user
        }
     }
     ...
}

Nun das errorist ein Errornicht NSError, codeist kein Mitglied.

Jordan H.
quelle
1
Versuchen Sieif (transaction.error as NSError).code != SKErrorCode.PaymentCancelled {
Leo Dabus
1
Das funktioniert, nur als Casting NSError, danke @LeoDabus
Jordan H

Antworten:

41

Casting to SKErrorscheint in xCode 8 und Swift 3 für mich zu funktionieren ...

    guard let error = transaction.error as? SKError else {return}
    switch error.code {  // https://developer.apple.com/reference/storekit/skerror.code
    case .unknown: break
    case .paymentCancelled: break
    case .clientInvalid: break
    case .paymentInvalid: break
    case .paymentNotAllowed: break
    case .cloudServiceNetworkConnectionFailed: break
    case .cloudServicePermissionDenied: break
    case .storeProductNotAvailable: break
    }

Keine Notwendigkeit für rawValue.

Murray Sagal
quelle
Aktualisieren Sie die richtige Antwort auf diese Frage, da sie die richtigste ist. Viel lieber, dies zu tun, anstatt zu gießen NSError. Bestätigt, dass es funktioniert.
Jordan H
Ist das nicht toll? Ich habe das gleiche Problem, aber in ALAssets. Aber es scheint dort kein SKError-Äquivalent zu geben
Anton Tropashko
@Joey Apple hatte SKError aus der öffentlichen iOS 11-API für Xcode 9-Betas 1 und 2 entfernt. Dies war ein Fehler, der in Xcode 9 Beta 3 behoben wurde. Jetzt muss "SwiftyStoreKit" verwendet werden!
Anirudha Mahale
140

Eine weitere Option für den Zugriff auf Code- und Domäneneigenschaften in Swift 3-Fehlertypen besteht darin, sie wie folgt zu erweitern:

extension Error {
    var code: Int { return (self as NSError).code }
    var domain: String { return (self as NSError).domain }
}
Leo Dabus
quelle
4
Überprüfen Sie die Antwort von @ murray-sagal. Es ist besser, den neu bereitgestellten SKError zu verwenden, als zu Objective-C-Objekten zurückzukehren.
o15a3d4l11s2
56

Jetzt in Xcode 8 und Swift 3 ist die bedingte Umwandlung immer erfolgreich, daher müssen Sie Folgendes tun:

let code = (error as NSError).code

und überprüfen Sie die codefür Ihre Bedürfnisse. Hoffe das hilft

Andrey M.
quelle
11

Dies ist richtig (Apples eigene Tests verwenden diesen Ansatz):

if error._code == SKError.code.paymentCancelled.rawValue { ... }

Auf der anderen Seite wird das Casting in NSError wahrscheinlich bald veraltet sein:

let code = (error as NSError).code // CODE SMELL!!
if code == SKError.code.paymentCancelled.rawValue { ... }
rauben
quelle
Gibt es einen Link zu dem Ansatz, den Apples eigene Tests verwenden?
Andrew Paul Simmons
Nun, @ AndrewPaulSimmons, es gab keinen netten, sauberen Link, aber wenn Sie Apples Git-Repo für Swift überprüfen und dann nach "_code" suchen, können Sie alle ihre eigenen Tests sehen, in denen sie auf diese Weise mit dem Fehlerobjekt umgehen. Probieren Sie es aus: github.com/apple/swift/search?utf8=%E2%9C%93&q=_code
Rob
8
Sie betrachten das Casting in die richtige Klasse als Codegeruch, aber der externe Zugriff auf unterstrichene Mitglieder ist in Ordnung? Zugegeben, Sie sollten .codein einem if letoder einem zugreifen guard letund nicht nur blind davon ausgehen, dass die Besetzung funktioniert hat.
Devios1
Du hast recht, @ devios1. "Code Geruch" war eine dumme Art, es auszudrücken.
Rob
1

Verwenden

error._code == NSURLErrorCancelled

um den Fehlercode abzugleichen.

Gurjit Singh
quelle
Wo hast du diesen Weg gefunden ...? das funktioniert! aber ich möchte den Ort kennen, den du kennengelernt hast.
Yodagama
Ich habe gerade das Fehlerprotokoll in Xcode untersucht, wo ich dieses gefunden habe.
Gurjit Singh
Ich habe nicht verstanden. Könnten Sie bitte etwas erklären. In der Fehlerprotokolldefinition habe ich nicht einmal ein Wort für Error._code gefunden.
Yodagama
1

Vieles ändert sich. Hier ist das Update für Xcode 11.

if let skError = transaction.error as? SKError, skError.code == .paymentCancelled { print("Cancelled") }

Codetard
quelle