UPDATED BELOW!
I have a UI structure with a horizontal scrollView nesting 5 tableViews – each representing a day of the week. I have added a UISwitch to add weekend to the week, so when the user switches it on, two more tableview-subviews are added to the scrollView. So far so good, but the switch change only takes effect, when I relaunch the application. Looks like ViewDidLoad() makes it happen, but nothing else. I added a Bool variable called isWeekOn. Its state is managed from viewDidLoad:
isWeekendOn = UserDefaults.standard.bool(forKey: "switchState")
dayTableViews = fiveOrSevenDayTableViews()
where fiveOrSevenTableViews() is a closure returning the array of tableviews with the proper count and dayTableViews is my local array variable.
lazy var fiveOrSevenDayTableViews: () -> [DayTableView] = {
if self.isWeekendOn == false {
return [self.mondayTableView, self.tuesdayTableview, self.wednesdayTableview, self.thursdayTableView, self.fridayTableView]
} else {
return [self.mondayTableView, self.tuesdayTableview, self.wednesdayTableview, self.thursdayTableView, self.fridayTableView, self.saturdayTableView,self.sundayTableView]
}
}
I added a didSet property observer to isWeekendOn and that also calls setupViews(), where the number of tableviews is also decided by calling fiveOrSevenTableViews closure .
var isWeekendOn: Bool = false {
didSet {
print("LessonVC IsWeekendon: ",isWeekendOn)
dayTableViews = fiveOrSevenDayTableViews()
setupViews()
print("didset daytableviews", fiveOrSevenDayTableViews().count)
}
}
Where my setupViews() looks like:
func setupViews() {
setupScrollView()
let numberOfTableViews = CGFloat(dayTableViews.count)
let stackView = UIStackView(arrangedSubviews: fiveOrSevenDayTableViews())
print("setupViews stacview subviews count", stackView.arrangedSubviews.count)
stackView.axis = .horizontal
stackView.distribution = .fillEqually
scrollView.addSubview(stackView)
setupStackViewConstraints(stackView, numberOfTableViews)
}
And setupScrollView():
private func setupScrollView() {
let numberOfTableViews = CGFloat(dayTableViews.count)
print("setupScrollview dableviews", numberOfTableViews)
scrollView.frame = CGRect(x: 0, y: 0, width: view.bounds.width, height:0)
scrollView.contentSize = CGSize(width: view.frame.width * numberOfTableViews, height: 0)
view.addSubview(scrollView)
setupScrollviewConstraints()
}
All the print statements are called properly, so I am wondering, why the changes actually do not take effect real time, and instead working only relaunch.
What I tried:
As @maniponken suggested, i made a function which looks like:
func readdStackView(_ stackView: UIStackView) { stackView.removeFromSuperview()
setupViews() }
than I call this within the isWeekendOn didSet observer. Didn't work out unfortunately.
UPDATE:
Actually when I put anything in my isWeekendon didSet observer, doesn't work! For example changing my navigationBar backgroundColor...etc Everything is reflecting on console though, in the print statements! Those functions also take effect at relaunch only.I have no idea what I am doing wrong.
UPDATE2:
Removing the tables works without problem with a local UIButton! My Problem is the following though: I have a settings view controller, which has a switch for setting 5 or 7 table views. Realtime update does not work with that switch, only with le local button, triggering an @objc func. I still need that settings panel for the user though!
Finally I have solved the problem.
UPDATE: The main reason I had to set up NotificationCenter for this matter, is that I used UITabBarController to add SettingsVC to my app instead of presenting it modally. Details below.
//Skip this part for answer My main problem – as it turned out – was that my UISwitch was on a separate vc, called SettingsViewController. This switch supposed to do the tableview-adding and removing on my main vc. I tried with delegate protocols, targeting shared instance of settingsVC, nothing worked, but adding a local button for this – which is definitely not what I wanted. Then I read about NotificationCenter! I remembered it from Apples App Development For Swift book,I read last year, but forgot since. // So the Anwswer
After I set my constraints correctly based on the great hint of @DonMag, I set up NotificationCenter for my SettingsViewController, posting to my Main VC.
class SettingsViewController: UITableViewController {
private let reuseID = "reuseId"
lazy var switchButton: UISwitch = {
let sw = UISwitch()
sw.addTarget(self, action: #selector(switchPressed), for: .valueChanged)
sw.onTintColor = AdaptiveColors.navigationBarColor
return sw
}()
static let switchNotification = Notification.Name("SettingsController.switchNotification")
var isOn = Bool() {
didSet {
NotificationCenter.default.post(name:SettingsViewController.switchNotification, object: nil)
}
}
@objc func switchPressed(_ sender: UISwitch) {
UserDefaults.standard.set(sender.isOn, forKey: "switchState")
self.isOn = sender.isOn
}
then in the mainVC:
override func viewDidLoad() {
super.viewDidLoad()
scrollView.delegate = self
view.backgroundColor = .white
isWeekendOn = UserDefaults.standard.bool(forKey: "switchState")
// The Solution:
NotificationCenter.default.addObserver(self, selector: #selector(handleRefresh), name: SettingsViewController.switchNotification, object: nil)
dayTableViews = fiveOrSevenDayTableViews()
print("daytableviews count ", dayTableViews.count)
scrollView.delegate = self
editButtonItem.title = LocalizedString.edit
navigationItem.title = localizedDays[currentPage]
setupNavigationBar()
setupButtons()
setupTableViews()
setupViews()
isWeekendOn == true ? setupCurrentDayViewFor_7days() : setupCurrentDayViewFor_5days()
}
then here in mainVC's @objc func handleRefresh() { }
i am handling the removal or addition!
UPDATE:
in SettingsVC:
static let switchOnNotification = Notification.Name("SettingsController.switchOnNotification")
static let switchOffNotification = Notification.Name("SettingsController.switchOffNotification")
var isOn = Bool() {
didSet {
}
willSet {
if newValue == true {
NotificationCenter.default.post(name:SettingsViewController.switchOnNotification, object: nil)
} else if newValue == false {
NotificationCenter.default.post(name:SettingsViewController.switchOffNotification, object: nil)
}
}
}
in viewDidLoad in mainVC:
NotificationCenter.default.addObserver(self, selector: #selector(handleAddWeekendTableViews), name: SettingsViewController.switchOnNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleRemoveWeekendTableViews), name: SettingsViewController.switchOffNotification, object: nil)
@objc func handleAddWeekendTableViews() {
[saturdayTableView, sundayTableView].forEach {
stackView.addArrangedSubview($0)
dayTableViews.append($0)
}
}
@objc func handleRemoveWeekendTableViews() {
manageCurrentPage()
dayTableViews.removeLast(2)
[saturdayTableView, sundayTableView].forEach {
$0.removeFromSuperview()
}
}
This one is actually working!