我正在使用Swift和SQLite.swift。我有以下 UIViewController :
class LoginViewController: UIViewController {
@IBOutlet weak var emailField: UITextField!
func setEmailAddress(email:String){
emailField.text = email
}
override func viewDidLoad() {
MySQLite().updateLatestEmailAddressFromUserTable() // breaks here (email is in console, though...)
}
}
然后我试图从另一个类更新它的值(通过setEmailAddress函数):
class MySQLite {
func updateLatestEmailAddressFromUserTable(){
let dbPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as String
let db = Database("\(dbPath)/db.sqlite3")
let users = db["users"]
let id = Expression<Int>("id")
let email = Expression<String>("email")
let time = Expression<Int>("time")
for user in users.limit(1).order(time.desc) {
println(user[email]) // this works, correctly outputs in console: email@domain.com
LoginViewController().setEmailAddress(user[email]) // breaks here
}
}
}
上面的代码给出了以下错误
fatal error: unexpectedly found nil while unwrapping an Optional value
进一步解释:我正在检索SQLite表中的最新条目以获取用户的电子邮件地址并更新登录视图控制器中的文本字段。这样可以更轻松地登录返回用户。
我一直在努力争取这个超过2个小时并尝试各种各样的事情。 主要问题我认为,当我尝试简单地从第二个函数返回电子邮件地址作为字符串并直接从LoginViewController设置字段时,它不起作用(SQLite相关代码不是&#34;执行&#34;但我相信)。
可能相关的线程(Obj-C): set UITextField.text from another class
答案 0 :(得分:2)
确保已在屏幕上实例化具有emailField的视图。
@IBOutlet weak var emailField: UITextField!
这是一个可选项,在加载故事板或nib之前将为nil。我假设OnBoardingRegistrationFormController是您的LoginViewController类的一个实例?
我看到你已经接受了答案,但在这种情况下,创建一个协议可能有点过分。如果sqlite是你的模型,为什么不让函数返回一个值,然后你可以将值赋给控制器中的文本字段。离。
class LoginViewController: UIViewController {
@IBOutlet weak var emailField: UITextField!
override func viewDidLoad() {
emailField.text = MySQLite().updateLatestEmailAddressFromUserTable()
}
}
class MySQLite {
func updateLatestEmailAddressFromUserTable() -> String{
let dbPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as String
let db = Database("\(dbPath)/db.sqlite3")
let users = db["users"]
let id = Expression<Int>("id")
let email = Expression<String>("email")
let time = Expression<Int>("time")
for user in users.limit(1).order(time.desc) {
println(user[email]) // this works, correctly outputs in console: email@domain.com
return user[email]
}
}
}
答案 1 :(得分:1)
这里发生的LoginViewController().setEmailAddress(user[email])
创建了LoginViewController
的新实例,它与您当前的LoginViewController不同。
为什么不在MySQLite中制作协议并定义为委托
LoginViewController将实现更新方法。将委托传递给MySqlite
在MySQLite中,当您获取值表单数据库时,请调用委托更新方法。
实施例
MySQLite
protocol loginDelegate
{
func update(NSString)
}
class MySQLite {
var delegate:loginDelegate?
func updateLatestEmailAddressFromUserTable(){
let dbPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as String
let db = Database("\(dbPath)/db.sqlite3")
let users = db["users"]
let id = Expression<Int>("id")
let email = Expression<String>("email")
let time = Expression<Int>("time")
for user in users.limit(1).order(time.desc) {
println(user[email]) // this works, correctly outputs in console: email@domain.com
if((delegate) != nil)
{
delegate?.update("example@example.com")
}
}
}
}
class LoginViewController: UIViewController,loginDelegate {
@IBOutlet weak var emailField: UITextField!
func setEmailAddress(email:String){
emailField.text = email
}
override func viewDidLoad() {
var mySQLite: MySQLite=LoginClass();
mySQLite.delegate=self;
[mySQLite .updateLatestEmailAddressFromUserTable()];
}
func update(email: NSString) {
println(email);
emailField.text = email
}
}
答案 2 :(得分:0)
问题是,当您尝试将文本分配给textField时,未加载LoginViewController
的视图。即:emailField
为零并且展开nil值会导致运行时崩溃(因为插座尚未连接到它的storyboard / xib对应部分)。