UInavigationController中使用异步代码的弱无限用法

时间:2015-12-23 10:11:39

标签: ios swift core-data

我有一个经典的主细节视图应用程序。在详细视图中,我添加了pull to refresh功能来刷新网络数据。即使我无法复制,我也会收到与此刷新功能相关的崩溃报告。我试图限制我的连接,刷新很多次,在视图控制器之间来回,仍然无法重现它。我想我应该在这里使用弱者或无主人,但我不确定选择哪一个。 User是我从Master View传递的Core Data对象。我的崩溃报告指示在对用户执行写操作期间,程序崩溃。 Crashlytics报告User.detail.count为0,这似乎表明User.detail已被释放?如果你能帮我解决这个问题,我感激不尽。

class User:NSManagedObject {
    @NSManaged var detail: NSOrderedSet
}

class UserDetail:NSManagedObject {
    @NSManaged var message:String?

}
class APIService {

    func getData(date:NSDate?,success: (User) -> Void, failure: (NSHTTPURLResponse?, AnyObject?, ErrorType) -> Void) {

    }
}

class ViewController {
var myUser:User!
typealias UserCompletion = (error: ErrorType?) -> Void

    func deleteDetails() {

    }

    func updateDetails() {

    }

func refreshList(completion: UserCompletion) {
    let downloadGroup = dispatch_group_create()
    var storedError: ErrorType?


    let service = APIService()
    dispatch_group_enter(downloadGroup)

    service.getData(nil,
        success: { user in
            var isitNew = false

            //first check if the amount of details changed.
            if user.detail.count == self.myUser.detail.count {
                let oldDetail = self.myUser.detail.lastObject as! UserDetail
                let newDetail = user.detail.lastObject as! UserDetail
                if oldDetail.message != newDetail.message {

                    isitNew = true
                }

            }
            if isitNew || (user.detail.count > 0 && user.detail.count != self.myUser.detail.count) { //something is changed

                //Following log function logs detail count as 0 "Something is new count: 0"
                //CLSLogv("Something is new count: %d", getVaList([self.myUser.detail.count]))

                //Crash after this log
                // delete old details and update
                self.deleteDetails()
                self.updateDetails()

            }
            dispatch_group_leave(downloadGroup)

        },
        failure: { response, document, error in
            storedError = error
            dispatch_group_leave(downloadGroup)

    })
    // Exit from group
    dispatch_group_notify(downloadGroup, dispatch_get_main_queue()) { // 2
        completion(error: storedError)
        }
    }
}

1 个答案:

答案 0 :(得分:0)

修改

哦,我觉得我误读了你的帖子(和我最初回答的问题一样)。在闭包中使用[弱自我]来获得弱引用:

success: { [weak self] user in
        var isitNew = false

        //first check if the amount of details changed.
        if user.detail.count == self?.myUser.detail.count {
            let oldDetail = self?.myUser.detail.lastObject as! UserDetail
            let newDetail = user.detail.lastObject as! UserDetail
            if oldDetail.message != newDetail.message {

                isitNew = true
            }

        }
        if isitNew || (user.detail.count > 0 && user.detail.count != self?.myUser.detail.count) { //something is changed

            //Following log function logs detail count as 0 "Something is new count: 0"
            //CLSLogv("Something is new count: %d", getVaList([self?.myUser.detail.count]))

            //Crash after this log
            // delete old details and update
            self?.deleteDetails()
            self?.updateDetails()

        }
        dispatch_group_leave(downloadGroup)

    }

原始回复 (暂时留下这个 - 可能仍然是你的崩溃的原因)

我认为您的问题可能是详细视图控制器保留对NSManagedObject的引用,其基础数据通过网络调用从数据存储中删除(similar issue

一个建议是不要在细节中保留对NSManagedObject本身的引用,而是保留与之比较的关键属性。

另一个想法是让你的getData返回" isitNew"值。该函数将知道是否创建了新的核心数据条目。

但我保持最佳解决方案(在我看来)。您可以使用NSFetchedResultsController来检测更改。将您的详细信息视图设置为NSFetchedResultsControllerDelegate。 Apple文档实际上包含了如何执行此操作的一个很好的示例。

最后一个解决方案的优点是你可以摆脱闭包,并将数据与数据的任何变化分离。当您需要扩展应用程序并引入其他更改源时,这可能有用。此来源可能不知道您的详细视图控制器,也可能不知道它。