ios - 如何在 swift 中避免由于 AFNetworking 导致的内存泄漏
问题描述
我在我的项目中使用 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)
}
}
}
解决方案
为了诊断这些问题,带有“Malloc Stack”选项的“Debug Memory Graph”功能是我们使用的第一个工具。请参阅当 Leaks 仪器未显示内存泄漏时如何调试内存泄漏?
无论如何,当我们运行它时,我们可以看到问题不在于您对 API 的使用。您的代码中没有任何强引用循环。在此示例中,我们在左侧面板中看不到任何应用程序的对象(除了应用程序和场景委托)(因为我关闭了发起请求的自定义视图控制器)。那太好了。
发生什么了?AFHTTPSessionManager
问题是 和 之间的循环NSURLSession
。与大多数委托不同,NSURLSession
它保持对其委托的强引用。正如文档所说:
会话对象保持对此委托的强引用,直到您的应用退出或显式使会话无效。如果您不使会话无效,您的应用程序会泄漏内存,直到它退出。
因此,您有两种可能的解决方案:
请求完成后使会话无效。致电
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
为每个请求单独创建一个,而是将其实例化一次,然后将其存储在一个属性中。然后你就不用担心它会失效了。此外,创建会话有一定的开销,所以我们经常实例化一个会话,然后使用它执行许多请求。然后您不必担心为每个请求创建和使新会话无效。
推荐阅读
- javascript - 如何在字符串中的特定文本之后插入值
- c - 如果语句不适用于 C 中的 char
- reactjs - 在 React Typescript 中传递带有 props 的组件作为 prop
- javascript - 改进设置值之间的所有唯一组合导致目标数总和的功能
- java - 如何修复 Android Studio 中的“at android.view.View.jumpDrawablesToCurrentState(View.java:22662)”错误
- linux - 来自主机的特定容器的`ps`
- css - Tailwind CSS,React JS - 过渡和变换导致导航栏重叠
- postgresql - Postgres 将 2 列选择为 1 个没有空值的组合列
- python - 在 pandas 中使用 str.contains 而不是 .isin
- html - 边框半径和浏览器缩放