2017-04-04 1 views
1

Hallo Kolleginnen und Entwickler verwenden,App stürzt ab, wenn NSStringFromClass() in Release Ziel

Ich bin derzeit eine seltsame Problem mit einigen Swift 3 Code gegenüber.

Ich habe eine benutzerdefinierte Protokollierung-Klasse (mit XCGLogger):

struct Log { 
    #if DEBUG 
     fileprivate static let Logger: XCGLogger = { 
      let logger = XCGLogger(identifier: "API") 

      if let standardConsoleDestination = logger.destination(withIdentifier: XCGLogger.Constants.baseConsoleDestinationIdentifier) as? ConsoleDestination { 
       standardConsoleDestination.showLogIdentifier = true 
       standardConsoleDestination.showFunctionName = false 
       standardConsoleDestination.showThreadName = false 
       standardConsoleDestination.showLevel = true 
       standardConsoleDestination.showFileName = false 
       standardConsoleDestination.showLineNumber = false 
       standardConsoleDestination.showDate = true 
       standardConsoleDestination.outputLevel = .debug 
      } 

      return logger 
     }() 
    #endif 

    fileprivate static func log(_ level: XCGLogger.Level, message: String) { 
     #if DEBUG 
      Logger.logln("[] \(message)", level: level, userInfo: [:]) 
     #endif 
    } 

    static func warning(_ message: String) { 
     log(.warning, message: message) 
    } 

    static func parseFailure(in aClass: AnyClass, json: [String: Any]) { 
     let className = NSStringFromClass(aClass) 
     Log.warning("Failed to create \(className) object from JSON: \(json)") 
    } 
} 

Die DEBUG Pre-Prozessor-Direktive für Debug-Modus aktiviert ist.

Ich benutze diese Methode dann ein Objekt aus einer JSON Nutzlast zu instanziiert:

required init?(json: [String: Any]) { 
    guard 
     let value1 = json["value1"] as? String, 
     let value2 = json["value2"] as? String 
     else { 
      Log.parseFailure(in: type(of: self), json: json) 
      return nil 
    } 

    self.value1 = value1 
    self.value2 = value2 
} 

Das ist ziemlich einfach, aber es ist nur der Fall, den ich erlebt habe zu erläutern.

ich den folgenden Absturz bekommen:

Exception Type: EXC_BAD_ACCESS (SIGSEGV) 
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000e115ebec8 

1 MyProject     0x00000001015cb92c static Log.parseFailure ->() (in MyProject) (Log.swift:0) 
2 MyProject     0x000000010151c9a0 Object.init(json : [String : Any]) -> Object? (Object.swift:0) 
... 

Ich bin sicher, es ist etwas dumm ... Vielleicht ist die Klasse freigegeben wird, bevor der Log geschieht, in dem Selbst resultierenden typeof als gleich Null.

Jeder Einblick ist willkommen zu dem Thema, also vielen Dank für Ihren Beitrag/Kommentar.

EDIT

Ich habe in der Lage, das Problem zu replizieren, indem Tests auf Release-Modus ermöglicht, so scheint es, dass die Optimierung deaktivieren der Inhalt der Parameter zu überprüfen, um das Problem zu lösen.

Vielleicht ist einer von ihnen das Hinzufügen einer Art von Sicherheit ... Ich werde tiefer graben, während ich versuche, einen Workaround zu finden.

+1

Können Sie einen Absturzbericht erstellen? – Sergey

+2

Gibt es sogar eine entfernte Möglichkeit, dass der 'json' selbst" nil "war? Vielleicht, als Ihr Backend auf ein Problem stieß und eine leere Antwort zurückgab? – Losiowaty

+0

@Losiowaty Nein, die Payload des Backends wurde immer bereitgestellt. Dieser Absturz geschah nur, wenn einer der Schlüssel fehlte (was eigentlich nie passieren sollte ...). – Ethenyl

Antwort

0

Okay, fand ich den Täter:

let className = NSStringFromClass(aClass) 
Log.warning("Failed to create \(className) object from JSON: \(json)") 

Die NSStringFromClass() Funktion bricht, wenn Swift Optimierung aktiviert ist (SWIFT_OPTIMIZATION_LEVEL).

Ich ersetzte es mit den folgenden:

let className = String(describing: aClass) 
Log.warning("Failed to create \(className) object from JSON: \(json)") 

Und jetzt alles funktioniert, aber es war ein Schmerz zu testen ...

Ich werde den Beitrag Namen aktualisieren widerzuspiegeln, dass dieser Fehler ist anders als ein Problem mit einem Wörterbuch.