I use Alamofire to make an API call and use SwiftyJSON to wrap around the json response. XCode Instrument shows that there's memory leak created by Alamofire library.
Here's the code (pretty simple) :
Alamofire.request(service.method, service.url, parameters: nil, encoding: ParameterEncoding.URL,
headers: headers).responseJSON(completionHandler: { (req, res, result) -> Void in
// This line leak the memory
let json = JSON(result.value!)
})
If i comment out the line let json = JSON(result.value!) then no more memory leak.
Is this with master or the xcode7 branch?
Hi,
It seems that XCode apps are quite unreliable now. I tried with XCode 7.1 beta then it shows memory leak. I tried with XCode 7.0 GM then no memory leak. I highly believe this is XCode problem, because i did investigate this issue and it seems that SwiftyJSON doesn't do anything that can cause the memory leak.
I'll keep monitoring it more.
I have detected the same memory leak problem with the JSON(result) with xCode 7.0 GM. I commented out the let json = JSON(result) line and the leak went way. Am I using the code incorrectly? I have a lot of Alamofile URL Get and JSON results, this caused my application to run out of memory quickly.
Could this be the same memory leaks in the Argo swift? See https://github.com/thoughtbot/Argo/issues/205. This is related to Switch ... as.. statement that Apple said that could result in memory leak.
According to Apple xCode 7.0 release note.
Using switch against multiple types with as patterns may cause a memory leak. For example, avoid this kind of switch statement:
switch x {
case let a as A: ...
case let b as B: ...
case let c as C: ...
default: ...
}
SwiftyJSON uses the syntax extensively. We need a workaround ASAP.
There is only one block of code that has the switch... as expressions. I modified the following code in the SwiftyJSON.swift file and the memory leak went away:
if let number = newValue as? NSNumber {
if number.isBool {
_type = .Bool
} else {
_type = .Number
}
self.rawNumber = number
} else if let string = newValue as? String {
_type = .String
self.rawString = string
} else if let _ = newValue as? NSNull {
_type = .Null
} else if let array = newValue as? [AnyObject] {
_type = .Array
self.rawArray = array
} else if let dictionary = newValue as? [String : AnyObject] {
_type = .Dictionary
self.rawDictionary = dictionary
} else {
_type = .Unknown
_error = NSError(domain: ErrorDomain, code: ErrorUnsupportedType, userInfo: [NSLocalizedDescriptionKey: "It is a unsupported type"])
}
/*
switch newValue {
case let number as NSNumber:
if number.isBool {
_type = .Bool
} else {
_type = .Number
}
self.rawNumber = number
case let string as String:
_type = .String
self.rawString = string
case _ as NSNull:
_type = .Null
case let array as [AnyObject]:
_type = .Array
self.rawArray = array
case let dictionary as [String : AnyObject]:
_type = .Dictionary
self.rawDictionary = dictionary
default:
_type = .Unknown
_error = NSError(domain: ErrorDomain, code: ErrorUnsupportedType, userInfo: [NSLocalizedDescriptionKey: "It is a unsupported type"])
}
*/
So this is the right workaround.

I just found out exactly the same as Tehong. It seems that this is bug with Swift, but has been fixed in XCode 7.1 beta 2.
Has this been addressed yet? I am seeing this too in XCode 7.0
This is addressed in XCode 7.1 beta 2. It is in the release notes.
Is there a pr with a workaround that those of us not using Xcode 7.1 beta 2 can use?
I don't think so. Just modify SwiftyJSON.swift in your xCode SwiftyJSON framework directory as I did and that will eliminate the memory leak for any product produced with xCode prior to xCode 7.1 beta 2.
I just ran into this on Xcode 7.0.1 and can confirm @tehong's solution works.
:+1:
@tehong That worked for me too. Thanks
+1
This issue has been inactive for a while so I'm gonna go ahead and consider it fixed. Please let us know if you want to reopen it.
Most helpful comment
There is only one block of code that has the switch... as expressions. I modified the following code in the SwiftyJSON.swift file and the memory leak went away:
if let number = newValue as? NSNumber {
if number.isBool {
_type = .Bool
} else {
_type = .Number
}
self.rawNumber = number
} else if let string = newValue as? String {
_type = .String
self.rawString = string
} else if let _ = newValue as? NSNull {
_type = .Null
} else if let array = newValue as? [AnyObject] {
_type = .Array
self.rawArray = array
} else if let dictionary = newValue as? [String : AnyObject] {
_type = .Dictionary
self.rawDictionary = dictionary
} else {
_type = .Unknown
_error = NSError(domain: ErrorDomain, code: ErrorUnsupportedType, userInfo: [NSLocalizedDescriptionKey: "It is a unsupported type"])
}
So this is the right workaround.
