Reputation: 684
Hello fellow developers,
I'm currently facing a strange issue with some Swift 3 code.
I have a custom logging class (using 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)")
}
}
The DEBUG pre-processor directive is activated for Debug mode.
Then I'm using this method to instantiate an object from a JSON payload :
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
}
This is pretty basic but it's just to illustrate the case I've encountered.
I'm getting the following crash :
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)
...
I'm sure it's something dumb... Maybe the class being deallocated before the Log happens, resulting in the self typeof to be nil.
Any insight is welcome on the topic so thanks for your contribution / comment.
EDIT
I've been able to replicate the issue by enabling testing on release mode, it seems that disabling optimisation to check the content of the parameters solved the issue.
Maybe one of these is adding some sort of security... I'll dig deeper while trying to find a workaround.
Upvotes: 2
Views: 633
Reputation: 684
Okay, I found the culprit :
let className = NSStringFromClass(aClass)
Log.warning("Failed to create \(className) object from JSON: \(json)")
The NSStringFromClass()
function is breaking when Swift optimization is enabled (SWIFT_OPTIMIZATION_LEVEL).
I replaced it with the following :
let className = String(describing: aClass)
Log.warning("Failed to create \(className) object from JSON: \(json)")
And now everything is working but it was a pain to test...
I'll update the post name to reflect that this bug is different than an issue with a dictionary.
Upvotes: 1