刷新会给出错误,即在解开可选值时#34;找到nil;#34;

时间:2016-02-26 01:04:40

标签: ios xcode swift uitableview watchkit

我已将此getCloudKit功能从ViewController.swift移至Lay.swift,因此我可以将所有内容保存在一个班级中。

var objects = [Lay]()

override func viewDidLoad() {
    super.viewDidLoad()

    self.refreshControl?.addTarget(self, action: "handleRefresh:", forControlEvents: UIControlEvents.ValueChanged)
    self.getCloudKit()
}

func handleRefresh(refreshControl: UIRefreshControl) {

    self.objects.removeAll()
    self.getCloudKit()
}

func getCloudKit() {

    let now = NSDate()
    let predicate = NSPredicate(format: "TimeDate > %@", now)
    let sort = NSSortDescriptor(key: "TimeDate", ascending: true)

    let container = CKContainer.defaultContainer()
    let publicData = container.publicCloudDatabase

    let query = CKQuery(recordType: “lay”, predicate: predicate)
    query.sortDescriptors = [sort]
    publicData.performQuery(query, inZoneWithID: nil) { results, error in
        if error == nil { 
            for lay in results! {
                let newlay = Lay()

                newLay.tColor = lay["tColor"] as! String
                newLay.timeDate = lay["TimeDate"] as! AnyObject
                newLay.matchup = lay["Matchup"] as! String

                let applicationDict = ["tColor" : newLay.tColor, "Matchup" : newLay.matchup]
                let transfer = WCSession.defaultSession().transferUserInfo(applicationDict)

                self.objects.append(newLay)
            }

            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                self.refreshControl!.endRefreshing()
                self.tableView.reloadData()
            })

        } else {
            print(error)
        }
    }

}

问题是我移动它(以及必要的相关代码):

  • Lay.swift上的TableViewController().refreshControl!.endRefreshing() 错误 说"致命错误:在解开时意外地发现了零 可选值"
  • 当我尝试
  • 时,需要将WCSession: transferUserInfo中的 getCloudKit代码放入AppDelegate.swift,但不断出现错误

ViewController.swift

override func viewDidLoad() {
    super.viewDidLoad()

    self.refreshControl?.addTarget(self, action: "handleRefresh:", forControlEvents: UIControlEvents.ValueChanged)
    Lay().getCloudKit()
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete implementation, return the number of rows
    return Lay().objects.count
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath)

    let object = Lay().objects[indexPath.row];
    if let label = cell.textLabel{
        label.text = object.matchup
    }

    return cell
}

func handleRefresh(refreshControl: UIRefreshControl) {
    Lay().objects.removeAll()
    Lay().getCloudKit()
}

Lay.swift

  var objects = [Lay]()


func getCloudKit() {

    let now = NSDate()
    let predicate = NSPredicate(format: "TimeDate > %@", now)
    let sort = NSSortDescriptor(key: "TimeDate", ascending: true)

    let container = CKContainer.defaultContainer()
    let publicData = container.publicCloudDatabase

    let query = CKQuery(recordType: “lay”, predicate: predicate)
    query.sortDescriptors = [sort]
    publicData.performQuery(query, inZoneWithID: nil) { results, error in
        if error == nil { 
            for lay in results! {
                let newlay = Lay()

                newLay.tColor = lay["tColor"] as! String
                newLay.timeDate = lay["TimeDate"] as! AnyObject
                newLay.matchup = lay["Matchup"] as! String

                let applicationDict = ["tColor" : newlay.tColor, "Matchup" : newlay.matchup]
                let transfer = WCSession.defaultSession().transferUserInfo(applicationDict)

                self.objects.append(newlay)
            }

            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                TableViewController().refreshControl!.endRefreshing()
                TableViewController().tableView.reloadData()
            })

        } else {
            print(error)
        }
    }

AppDelegate

private func setupWatchConnectivity() {
    if WCSession.isSupported() {
        let session = WCSession.defaultSession()
        session.delegate = self
        session.activateSession()
    }
}


private func sendUpdatedDataToWatch(notification: NSNotification) {
    if WCSession.isSupported() {
        let session = WCSession.defaultSession()
        if session.watchAppInstalled
        {
                let applicationDict = ["TColor" : Lay().tColor, "Matchup" : Lay().matchup]
                let transfer = WCSession.defaultSession().transferUserInfo(applicationDict)
                NSLog("Transfer AppDelegate: %@", transfer)
                NSLog("Trans AppDelegate: %@", applicationDict)

                session.transferCurrentComplicationUserInfo(applicationDict)
        }
    }
}

1 个答案:

答案 0 :(得分:3)

您的代码始终包含ViewController()Lay()。这将创建这些对象的新实例。因此,尽管refreshControl在您的实际视图控制器中是非零的,但在新创建的控制器中它将为零。

通过拆分getCloudKit功能,您可以让视图控制器只管理视图,而新类只需管理Cloud Kit。这很好,所以理想情况下,您的Cloud Kit控制器不应该对视图控制器有任何了解。因此,getCloudKit不应该调用reloadData。相反,您可以将一个闭包传递给在查询完成时调用的getCloudKit。有点像:

    func getCloudKit(completion completionHandler: (([Lay]) -> Void)?) {
         ...
         publicData.performQuery(query, inZoneWithID: nil) { results, error in
            if error == nil { 
                ...
                if let completion = completionHandler {
                    completion(self.objects)
                }
            } else {
                print(error)
         }
    }

然后在ViewController中:

    let layCloudKit = LayCloudKit()
    layCloudKit.getCloudKit(completion: { (objects) -> Void in
        dispatch_async(dispatch_get_main_queue(), {
            self.objects = objects
            self.refreshControl!.endRefreshing()
            self.tableView.reloadData()
        })
    })

请注意,我假设您将Lay Cloud Kit控制器放入单独的Swift文件中,因为Lay模型类不需要了解Cloud Kit。如果你想把它放在与Lay相同的文件中,那么你应该将func标记为staticclass,因为你不想创建一个假的实例来调用{{ 1}}。在这种情况下,您可以使用getCloudKit调用它(即指定Lay类,而不是Lay实例)。