У меня проблема с классом Swift. У меня есть быстрый файл для класса UITableViewController и класса UITableViewCell. Моя проблема - это класс UITableViewCell и выходы. Этот класс имеет ошибку Класс "HomeCell" не имеет инициализаторов, и я не понимаю эту проблему.
Спасибо за ваши ответы.
import Foundation
import UIKit
class HomeTable: UITableViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet var tableViex: UITableView!
var items: [(String, String, String)] = [
("Test", "123", "1.jpeg"),
("Test2", "236", "2.jpeg"),
("Test3", "678", "3.jpeg")
]
override func viewDidLoad() {
super.viewDidLoad()
var nib = UINib(nibName: "HomeCell", bundle: nil)
tableView.registerNib(nib, forCellReuseIdentifier: "bookCell")
}
// Number row
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.items.count
}
// Style Cell
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("bookCell") as UITableViewCell
// Style here
return cell
}
// Select row
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// Select
}
}
// PROBLEM HERE
class HomeCell : UITableViewCell {
@IBOutlet var imgBook: UIImageView
@IBOutlet var titleBook: UILabel
@IBOutlet var pageBook: UILabel
func loadItem(#title: String, page: String, image:String) {
titleBook.text = title
pageBook.text = page
imgBook.image = UIImage(named: image)
}
}
Вы должны использовать неявно развернутые опции, чтобы Swift в этом случае справлялся с круговыми зависимостями (parent ↔ дочерние элементы пользовательского интерфейса в этом случае).
@IBOutlet var imgBook: UIImageView!
@IBOutlet var titleBook: UILabel!
@IBOutlet var pageBook: UILabel!
Прочитайте это doc, они все это хорошо объясняют.
Быстрое исправление - убедитесь, что все переменные, которые не инициализируются при их создании (например, var num : Int?
vs var num = 5
), имеют либо ?
, либо !
.
Длинный ответ (рекомендуется) - читайте doc, как предполагает mprivat...
?
означает, что это может быть ноль, но если это так, то нет проблем с движением вперед и бездействием. !
означает, что если после распаковки было ноль, то сбой - оба они удовлетворяют требованию инициации - сообщая компилятору: я знаю / хочу, чтобы он начинал с нуля.
Это от Apple doc
Классы и структуры должны установить все свои сохраненные свойства в соответствующее начальное значение к моменту создания экземпляра этого класса или структуры. Сохраненные свойства не могут оставаться в неопределенном состоянии.
Вы получите сообщение об ошибке Класс "HomeCell" не имеет инициализаторов, потому что ваши переменные находятся в неопределенном состоянии. Либо вы создаете инициализаторы, либо вы делаете их необязательными типами, используя! или?
Мой ответ касается ошибки вообще, а не точного кода OP. Никакой ответ не упоминал эту заметку, поэтому я просто подумал, что добавляю ее.
В приведенном ниже коде также будет генерироваться ошибка той же:
class Actor {
let agent : String?
}
Другие отметили, что либо вы создаете инициализаторы, либо делаете их необязательными типами, используя! или? что правильно. Однако, если у вас есть необязательный элемент/свойство, этот необязательный параметр должен быть изменен, т.е. var
. Если вы сделаете let
, тогда он никогда не сможет выйти из состояния nil
. Это плохо!
Таким образом, правильный способ записи:
class Actor {
var agent : String? // it has a chance so its value can be set!
}
Или вы можете записать его как:
class Actor {
let agent : String?
init (agent: String?){
self.agent = agent // it has a chance so its value can be set!
}
}
или по умолчанию использовать любое значение (включая nil
, которое является глупым)
class Actor {
let agent : String? = nil // very useless, but doable.
let company: String? = "Universal"
}
Мой ответ касается ошибки вообще, а не точного кода OP. Никакой ответ не упоминал эту заметку, поэтому я просто подумал, что добавляю ее.
В приведенном ниже коде также будет генерироваться ошибка той же:
class Actor {
let agent : String? // BAD! // Its value is set to nil, and will always be nil and that stupid so Xcode is saying not-accepted.
// Technically speaking you have a way around it, you can help the compiler and enforce your value as a constant. See Option3
}
Другие отметили, что либо вы создаете инициализаторы, либо делаете их необязательными типами, используя! или? что правильно. Однако, если у вас есть необязательный элемент/свойство, этот необязательный параметр должен быть изменен, т.е. var
. Если вы сделаете let
, тогда он никогда не сможет выйти из состояния nil
. Это плохо!
Таким образом, правильный способ записи:
class Actor {
var agent : String? // It defaulted to `nil`, but also has a chance so it later can be set to something different || GOOD!
}
Или вы можете записать его как:
class Actor {
let agent : String? // It value isn't set to nil, but has an initializer || GOOD!
init (agent: String?){
self.agent = agent // it has a chance so its value can be set!
}
}
или по умолчанию использовать любое значение (включая nil
, которое является глупым)
class Actor {
let agent : String? = nil // very useless, but doable.
let company: String? = "Universal"
}
Если вам интересно, почему let
(в отличие от var
) не инициализируется на nil
, тогда прочитайте здесь и здесь
В моем случае я объявил Bool
следующим образом:
var isActivityOpen: Bool
то есть. Я объявил это без разворачивания так. Вот как я решил ошибку (без инициализатора):
var isActivityOpen: Bool!
Не конкретный ответ на ваш вопрос, но я получил эту ошибку, когда я не задал начальное значение для перечисления, объявив его как свойство. Я назначил начальное значение перечислению для устранения этой ошибки. Проводка здесь, поскольку это может помочь кому-то.