如何只为单元格内的某些视图提供值,同时留下一些零而不崩溃?
Posted
技术标签:
【中文标题】如何只为单元格内的某些视图提供值,同时留下一些零而不崩溃?【英文标题】:How to provide values for only certain views inside a cell while leaving some nil and not crash? 【发布时间】:2017-03-31 14:26:05 【问题描述】:我有一个包含一些令人困惑的规范的课程。我需要编写一个应用程序来存储有关用户消费的食物的详细信息。我已经完成了所有这些,我将条目存储在一个核心数据实体中,并将它们显示在一个表中。问题在于,在用户可以提供的 6 条不同信息中,只有 3 条是强制性的(餐点名称、日期和时间以及食物组)。其他 3 个(照片、用餐类型和用户 ID)他可以跳过。我在核心数据中的所有属性都是可选的。当我完成所有字段时,它工作得很好。一旦我将不必要的 3 设置为 nil,我就会得到一个致命错误(在展开可选时发现 nil)。有人可以帮忙解决这个问题吗?谢谢你。代码清单如下。
@IBAction func saveUserInput(_ sender: UIButton)
let userMeals = UserMeals(context: managedObjectContext!)
if (mealName.text?.isEmpty)! || (foodGroup.text?.isEmpty)! || (dateAndTimeOfMeal.text?.isEmpty)!
let screenAlert = UIAlertController(title: "Warning!", message: "You must enter at least the name of the meal, the date and time, and the group!", preferredStyle: .alert)
screenAlert.addAction(UIAlertAction(title: "Got it!", style: .default, handler: nil))
self.present(screenAlert, animated: true, completion: nil)
else if photoView?.image == nil || (mealType.text?.isEmpty)! || (userName.text?.isEmpty)!
userMeals.mealPhoto = nil
userMeals.mealType = nil
userMeals.userID = nil
let screenNotification = UIAlertController(title: "Done!", message: "Your meal has been saved without a photo, meal type and user name!", preferredStyle: .alert)
screenNotification.addAction(UIAlertAction(title: "Got it!", style: .default, handler: nil))
self.present(screenNotification, animated: true, completion: nil)
else
userMeals.mealPhoto = NSData(data: UIImageJPEGRepresentation((photoView?.image)!, 0.5)!)
userMeals.mealName = mealName?.text
userMeals.foodGroup = foodGroup?.text
userMeals.dateAndTime = dateAndTimeOfMeal?.text
userMeals.mealType = mealType?.text
userMeals.userID = userName?.text
let screenNotification = UIAlertController(title: "Done!", message: "Your meal has been saved!", preferredStyle: .alert)
screenNotification.addAction(UIAlertAction(title: "Got it!", style: .default, handler: nil))
self.present(screenNotification, animated: true, completion: nil)
表格视图类的代码:
private func loadData()
let mealRequest: NSFetchRequest<UserMeals> = UserMeals.fetchRequest() // get all information from core, of type guardian.
do
storedMeals = try managedObjectContext.fetch(mealRequest)
catch
print("could not load data from core \(error.localizedDescription)") // get more details from the error.
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int
return 1
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return storedMeals.count
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "cellForMeal", for: indexPath) as! ViewMealsCell
let mealItem = storedMeals[indexPath.row]
if let mealImage = UIImage(data: mealItem.mealPhoto as! Data)
cell.mealPhoto.image = mealImage
cell.mealName.text = mealItem.mealName
cell.foodGroup.text = mealItem.foodGroup
cell.dateAndTime.text = mealItem.dateAndTime
cell.mealType.text = mealItem.mealType
cell.userName.text = mealItem.userID
return cell
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool
return true
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath)
if editingStyle == .delete // delete the row from the data source
tableView.deleteRows(at: [indexPath], with: .fade)
self.tableView.reloadData()
用户餐的定义:
extension UserMeals
@nonobjc public class func fetchRequest() -> NSFetchRequest<UserMeals>
return NSFetchRequest<UserMeals>(entityName: "UserMeals");
@NSManaged public var dateAndTime: String?
@NSManaged public var foodGroup: String?
@NSManaged public var mealName: String?
@NSManaged public var mealPhoto: NSData?
@NSManaged public var mealType: String?
@NSManaged public var userID: String?
【问题讨论】:
我用 UserMeals 定义编辑了代码清单 我添加了一张包含崩溃细节的照片 我在问问题之前已经完成了 if let ......结果是一样的...... 现在就可以了。谢谢您的宝贵时间 我在调试器中得到了一个循环。我在所有 3 个数据源函数中都加了点。当我按步进入或继续程序执行时,它会循环节数和节中的行数,但不会进入索引路径处的行的单元格。它只是向我显示带有十六进制值的页面。请给我一秒钟重做调试 【参考方案1】:问题出在这一行:
if let mealImage = UIImage(data: mealItem.mealPhoto as! Data)
cell.mealPhoto.image = mealImage
只要你有一个感叹号,你就是在说“请让我崩溃”。如果运行时完全按照您的要求执行,您就不能抱怨。
你想在这里使用as?
。这将安全地展开。
可能需要进行额外的安全展开,但一般来说,这是您想要采用的方法。例如,你可能会这样写:
if let data = mailItem.mealPhoto as? Data
cell.mealPhoto.image = UIImage(data:data)
通过这种方式,我们首先将mealPhoto
安全解包到一个数据中,然后从该数据安全地创建图像。您需要分两步执行此操作,因为您不能使用 Data?
参数调用 UIImage(data:)
;你必须先打开Data
。
EDIT 正如 cmets 中正确指出的那样,我们需要为 每一 行设置image
,而不仅仅是我们拥有数据的行。因此,将上述内容扩展为以下内容:
if let data = mailItem.mealPhoto as? Data
cell.mealPhoto.image = UIImage(data:data)
else
cell.mealPhoto.image = nil
通过这种方式,我们删除了我们没有图像数据的重复使用表行的图像。
【讨论】:
但是 - 当你没有返回有效数据时,使用这个检查作为一个机会来提供一个默认图像 - 否则你最终会显示上一次可重复使用单元格的 mealPhoto如果 let data = mailItem.mealPhoto 显示为?数据 cell.mealPhoto.image = UIImage(data:data) else cell.mealPhoto.image = mealPhotoDefaultImage @Russell 非常好。我将添加nil
作为替代。 — 当我写下我的答案时,我专注于崩溃和展开,而不是这是一张桌子这一事实。 :)以上是关于如何只为单元格内的某些视图提供值,同时留下一些零而不崩溃?的主要内容,如果未能解决你的问题,请参考以下文章
如何从表格视图的自定义单元格内的文本字段中获取值(标签)以发布到 URL [重复]