ios - 使用 Swift 获取核心数据请求中的内存泄漏

标签 ios swift core-data memory-leaks

当我使用 Swift 发出核心数据提取请求时,我遇到了内存泄漏。但是,我在应用程序的不同部分发出了几乎相同的提取请求,但它不会导致泄漏。在这两种情况下,提取请求都是在 View Controller 的 viewDidLoad 中发出的,提取请求的结果被分配给 View Controller 的可选属性。

以下是不会造成任何泄漏的获取请求的方法:

class LocationFilter {
    //Lots of other code...
    class func getAllPlacesOfRegionType<T: Region>(regionType: RegionType) -> [T] {
        let fetchRequest = NSFetchRequest(entityName: regionType.rawValue)

        var places: [T]
        do {
            places = try CoreDataStack.sharedInstance.context.executeFetchRequest(
                fetchRequest) as! [T]
        } catch let error as NSError {
            NSLog("Fetch request failed: %@", error.localizedDescription)
            places = [T]()
        }

        places.sortInPlace({ (firstPlace, nextPlace) -> Bool in
            //Ingenious sorting code...
        })

        return places
    }
}

该方法在viewController的viewDidLoad中调用,结果赋值给属性var allRegions: [Region]?没有任何泄漏。这是代码:

class PlacesTableViewController: UITableViewController {
    var allRegions: [Region]?
    @IBOutlet weak var segmentedRegions: UISegmentedControl!

    @IBAction func selectRegionSegment(sender: UISegmentedControl) {
        // When the segmented control is tapped, the appropriate list will be loaded.
        switch sender.selectedSegmentIndex {
        case 0:  //Country Segment
            allRegions = LocationFilter.getAllPlacesOfRegionType(RegionType.Country)
        case 1:  //States segment
            allRegions = LocationFilter.getAllPlacesOfRegionType(RegionType.Province)
        case 2:  //Cities segment
            allRegions = LocationFilter.getAllPlacesOfRegionType(RegionType.City)
        case 3:  //Addresses segment
            allRegions = LocationFilter.getAllPlacesOfRegionType(RegionType.Address)
        default:
            break
        }

        // Then reload the cells with animations.
        let index = NSIndexSet(index: 0)
        tableView.reloadSections(index, withRowAnimation: UITableViewRowAnimation.Automatic)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        selectRegionSegment(segmentedRegions)
    }
}

下面的方法在不同viewController的viewDidLoad中调用来设置属性var allDays: [Day]! .

class DateFilter {
    //Lots of other code in the class...
    class func getAllDays() -> [Day] {
        let fetchRequest = NSFetchRequest(entityName: "Day")

        let days: [Day]
        do {
            days = try CoreDataStack.sharedInstance.context.executeFetchRequest(
                fetchRequest) as! [Day]
        } catch let error as NSError {
            NSLog("Fetch request failed: %@", error.localizedDescription)
            days = [Day]()
        }

        return days
    }
}

这就是它的名字:

class SearchViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    var allDays: [Day]!

    override func viewDidLoad() {
        super.viewDidLoad()

        allDays = DateFilter.getAllDays()

        let backgroundView = UIView(frame: CGRectZero)
        tableView.tableFooterView = backgroundView
        tableView.backgroundColor = UIColor.groupTableViewBackgroundColor()
    }
}

Xcode 工具在调用时检测到内存泄漏。据说负责的图书馆是libswiftFoundation.dylib , 负责的框架是 static Array<A>._forceBridgeFromObjectiveC<A>(NSArray, result:inout [A]?) -> () .当我查看 Cycles & Roots 时,它显示一个 NSArray在根部,带有 +16 list: (null)+24 [no ivar]: (null)分支。

我存储提取请求结果的方式有问题吗?或者这是 Swift 与 Core Data 交互方式中的错误?

编辑:根据 Mundi 的建议整理代码。 编辑 2:添加了调用获取请求函数的代码。

最佳答案

在尝试了很多事情之后,我很确定这是在获取我的 Day 实体时 Core Data 如何将 NSArray 转换为 Swift 数组的错误。也许它与 Day 实体的关系或属性有关。我会继续研究它。

目前,我找到了解决方法。 Instruments 不断指向将 NSArray 转换为 Array 的 libswiftFoundation 方法,Cycles & Roots 不断显示一个没有 no ivar 的 NSArray。根据我的研究,这与获取请求创建的 NSArray 的初始化有关,它在后台转换为 Swift 数组。由于我无法更改它,因此我根据获取结果创建了一个新数组:

override func viewDidLoad() {
    super.viewDidLoad()

    let fetchResults: [Day] = DateFilter.getAllDays()
    allDays = fetchResults.map({$0})

    let backgroundView = UIView(frame: CGRectZero)
    tableView.tableFooterView = backgroundView
    tableView.backgroundColor = UIColor.groupTableViewBackgroundColor()
}

神奇的是,内存泄漏消失了!我不完全确定为什么 fetchResults 数组会泄漏,但这似乎是问题的根源。

关于ios - 使用 Swift 获取核心数据请求中的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33574867/

相关文章:

ios - 支付队列不调用观察者对象更新交易,为什么?

ios - 从iPhone的Watch触发搜寻

objective-c - ManagedObjectContext 从 AppDelegate 返回 nil

c++ - AudioOutputUnitStart 非常慢

ios - Codesign 在 High Sierra 中返回了 errSecInternalComponent

ios - Swift 嵌套类属性

ios - 为什么 swift GCD 不能在 tableview cell imageView 中工作

ios - 我如何在 swift 的扩展中声明 NSLayoutConstraint 类型的变量

ios - 将本地通知与 CoreData 结合使用作为每月提醒

iphone - 我的 CoreData 获取请求实际上返回了什么?