Alamofire请求提供内存警告

时间:2016-03-31 08:20:54

标签: ios swift memory-management memory-leaks alamofire

我正在使用Master Detail Application。主屏幕是仪表板,在选择项目时,移动到详细屏幕,我在后端触发Alamofire请求

以下是摘录

class APIManager: NSObject {

    class var sharedManager: APIManager {
        return _sharedManager
    }

    private var requests = [Request]()

    // Cancel any ongoing download
    func cancelRequests() {
        if requests.count > 0 {
            for request in requests {
                request.cancel()
            }
        }
    }

    func getData(completion: (dataSet: [Data]?, error: NSError?) -> Void) {
        let request = Alamofire.request(.GET, "http://request")
            .response { (request, response, data, error) in
                dispatch_async(dispatch_get_main_queue(), {
                    if(error == nil) {
                        if let response = data, data = (try? NSJSONSerialization.JSONObjectWithData(response, options: [])) as? [NSDictionary] {

                            var dataSet = [Data]()
                            for (_, dictionary) in data.enumerate() {
                                let lat = dictionary["Latitude"]
                                let lng = dictionary["Longitude"]
                                let id = dictionary["ID"] as! Int
                                let data = Data(lat: lat!, long: lng!, id: shuttleID)
                                dataSet.append(data)
                            }
                            completion(dataSet: dataSet, error: nil)
                        }
                    } else { completion(dataSet: nil, error: error) }
                })
        }
        requests.append(request)
    }
}

我有一个单独的API管理器类,我从详细视图控制器调用getData()函数。一切正常。

但是,当我反复推动和弹出时,我看到内存迅速增加,在10-15次尝试后,我得到了内存警告。但是在AppDelegate我正在管理它以显示警报消息并添加延迟计时器8秒。但是,在20-25次尝试应用程序崩溃后,由于内存警告。

viewWillDisappear()中,我也取消了任何正在进行的请求。但我无法阻止内存警告问题。我评论了我调用请求的部分,我看到没有问题,甚至内存消耗也更少。

我欢迎你的想法。

2 个答案:

答案 0 :(得分:0)

问题是您永远不会删除附加到成员变量'requests'的请求。

当您取消请求或请求成功完成时,您需要确保删除请求。

进行以下修改 -

    func cancelRequests() {
        if requests.count > 0 {
            for request in requests {
                request.cancel()
            }
        }
         requests.removeAll() //Delete all canseled requests
    }

also 

func getData(completion: (dataSet: [Data]?, error: NSError?) -> Void) {
        let request = Alamofire.request(.GET, "http://request")
            .response { (request, response, data, error) in
                dispatch_async(dispatch_get_main_queue(), {
                    if(error == nil) {
                        if let response = data, data = (try? NSJSONSerialization.JSONObjectWithData(response, options: [])) as? [NSDictionary] {

                            var dataSet = [Data]()
                            for (_, dictionary) in data.enumerate() {
                                let lat = dictionary["Latitude"]
                                let lng = dictionary["Longitude"]
                                let id = dictionary["ID"] as! Int
                                let data = Data(lat: lat!, long: lng!, id: shuttleID)
                                dataSet.append(data)
                            }
                            requests.removeObject(request)
                            completion(dataSet: dataSet, error: nil)
                        }
                    } else { 
                         requests.removeObject(request)
                         completion(dataSet: nil, error: error) }
                })
        }
        requests.append(request)
    }

在Array上添加此Handy扩展名以将项目移除到您的代码中:

// Swift 2 Array Extension
extension Array where Element: Equatable {
    mutating func removeObject(object: Element) {
        if let index = self.indexOf(object) {
            self.removeAtIndex(index)
        }
    }

    mutating func removeObjectsInArray(array: [Element]) {
        for object in array {
            self.removeObject(object)
        }
    }
}

答案 1 :(得分:0)

经过分析,我发现内存警告不是由Alamofire请求引起的。这是由于MKMapView。加载MKMapView,放大和缩小会消耗更多内存。所以,在viewWillDisappear我做了修复。

override func viewWillDisappear(animated:Bool){
    super.viewWillDisappear(animated)
    self.applyMapViewMemoryFix()
}

func applyMapViewMemoryFix(){
    switch (self.mapView.mapType) {
        case MKMapType.Hybrid:
            self.mapView.mapType = MKMapType.Standard
            break;
        case MKMapType.Standard:
            self.mapView.mapType = MKMapType.Hybrid
            break;
        default:
            break;
    }
    self.mapView.showsUserLocation = false
    self.mapView.delegate = nil
    self.mapView.removeFromSuperview()
    self.mapView = nil
}

礼貌 - Stop iOS 7 MKMapView from leaking memory