首先,我是快速编程的新手,对很多事情我也不是很清楚,因此我遵循指南来确保我的应用程序可以正常工作。
基本上,我一直遵循(https://www.brianadvent.com/build-simple-core-data-driven-ios-app/)上的指南来构建简单的核心数据驱动的iOS应用。我完全遵循了代码,并且可以正常工作。但是,我不得不对该应用程序进行更多改进,这就是问题所在。
基本上,在指南中,将项目加载到核心数据和tableview中都存在于同一视图控制器中。在我的新应用中,我希望用户输入以相同方式存储在核心数据中的字符串,并让Tableview在另一个View Controller上显示输入的数据。很快,我意识到您不能从不同的视图控制器调用变量和函数,因此我认为在第二个视图控制器中创建新变量和moc应该不是什么大问题。
这是我到目前为止尝试过的。我将所有内容都保留在代码中,因为我担心那可能是错误所在。
第一个视图控制器(数据存储在核心数据中:
from unittest.mock import patch
from a import A,foo
def my_wrapper(*args, **kwargs):
return A('b')
def bar():
with patch('a.A', my_wrapper):
foo()
第二个viewController(表视图所在的位置):
import UIKit
import CoreData
class ViewController: UIViewController {
//name of entity = Alarm
var alarmItems = [Alarm]() // array of alarm items called alarmItems
var moc: NSManagedObjectContext!
let appDelegate = UIApplication.shared.delegate as? AppDelegate
@IBOutlet weak var engineerName: UITextField!
@IBOutlet weak var dateTimeOfAlarm: UITextField!
@IBOutlet weak var trueFalseAlarmSelector: UISwitch!
@IBOutlet weak var engineerComments: UITextField!
//saving alarm attributes into coredata
@IBOutlet weak var submitButton: UIStackView!
override func viewDidLoad() {
super.viewDidLoad()
engineerName.delegate = (self as UITextFieldDelegate)
dateTimeOfAlarm.delegate = (self as UITextFieldDelegate)
//trueFalseAlarmSelector.delegate = self
moc = appDelegate?.persistentContainer.viewContext
// Do any additional setup after loading the view.
loadData()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?){
engineerName.resignFirstResponder()
dateTimeOfAlarm.resignFirstResponder()
}
@IBAction func dateTimeOfAlarmEdit(_ sender: UITextField) {
let datePickerView = UIDatePicker()
datePickerView.datePickerMode = .dateAndTime
sender.inputView = datePickerView
datePickerView.addTarget(self, action: #selector(handleDatePicker(sender:)), for: .valueChanged)
}
@objc func handleDatePicker(sender: UIDatePicker) {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd MMM yyyy HH:mm"
dateTimeOfAlarm.text = dateFormatter.string(from: sender.date)
}
//sending the attributes to the coredata
@IBAction func submitAlarmAttributes(_ sender: UIButton) {
let alarmItem = Alarm(context: moc)
//true/false button checker
if trueFalseAlarmSelector.isOn {
alarmItem.trueOrFalseAlarm = true
} else {
alarmItem.trueOrFalseAlarm = false
}
alarmItem.nameOfEngineer = engineerName.text
alarmItem.dateTimeOfAlarm = dateTimeOfAlarm.text
alarmItem.engineerComments = engineerComments.text
appDelegate?.saveContext()
loadData()
}
//loadData will update the alarmItems array with the new and most current data from the database.
func loadData(){
let alarmRequest:NSFetchRequest<Alarm> = Alarm.fetchRequest()
let sortDescriptor = NSSortDescriptor(key: "dateTimeOfAlarm", ascending: false)
alarmRequest.sortDescriptors = [sortDescriptor]
do{try alarmItems=moc.fetch(alarmRequest)
} catch {
print("Could not load data")
}
//self.tableView.reloadData()
}
}
extension ViewController : UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
第一个视图控制器没有任何错误消息。
但是,第二个视图控制器有很多问题。例如,在一开始,就出现此错误类型'SecondViewController'不符合协议'UITableViewDataSource'“。在某些行中有一些错误消息,显示为“源文件中的编辑器占位符”。还有一个“即使我确实有tableView,“ SecondViewController”类型的值也没有成员“ tableView””错误,最后,最后还有“使用未解析的标识符'cell'”。
非常感谢您的帮助,过去几天我一直在努力解决这个问题,我真的不知道还能做什么。
答案 0 :(得分:0)
我怀疑您所做的是在InterfaceBuilder中复制/粘贴以创建SecondViewController。
您使用的原始代码有一个名为tableView
的变量,该变量仍在InterfaceBuilder中引用。要解决此问题,请打开InterfaceBuilder并找到您的SecondViewController。如果尚未展开,请展开场景对象并选择SecondViewController,然后使用右侧的检查器显示“连接检查器”。您可能会发现带有感叹号的tableView
插座和另一个名为historyTable
的插座。只需删除tableView
参考,并确保您的historyTable
已正确链接。
关于“未解析的标识符单元格”,这是因为您未正确放置viewDidLoad
函数的右括号。由于未关闭函数,因此此后所有其他函数都将创建为viewDidLoad的局部函数,而不是SecondViewController的函数。要修复您的源代码,只需移除return cell
上方的括号,然后将其添加到self.historyTable.dataSource = self
(是的,当前您将其命名为self.tableView.dataSource
,但变量名为historyTable)。>