0

I have a UITableViewController that I have data. If you tap on the row, you can edit the existing data, if you tap on the + in the UIBarButtonItem, you add new infomation. When my Segue passes the Core Data Object (vc.managedObjectID) my "detail" view controller checks to see if the firstName field has data or no data.

In Objective-C, I would do something like this

- (void)refreshInterface
{
    CoreDataHelper *cdh = [CoreDataHelper sharedHelper];
    Cues *existingCues = (Cues*)[cdh.context existingObjectWithID:_cuesNSManagedObjectID error:nil];

    if (!existingCues.cuesName)
    {
        _cueNameTextField.text           = nil;
        self.cueDescriptionTextView.text = nil;
    }
    else
    {
        _cueNameTextField.text           = existingCues.cuesName;
        self.cueDescriptionTextView.text = existingCues.cuesDescription;
    }
}

I'm having a problem checking to see if there is any data in firstName: var firstName = playerInformation.firstName causes a EXC_BAD_ACCESS only when adding a new object (meaning playerInformatin is empty), when I tap to see existing data it returns the correct data. How do I check to see if playerInfomation is empty (new record) or has data (exisiting data) in Swift?

func refreshInterface(){

    if managedObjectID != nil {
        var playerInformation = managedObjectContext?.existingObjectWithID(managedObjectID!, error: nil) as? PlayerInformation

        var firstName = playerInformation!.firstName //EXC_BAD_ACCESS
        println("firstName \(firstName)")
    }
}

prepareForSegue

   override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

        if segue.identifier == "addPlayerInformationDetail" {

            println("addPlayerInformationDetail")

            let context = self.fetchedResultsController.managedObjectContext

            let entity  = self.fetchedResultsController.fetchRequest.entity

            let playerInformation = NSEntityDescription.insertNewObjectForEntityForName(entity.name, inManagedObjectContext: managedObjectContext!) as PlayerInformation?

            var vc  = segue.destinationViewController as PlayerInformationDetailTableViewController

            vc.managedObjectID = playerInformation?.objectID

        } else if segue.identifier == "editPlayerInformationDetail" {


            println("editPlayerInformationDetail")

            var indexPath:NSIndexPath = tableView.indexPathForSelectedRow()!

            var vc                    = segue.destinationViewController as PlayerInformationDetailTableViewController

            vc.managedObjectID        = self.fetchedResultsController.objectAtIndexPath(indexPath).objectID

        }
Bruno Franco
  • 2,028
  • 11
  • 20
Paul S.
  • 1,342
  • 4
  • 22
  • 43

2 Answers2

0

You can use a conditional let like so:

if let firstName = playerInformation?.firstName {
    println("firstName \(firstName)")
}

This will only unwrap the optional value if it isn't nil, avoiding the crash.

Greg
  • 9,068
  • 6
  • 49
  • 91
  • `if let firstName = playerInformation?.firstName { println("firstName \(firstName)") }` The `if` condition causes the EXC_BAD_ACCESS – Paul S. Oct 02 '14 at 12:45
  • @PaulS. Interesting. Try `if let p = playerInformation { var firstName = p.firstName println("firstName \(firstName)") }` – Greg Oct 02 '14 at 12:48
  • EXC_BAD_ACCESS on the `var firstname` line. It might be worth nothing that in the Variables View (lower left hand debug pane) `firstName = (String) ""` – Paul S. Oct 02 '14 at 12:55
  • What's the declared type of `firstName`? Is it `NSString!`? – Greg Oct 02 '14 at 12:58
  • PlayerInformation is an NSManagedObject, firstName is a String. Again, when I run the app and select a UITableView cell that has data, even your suggested code works find, and the firstName is printed. – Paul S. Oct 02 '14 at 13:01
  • Try writing just `if playerInformation != nil`, your original code within the `if` statement. If that doesn't work, it's probably a Core Data bug with optional values, and we'll have to look for a workaround. – Greg Oct 02 '14 at 13:03
  • I tried the following: `var playerInformation = managedObjectContext?.existingObjectWithID(managedObjectID!, error: nil) as? PlayerInformation if playerInformation != nil { var firstName = playerInformation!.firstName //EXC_BAD_ACCESS println("firstName \(firstName)") }` same problem. – Paul S. Oct 02 '14 at 13:11
  • Do you get any error log output? Is the memory address shown by the exception 0x0, or an actual value? – Greg Oct 02 '14 at 13:14
  • Not sure if this is what you're asking: `EXC_BAD_ACCESS (code =1, address 0x0)` in the left hand pane, pretty much all the values are 0 – Paul S. Oct 02 '14 at 13:21
  • The problem appears to be that the non-optional `firstName` value is set to nil by Core Data. Changing the type of `firstName` in the declaration of the class to `String!` *might* fix this problem. You could also try removing the `!` from the code on the line where the exception occurs (if that even compiles). This looks like a bug in the Swift compiler or Core Data to me. – Greg Oct 02 '14 at 13:25
0

for some reason this works:

var playerInformation = managedObjectContext?.existingObjectWithID(managedObjectID!, error: nil)
var firstName: AnyObject? = playerInformation?.valueForKey("firstName")
println("firstName \(firstName)")

If I subclass the managedObjectContext as PlayerInformation, I would get EXC_BAD_ACCESS

Paul S.
  • 1,342
  • 4
  • 22
  • 43