如何在 swift 中避免由于 AFNetworking 导致的内存泄漏
Posted
技术标签:
【中文标题】如何在 swift 中避免由于 AFNetworking 导致的内存泄漏【英文标题】:How to avoid Memory Leaks due to AFNetworking in swift 【发布时间】:2019-10-15 12:31:52 【问题描述】:我在我的项目中使用 AFNetworking。当我尝试使用仪器查找内存泄漏时,它显示 AFNetworking 作为内存泄漏的原因。我正在创建一个模型类,并在该类中调用 AFNetworking。对 API 的调用是从 Viewcontroller 到模型类完成的。请帮我解决这个问题。
我的编码模式在下面添加。
Class myViewController:UIViewcontroller
override func viewDidLoad()
super.viewDidLoad()
//apiCall
myModel.apiCallFuncT("value") (success) in
Class myModel
var somevariable:String
class apiCallFuncT(parameters:string,completionHandler:@escaping(_ success:Bool)->Void)
//here Im calling the AFNetworking class. Im adding the call below.
ServiceManager.getDataFromNewServiceSolOne(serviceName: URL + "\(apiName)", parameters: param , success: (result) in
completion(true)
)
//This is the serviceManger I'm calling from all models I have for api Calls.
class ServiceManager: NSObject
static var sharedManager = AFHTTPSessionManager()
class func getDataFromNewServiceSolOne(serviceName: String, parameters : [String : String]?, success:@escaping (_ result: AnyObject) -> Void, failure :@escaping (_ error : NSError) -> Void)
let manager = AFHTTPSessionManager(baseURL: NSURL(string: URL)! as URL)
manager.responseSerializer.acceptableContentTypes = ["text/html", "application/json"]
manager.post(serviceName, parameters: parameters, progress: (progress) in
, success: (task, result) in
success(result as AnyObject)
) (task, error) in
failure(error as NSError)
【问题讨论】:
您使用 AFNetworking 有什么特别的原因吗?为什么不是来自 Apple 的 URLSession 或 Alamofire?另外,请尝试在您的代码中包含一个可重现的示例。 我刚加入团队而已。 AF 是很久以前添加的。现在项目很大,很难改成另一个。以上正是我正在使用的。我在组织中无法分享网址。你能帮帮我吗? @卡姆兰 【参考方案1】:为了诊断这些问题,带有“Malloc Stack”选项的“Debug Memory Graph”功能是我们使用的第一个工具。见How to debug memory leaks when Leaks instrument does not show them?
无论如何,当我们运行它时,我们可以看到问题不在于您对 API 的使用。您的代码中没有任何强引用循环。在此示例中,我们在左侧面板中看不到任何应用程序的对象(除了应用程序和场景委托)(因为我关闭了发起请求的自定义视图控制器)。那太好了。
那么,发生了什么?问题是AFHTTPSessionManager
和它的NSURLSession
之间的循环。与大多数委托不同,NSURLSession
保留对其委托的强引用。正如the documentation 所说:
会话对象保持对此委托的强引用,直到您的应用退出或显式使会话无效。如果您不使会话无效,则您的应用会泄漏内存,直到退出。
因此,您有两种可能的解决方案:
请求完成后使会话无效。拨打finishTasksAndInvalidate
:
class func getDataFromNewServiceSolOne(serviceName: String, parameters: [String: String]?, success: @escaping (_ result: AnyObject) -> Void, failure: @escaping (_ error: NSError) -> Void)
let manager = AFHTTPSessionManager(baseURL: URL(string: baseUrlString))
manager.post(serviceName, parameters: parameters, headers: nil, progress: _ in
// this is intentionally blank
, success: task, result in
success(result as AnyObject)
, failure: task, error in
failure(error as NSError)
)
manager.session.finishTasksAndInvalidate() // add this line
另一种方法是不为每个请求创建单独的AFHTTPSessionManager
,而是将其实例化一次,然后将其存储在属性中。那么你就不用担心它会失效了。此外,创建会话有一定的开销,所以我们经常实例化一个会话,然后使用它执行许多请求。然后您不必担心为每个请求创建新会话并使其失效。
【讨论】:
以上是关于如何在 swift 中避免由于 AFNetworking 导致的内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章
我是不是需要将 Alamofire 请求打包成 AFNetwork 之类的东西?
Objective-C 如何使用 AFNetwork 上传字符串
如何使用 AFNetwork 的 AFHTTPRequestOperationManager 设置 HTTP 请求正文?