NSURLC подключение утечки в Swift

Я нашел несколько других статей о проблемах памяти с NSURLConnection, однако ни одна из них не имела отношения к проектам, использующим ARC. Моя проблема в том, что я делаю NSURLConnections каждые 0,5 с (да, я знаю, что было бы лучше с сокетами, но я не имею контроля над API). Когда я открываю инспектор отладки xCode, я ясно вижу рост используемой памяти:

Однако, когда я профилирую свое приложение с помощью инструментов - без утечек, без постоянного хранения между поколениями марок, просто ничего:

Я намеренно отделил всю свою другую логику и создал простое приложение, чтобы показать мою проблему.

Это основной (и единственный) ViewController

import UIKit

class ViewController: UIViewController {

    private var timer: NSTimer!

    private var requests = [ServerRequest]()

    override func viewDidAppear(animated: Bool)
    {
        self.timer = NSTimer(timeInterval: 0.5, target: self, selector: "refresh", userInfo: nil, repeats: true)
        NSRunLoop.mainRunLoop().addTimer(self.timer, forMode: NSRunLoopCommonModes)
    }

    @objc private func refresh()
    {
        let urlRequest = NSURLRequest(URL: NSURL(string: "https://api.stackexchange.com/2.2/questions?order=desc&sort=activity&site=stackru")!)

        let serverRequest = ServerRequest(request: urlRequest){
            [unowned self] result, error, request in

            println("yaba daba duu")

            self.requests.removeAll(keepCapacity: false)
        }

        requests.append(serverRequest)

        serverRequest.send()
    }
}

А вот мой делегат асинхронного соединения:

import Foundation

class ServerRequest: NSObject
{
    private var request: NSURLRequest!
    typealias completionType = (NSData?, NSError?, ServerRequest) -> ()
    private var completion: completionType!
    private var receivedData: NSMutableData?
    private var connection: NSURLConnection?

    init(request: NSURLRequest, completion: (NSData?, NSError?, ServerRequest) -> ())
    {
        super.init()

        self.request = request
        self.completion = completion
        self.connection = NSURLConnection(request: self.request, delegate: self, startImmediately:false)
        //this line will help connection is fired even while tere are touch events
        self.connection?.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSRunLoopCommonModes)
        NSURLCache.sharedURLCache().removeAllCachedResponses()
    }

    func send()
    {
        receivedData = NSMutableData()

        self.connection?.start()
    }

    func abort()
    {
        self.connection?.cancel()
    }
}

extension ServerRequest: NSURLConnectionDataDelegate, NSURLConnectionDelegate
{
    func connection(connection: NSURLConnection, didReceiveResponse response: NSURLResponse)
    {
        self.receivedData?.length = 0
    }

    func connection(connection: NSURLConnection, didReceiveData data: NSData)
    {
        self.receivedData?.appendData(data)
    }

    func connection(connection: NSURLConnection, didFailWithError error: NSError)
    {
        self.connection = nil
        self.completion(nil, error, self)
    }

    func connectionDidFinishLoading(connection: NSURLConnection)
    {
        self.connection = nil
        self.completion(receivedData, nil, self)
    }

    //MARK: https specific(canAuthenticateAgainstProtectionSpace is depraceted first in iOS 8)
    func connection(connection: NSURLConnection, canAuthenticateAgainstProtectionSpace protectionSpace: NSURLProtectionSpace) -> Bool
    {
        return protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust
    }

    func connection(connection: NSURLConnection, willSendRequestForAuthenticationChallenge challenge: NSURLAuthenticationChallenge)
    {
        challenge.sender.useCredential(NSURLCredential(forTrust: challenge.protectionSpace.serverTrust), forAuthenticationChallenge: challenge)
        challenge.sender.continueWithoutCredentialForAuthenticationChallenge(challenge)
    }

    func connection(connection: NSURLConnection, willCacheResponse cachedResponse: NSCachedURLResponse) -> NSCachedURLResponse? {
        return nil
    }

}

Обратите внимание, что мне нужно подключиться к серверу https, поэтому мне нужны соответствующие методы делегата. Также я реализовал методы кэширования из-за некоторых предположений в SO, что кеширование ответов в NSURLConnection может вызвать мои проблемы. Наконец, запрос запланирован в режиме "NSRunLoopCommonModes", потому что он мне нужен во время прокрутки (хотя удаление этой строки в любом случае не влияет на проблему).

ОБНОВИТЬ

Я только что попробовал даже без пользовательского класса с делегатом, и результат почти такой же. Просто скопируйте и вставьте следующее:

import UIKit

class ViewController: UIViewController {

    private var timer: NSTimer!

    override func viewDidAppear(animated: Bool)
    {
        self.timer = NSTimer(timeInterval: 0.5, target: self, selector: "refresh", userInfo: nil, repeats: true)
        NSRunLoop.mainRunLoop().addTimer(self.timer, forMode: NSRunLoopCommonModes)
    }

    @objc private func refresh()
    {
        let urlRequest = NSURLRequest(URL: NSURL(string: "https://api.stackexchange.com/2.2/questions?order=desc&sort=activity&site=stackru")!)

        NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue())
        {
            response, data, error in

            println("yaba daba duu")

        }
    }
}

И давление моей памяти снова растет

0 ответов

Другие вопросы по тегам