iOS 8 Swift:使用 segue 编辑 NSManagedObject:声明类型时出错
Posted
技术标签:
【中文标题】iOS 8 Swift:使用 segue 编辑 NSManagedObject:声明类型时出错【英文标题】:iOS 8 Swift: editing NSManagedObject with segue: error when declaring types 【发布时间】:2015-04-18 00:01:27 【问题描述】:所以我在思考如何在 Core Data 中编辑/更新对象时遇到了一些麻烦。
我想要做的是在我的DetailViewController
中有两个 segues 推送到我的AddTableViewController
。
DetailViewController
:
import UIKit
import Social
import CoreData
class DetailViewController: UIViewController, UITableViewDataSource, UITableViewDelegate
@IBOutlet var backpackerSpotImageView:UIImageView!
@IBOutlet var tableView:UITableView!
var backpackerSpot:BackpackerSpot?
var managedContext: NSManagedObjectContext!
var backpackerSpots:[BackpackerSpot] = []
var fetchResultController:NSFetchedResultsController!
override func viewDidLoad()
super.viewDidLoad()
// customizing background of tableview
self.tableView.backgroundColor = UIColor(red: 240.0/255.0, green: 240.0/255.0, blue: 240.0/255.0, alpha: 0.2)
// remove extra separators
self.tableView.tableFooterView = UIView(frame: CGRectZero)
// change the color of the separator
self.tableView.separatorColor = UIColor(red: 240.0/255.0, green: 240.0/255.0, blue: 240.0/255.0, alpha: 0.8)
// self-sizing cells
tableView.estimatedRowHeight = 36.0
tableView.rowHeight = UITableViewAutomaticDimension
// Do any additional setup after loading the view.
if let spotImage = backpackerSpot?.spotImage
self.backpackerSpotImageView.image = UIImage(data:spotImage)
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return 4
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! DetailTableViewCell
// make cell transparent so background color can be seen
cell.backgroundColor = UIColor.clearColor()
cell.mapButton.hidden = true
switch indexPath.row
case 0:
cell.fieldLabel.text = "Name"
cell.valueLabel.text = backpackerSpot?.spotName
case 1:
cell.fieldLabel.text = "Location"
cell.valueLabel.text = backpackerSpot?.spotLocation
cell.mapButton.hidden = false
case 2:
cell.fieldLabel.text = "Notes"
cell.valueLabel.text = backpackerSpot?.spotNote
default:
cell.fieldLabel.text = ""
cell.valueLabel.text = ""
return cell
// func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool
// return true
//
//
// func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath)
// if(editingStyle == .Delete)
// // Find the BackPacker Spot object the user is trying to delete
// let backpackerSpotToDelete = backpackerSpots[indexPath.row]
//
// // Delete it from the managedObjectContext
// managedContext?.deleteObject(backpackerSpotToDelete)
//
// reloadInputViews()
//
//
//
//
@IBAction func shareSheet(sender:UIBarButtonItem)
let firstActivityItem = backpackerSpot!.spotName
let secondActivityItem = backpackerSpot!.spotLocation
let activityViewController : UIActivityViewController = UIActivityViewController(
activityItems: [firstActivityItem, secondActivityItem], applicationActivities: nil)
activityViewController.excludedActivityTypes = [
UIActivityTypePostToVimeo,
UIActivityTypePostToTencentWeibo,
UIActivityTypePostToFlickr,
UIActivityTypePostToWeibo,
UIActivityTypeSaveToCameraRoll,
UIActivityTypePrint,
UIActivityTypeAssignToContact,
UIActivityTypeAddToReadingList
]
self.presentViewController(activityViewController, animated: true, completion: nil)
// MARK: - Navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
if segue.identifier == "showMap"
let destinationController = segue.destinationViewController as! MapViewController
destinationController.backpackerSpot = backpackerSpot
else if segue.identifier == "editSpot"
var selectedItem: NSManagedObject = backpackerSpot!
let destinationController = segue.destinationViewController as! AddTableViewController
destinationController.existingName = selectedItem.valueForKey("spotName") as! String
destinationController.existingLocation = selectedItem.valueForKey("spotLocation") as! String
destinationController.existingNotes = selectedItem.valueForKey("spotNote") as! String
destinationController.existingImage = selectedItem.valueForKey("spotImage") as! NSData
destinationController.existingSpot = selectedItem
destinationController.backpackerSpot = backpackerSpot
AddTableViewController:
import UIKit
import CoreData
class AddTableViewController: UITableViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate
@IBOutlet weak var nameTextField:UITextField!
@IBOutlet weak var locationTextField:UITextField!
@IBOutlet weak var imageView:UIImageView!
@IBOutlet weak var notesView:UITextView!
var existingName:String = ""
var existingLocation:String = ""
var existingNotes:String = ""
var existingImage:NSData!
var existingSpot: NSManagedObject!
var coreDataStack = (UIApplication.sharedApplication().delegate as! AppDelegate).coreDataStack
var backpackerSpot:BackpackerSpot!
var managedContext: NSManagedObjectContext!
override func viewDidLoad()
super.viewDidLoad()
managedContext = coreDataStack.context
if (existingSpot != nil)
nameTextField.text = existingName
locationTextField.text = existingLocation
imageView.image = existingImage
notesView.text = existingNotes
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
// TODO Give user the choice of the Photo Library or the Camera
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
if indexPath.row == 0
if UIImagePickerController.isSourceTypeAvailable(.Camera)
let imagePicker = UIImagePickerController()
imagePicker.allowsEditing = false
imagePicker.delegate = self
imagePicker.sourceType = .Camera
self.presentViewController(imagePicker, animated: true, completion: nil)
tableView.deselectRowAtIndexPath(indexPath, animated: true)
// FIXME image is being displayed in landscape if it is taken in portrait mode by default
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!)
imageView.image = image
imageView.contentMode = UIViewContentMode.ScaleAspectFill
imageView.clipsToBounds = true
dismissViewControllerAnimated(true, completion: nil)
@IBAction func save()
//validation
var errorField = ""
// TODO have placeholder text in the NOTES field match up with the placholder text in the NAME and LOCATION fields.
if nameTextField.text == ""
errorField = "name"
else if locationTextField.text == ""
errorField = "location"
else if notesView.text == ""
errorField = "notes"
if errorField != ""
let alertController = UIAlertController(title: "Error", message: "You must fill in \(errorField).", preferredStyle: .Alert)
let doneAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
alertController.addAction(doneAction)
self.presentViewController(alertController, animated: true, completion: nil)
return
// If all fields are correctly filled in, extract the field value
// Create Restaurant Object and save to data store
// if let managedObjectContext = (UIApplication.sharedApplication().delegate as AppDelegate).coreDataStack.context
let entityBackpackerSpot = NSEntityDescription.entityForName("BackpackerSpot", inManagedObjectContext: coreDataStack.context)
backpackerSpot = BackpackerSpot( entity: entityBackpackerSpot!, insertIntoManagedObjectContext: managedContext )
backpackerSpot?.spotName = nameTextField.text
backpackerSpot?.spotLocation = locationTextField.text
backpackerSpot?.spotImage = UIImagePNGRepresentation(imageView.image)
backpackerSpot?.spotNote = notesView.text
var error: NSError?
if !managedContext.save(&error)
println("insert error: \(error!.localizedDescription)")
return
// Execute the unwind segue and go back to the home screen
performSegueWithIdentifier("unwindToHomeScreen", sender: self)
我知道我还没有必要的功能来编辑我的AddTableViewController
中的数据,但我遇到的第一个问题甚至是传递数据。我目前收到以下错误:
AddTableViewController.swift:38:31: Cannot assign a value of type 'NSData!' to a value of type 'UIImage?'
我尝试将相同的变量强制转换为 UIImage
,但这也给了我一个错误(这是我所预料的)。
我是在正确的轨道上,还是应该以完全不同的方式编辑/更新对象?我已经使用 CoreData 工作了几个星期,并且开始掌握它的窍门,但正如我之前所说,我无法完全解决传递数据的问题。
感谢任何帮助。谢谢。
【问题讨论】:
【参考方案1】:你需要先用你的 NSData 创建 UIImage,试试:
if (existingSpot != nil)
nameTextField.text = existingName
locationTextField.text = existingLocation
imageView.image = UIImage(data: existingImage)
notesView.text = existingNotes
【讨论】:
谢谢。做到了:)。以上是关于iOS 8 Swift:使用 segue 编辑 NSManagedObject:声明类型时出错的主要内容,如果未能解决你的问题,请参考以下文章
准备使用数组进行 Segue - Xcode 8.0 Swift 3.0
如何使用 Swift 在 iOS 中以编程方式进行 segue
无法使用 Xcode 8 和 Swift 3 在 SpriteKit 中以编程方式触发 segue
iOS Swift 使用 Segue 在 viewController 之间传递变量