我正在构建一个具有“播放列表”功能的应用程序。用户可以创建新的空播放列表,然后向其中添加内容。
我决定使用 Core Data 来做到这一点。所以我做了一些研究并创建了这个对象模型:
其中话语实体表示播放列表中的项目。
我用来显示播放列表的 View Controller 是 UITableViewController
。这是类(class)的一部分:
var playlists: [Playlists] = []
let dataContext: NSManagedObjectContext! = (UIApplication.sharedApplication().delegate as? AppDelegate)?.managedObjectContext
override func viewDidLoad() {
if dataContext != nil {
let entity = NSEntityDescription.entityForName("Playlist", inManagedObjectContext: dataContext)
let request = NSFetchRequest()
request.entity = entity
let playlists = try? dataContext.executeFetchRequest(request)
if playlists != nil {
for item in playlists! {
self.playlists.append(item as! Playlists)
print((item as! Playlists).name)
}
}
}
}
Playlists
是 Xcode 生成的 NSManagedObject
子类。在 viewDidLoad
中,我获取所有播放列表并将它们放入 self.playlists
中。另请注意,tableView
已正确实现。
现在我正在编写用户点击添加播放列表按钮时的操作方法。我想显示一个警告,询问用户播放列表的名称。如果他/她没有输入任何内容,将显示failAlert
。否则,我创建一个新的 Playlist
对象并将其名称设置为文本字段的文本并将其保存在数据库中。这是代码:
@IBAction func addPlaylist(sender: UIBarButtonItem) {
let alert = UIAlertController(title: "新播放列表", message: "请输入播放列表的名字", preferredStyle: .Alert)
alert.addTextFieldWithConfigurationHandler({ (textField) -> Void in
textField.placeholder = "名字"
})
alert.addAction(UIAlertAction(title: "确定", style: .Default, handler: { (action) -> Void in
if alert.textFields?.first?.text == "" || alert.textFields?.first?.text == nil {
let failAlert = UIAlertController(title: "失败", message: "播放列表名不能为空", preferredStyle: .Alert)
failAlert.addAction(UIAlertAction(title: "确定", style: .Default, handler: nil))
self.presentViewController(failAlert, animated: true, completion: nil)
return
}
let newPlaylist = Playlists(entity: NSEntityDescription.entityForName("Playlist", inManagedObjectContext: self.dataContext)!, insertIntoManagedObjectContext: self.dataContext)
newPlaylist.name = alert.textFields?.first?.text
if let _ = try? self.dataContext.save() {
print("Error occured")
}
self.tableView.reloadData()
}))
self.presentViewController(alert, animated: true, completion: nil)
}
如你所见,我是这样写的:
newPlaylist.name = alert.textFields?.first?.text
if let _ = try? self.dataContext.save() {
print("Error occured")
}
self.tableView.reloadData()
所以如果在保存过程中发生错误,它会打印Error occurred
。当我通过单击添加播放列表按钮测试应用程序时,它要求我提供播放列表的名称。所以我输入了一些随机字母,例如 ggg
,不幸的是它打印出 Error occurred
!此外,表格 View 仍然是空的。
我真的不明白为什么,以为数据没有保存。但是当我再次运行该应用程序时,我在 TableView 中看到了 ggg
!这太奇怪了!发生错误但保存数据成功!为什么是这样?错误是什么?
编辑:
很多答案都说 save
返回一个 Bool
。但是 Xcode 说它没有:
那分明是Void
这个词!
最佳答案
NSManagedObject
的save:
方法 returns a boolean :
Return Value
YES if the save succeeds, otherwise NO.
因此,if let
语句不是正确的方法,因为即使保存成功,该方法也总是会返回一些东西( bool 值),导致 if 中的语句
运行。
您应该通过 do-catch 语句使用 Swift 的错误处理功能:
do {
try self.dataContext.save()
} catch let error as NSError {
print("Error: \(error)")
}
More about error handling in Swift 2.0
但这只能解决您的保存问题,而不能解决新对象在您重新启动应用程序之前不会出现的问题。要解决此问题,您需要查看重新加载数据的方式。
现在,您正在调用 self.tableView.reloadData()
,除了您包含的代码显示您正在从 viewDidLoad
中的数据库中获取对象。鉴于 viewDidLoad
仅在首次加载 View 时调用,您添加的新对象将不会包含在 self.playlists
数组中。
您应该在保存后立即将新播放列表添加到 addPlaylist
函数中的 self.playlists
:
self.playlists.append(item as! Playlists)
关于ios - 为什么我存入CoreData会出错?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35110679/