While creating a table view that displays the date and cell check items in the section, the tableData definition displays the error Cannot use instance member'checkListItem1' with in property initializer; property initializers run before 'self' is available.How can we solve this problem?Thank you from the bottom of my heart for your reply.
import UIKit
classViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
////
func numberOfSections (intableView: UITableView) - > Int // Default is 1 if not implemented
{ return sectionTitle.count
}
////
functableView(_tableView:UITableView, titleForHeaderInSection section: Int) - > String?// fixed font style.use custom view(UILabel) if you want something different
{
return sectionTitle [section]
}
// Place the calendar or date picker on the height of the status bar.
let statusBarHeight=UIApplication.shared.statusBarFrame.height+200
// Section Items
var sectionTitle= ["H28,01,23", "H27,12,31", "H28,01,12", "H28,02,21", "H28,11,10" ]
// Checklist Items and Check Status
varcheckListItem1: String:Bool = [
"Item 1": true,
Item 2 : false,
"Item 3": true,
"Item 4": true,
"Item 5": false
]
varcheckListItem2: String:Bool = [
"Item 2-1": false,
"Item 2-2": true,
"Item 2-3": true,
"Item 2-4": true,
"Item 2-5": false
]
varcheckListItem3: String:Bool = [
"Item 3-1": true,
"Item 3-2": true,
"Item 3-3": true,
"Item 3-4": true,
"Item 3-5": false
]
varcheckListItem4: String:Bool = [
"Item 4-1": true,
"Item 4-2": false,
"Item 4-3": true,
"Item 4-4": false,
"Item 4-5": false
]
varcheckListItem5: String:Bool = [
"Item 5-1": true,
"Item 5-2": false,
"Item 5-3": true,
"Item 5-4": true,
"Item 5-5": true
]
variableData=[checkListItem1, checkListItem2, checkListItem3, checkListItem4, checkListItem5]
lettableView=UITableView()
override func viewDidLoad(){
super.viewDidLoad()
// Creating a UITableView
tableView.frame = CGRect(
x —0,
y —statusBarHeight,
width —self.view.frame.width,
height —self.view.frame.height-statusBarHeight
)
tableView.delegate=self
tableView.dataSource=self
self.view.addSubview(tableView)
}
// Creating Cells
//
functableView(_tableView:UITableView, cellForRowAtindexPath:IndexPath) - >UITableViewCell{
// Obtain an array of Dictionary keys
varkeys = String (tableData.keys)
// Sort by key
keys.sort()
// Retrieve key string
letcellText=keys [indexPath.row]
// Cell Creation and Text Configuration
letcell=UITableViewCell (style:.default, reuseIdentifier: "cell")
cell.textLabel?.text=cellText
///
let sectionData=tableData[(indexPath as NSIndexPath).section]
letcellData=sectionData[(indexPath as NSIndexPath).row]
// If the check state is true, go to the check state from the beginning.
if self.tableData[cellText]!{
cell.imageView?.image=UIImage(named: "checked")
} else{
cell.imageView?.image=UIImage(named: "unchecked")
}
return cell
}
// What to do when a cell is tapped?
functableView(_tableView:UITableView, didSelectRowAtindexPath:IndexPath){
iflet cell=tableView.cellForRow(at:indexPath){
// Get text for tapped cells
letcellText=cell.textLabel?.text
// Switch Images and Change Dictionary Values
ifcell.imageView?.image==UIImage(named: "checked"){
self.tableData.updateValue(false, forKey:cellText!)
cell.imageView?.image=UIImage(named: "unchecked")
} else{
self.tableData.updateValue(true, forKey:cellText!)
cell.imageView?.image=UIImage(named: "checked")
}
// Unselect state
cell.isSelected=false
}
}
// functableView(_tableView:UITableView, heightForRowAtindexPath:IndexPath)->CGFloat{
// return56
// }
///
functableView(_tableView:UITableView, numberOfRowsInSection section:Int) - > Int{
let sectionData=tableData[section]
return self.tableData.count
}
}
Simply put, Swift cannot use other instance variables (all references to self
) in the initialization expression for instance properties.
For more information, see The Swift Programming Language (Swift 3.0.1)) in the I need you to read this carefully, but since it's long English, the Swift (class) initializer must do the following in the order specified:
Give initial value to all instance properties introduced in your class
(You can give the property an initialization expression or substitute it within your own init
)
Call the designated superclass initializer among initializers
(If you inherit the initializer, it will automatically call you, or you can explicitly call it super.init(...)
in your initializer.)
So far, other object-oriented languages have similar rules, but Swift has even more stringent restrictions here.
self
until you have completed 1.2. aboveIt's supposed to be thatTherefore, any initialization expression evaluated prior to the initializer cannot use other instance properties (accessed via self
) or call instance methods.
(By the way, 1.2. above is supposed to be phase one of the "two-phase initialization" in Swift terminology.)
Therefore, if you want to initialize with a value that uses other instance property values (or uses the results of the instance method), you can do the following:
Give value after reading super.init(...)
in your initializer
Due to the above circumstances, super.init(...)
cannot be called, so you can give temporary values such as initialization expressions (you may need to set the data type of the variable to Implicitly Unwrapped Optional) and rewrite it after super.init(...)
.
For ViewController, which usually does not define its own initializer like your code, this pattern can be difficult to use because defining the initializer is troublesome.Reopening and initializing in viewDidLoad()
is a very common pattern.
Use the lazy
variable
The exception to the above constraints is that lazy
declared instance properties can contain other instance properties in the initialization expression.lazy
property initialization must remain uninitialized before super.init(...)
is first referenced.
Makes the referenced property either a class constant or a top-level constant
Class properties and top-level variables and constants can be used as the initialization of instance properties in class definitions without any problems because they were initialized before the initializer of the class was called.
If you want to use viewDidLoad()
in 1.tableData
property declaration is
variableData: [[String:Bool]]=[ ]
Keep as shown in
override func viewDidLoad(){
super.viewDidLoad()
tableData=[checkListItem1, checkListItem2, checkListItem3, checkListItem4, checkListItem5]
// Creating a UITableView
tableView.frame = CGRect(
x —0,
y —statusBarHeight,
width —self.view.frame.width,
height —self.view.frame.height-statusBarHeight
)
tableView.delegate=self
tableView.dataSource=self
self.view.addSubview(tableView)
}
Will it look like this?
If you use lazy
in 2, this is the one line to rewrite.
lazy variableData: [[String:Bool]] = [self.checkListItem1, self.checkListItem2, self.checkListItem3, self.checkListItem4, self.checkListItem5]
It is understandable that self
is required to reference each property, considering that the initialization expression of the lazy
property is actually a type of closure, but it is difficult to understand the error message when you forget to add self.
.Check it out yourself.
You can also rewrite the pattern in 3. checkListItem1
~checkListItem5
is kicked out of the class to make it the top level constant.
// Checklist Items and Check States
private let checkListItem1: [String:Bool] = [
"Item 1": true,
Item 2 : false,
"Item 3": true,
"Item 4": true,
"Item 5": false
]
private let checkListItem2: [String:Bool] ]
//...
]
private let checkListItem3: String:Bool = [
//...
]
private let checkListItem4: [String:Bool] = [
//...
]
private let checkListItem5: [String:Bool] ]
//...
]
classViewController:UIViewController {
//...
variableData=[checkListItem1, checkListItem2, checkListItem3, checkListItem4, checkListItem5]
//...
}
The Bool
value, which represents the check state, is rewritten, so you may not think it can be a let
constant, but Swift has both Array
and Dictionary
values, so tableData
has checkListItem1
~ checkListI/code> initial value.There is no problem with
.You do not want to fiddle with the ViewController
instance properties from another class.
The sure and easy way is the first one.Try it.
So, if you solve the error in the title, it seems that the error hidden in your code appears in a potato-zuru style, but it's a different matter, so if there's anything you can't solve by yourself, you should ask another question.
© 2024 OneMinuteCode. All rights reserved.