Search code examples
iosxcodeswiftparse-platform

Cannot assign a value of type 'PFObject' to a value of 'PFObject!', Swift, Xcode


Xcode 6.3.1: Error: Cannot assign a value of type 'PFObject' to a value of 'PFObject!'

Trying to understand the stricter Swift '!' and '?' requirements, as I feel that's the main cause of the error.

Issues are with the following line of the code below:

detailScene.currentObject = objects[row] as! PFObject

Within:

import UIKit

class TeamsViewController: PFQueryTableViewController {

    // Initialise the PFQueryTable tableview
    override init(style: UITableViewStyle, className: String!) {
        super.init(style: style, className: className)
    }

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    // Configure the PFQueryTableView
    self.parseClassName = "Teams"
    self.textKey = "teamName"
    self.pullToRefreshEnabled = true
    self.paginationEnabled = false
}

// Define the query that will provide the data for the table view
override func queryForTable() -> PFQuery {
    var query = PFQuery(className: "Teams")
    query.orderByAscending("teamName")
    return query
}

// MARK: - Table view data source

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject!) -> PFTableViewCell {

    var cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! PFTableViewCell!
    if cell == nil {
        cell = PFTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
    }

    // Extract values from the PFObject to display in the table cell
    if let teamName = object["teamName"] as? String {
        cell?.textLabel?.text = teamName
    }

    if let coachName = object["coachName"] as? String {
        cell?.detailTextLabel?.text = coachName
    }

    return cell
}

// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    // Get the new view controller using [segue destinationViewController].
    var detailScene = segue.destinationViewController as! AddTeamsViewController

    // Pass the selected object to the destination view controller.
    if let indexPath = self.tableView.indexPathForSelectedRow() {
        let row = Int(indexPath.row)
        detailScene.currentObject = objects[row] as! PFObject
    }
}

override func viewDidAppear(animated: Bool) {

    // Refresh the table to ensure any data changes are displayed
    tableView.reloadData()
}

// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {

}

// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    // Return NO if you do not want the item to be re-orderable.
    return true
    }

}

Any direction on why I get an error there and how to fix it will be appreciated. Thank you


Solution

  • You need to force unwrap the objects Array because it's an optional Array of anyobjects ([AnyObject]?)

    So your code should look like this:

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
            // Pass the selected object to the destination view controller.
            if let indexPath = self.tableView.indexPathForSelectedRow() {
                let row = indexPath.row
                detailScene.currentObject = objects![row] as! PFObject
            }
    
        }
    

    The saver way to unwrap is:

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
            // Pass the selected object to the destination view controller.
            if let indexPath = self.tableView.indexPathForSelectedRow() {
                let row = indexPath.row
                if let unwrappedobjects = objects {
                    if let yourobject = unwrappedobjects[row] as? PFObject {
                        detailScene.currentObject = yourobject
                    }
                }
            }
    
        }