从 Swift 中的函数设置 UiButton 的状态
Posted
技术标签:
【中文标题】从 Swift 中的函数设置 UiButton 的状态【英文标题】:Setting the state of a UiButton from a function in Swift 【发布时间】:2017-08-12 12:39:38 【问题描述】:我有 7 个按钮来打开和关闭一周中的日子。例如,如果按下星期日的按钮,IBAction 会自动切换状态而不会出现任何问题:
@IBAction func SoToggle(_ sender: UIButton)
self.So.isSelected = !self.So.isSelected;
但是当我尝试从同一类中的函数设置该按钮的状态时,我收到一条错误消息:
在展开可选值时意外发现 nil
这是用于将“isSelected”设置为真或假的代码:
func setSo(state: Bool)
self.So.isSelected = state
我不明白为什么这不起作用,因为它几乎是相同的代码。
编辑: 该函数由 TableViewController 调用,按钮位于自定义 TableViewCell 中。我包含了整个代码,只是为了让事情清楚。 表视图控制器:
class TableViewSettings: UITableViewController
let sections = ["weekdays", "start time"]
var CellDays:TableViewCellDays = TableViewCellDays()
override func viewDidLoad()
super.viewDidLoad()
self.view.layer.cornerRadius = 7
self.tableView.contentInset = UIEdgeInsets(top: 10,left: 0,bottom: 0,right: 0)
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?
return self.sections[section]
override func numberOfSections(in tableView: UITableView) -> Int
// #warning Incomplete implementation, return the number of sections
return sections.count
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
// #warning Incomplete implementation, return the number of rows
return 1
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
if(indexPath.section == 0)
return Bundle.main.loadNibNamed("TableViewCellDays", owner: self, options: nil)?.first as! TableViewCellDays
else
return Bundle.main.loadNibNamed("TableViewCellPicker", owner: self, options: nil)?.first as! TableViewCellPicker
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
if(indexPath.section == 0)
return 80
else
return 150
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat
return 15
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
return 30
override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView?
let v: UIView = UIView()
v.backgroundColor = .clear
return v;
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
let cell = Bundle.main.loadNibNamed("TableViewCellHeader", owner: self, options: nil)?.first as! TableViewCellHeader
cell.mainLabel.text = sections[section]
return cell
func setSettingsButtons(settings: [String])
// if (settings[0] == "1")
// CellDays.Mo.isSelected = true
// else CellDays.Mo.isSelected = false
//
// if (settings[1] == "1")
// CellDays.Di.isSelected = true
// else CellDays.Di.isSelected = false
//
// if (settings[2] == "1")
// CellDays.Mi.isSelected = true
// else CellDays.Mi.isSelected = false
//
// if (settings[3] == "1")
// CellDays.Do.isSelected = true
// else CellDays.Do.isSelected = false
//
// if (settings[4] == "1")
// CellDays.Fr.isSelected = true
// else CellDays.Fr.isSelected = false
//
// if (settings[5] == "1")
// CellDays.Sa.isSelected = true
// else CellDays.Sa.isSelected = false
//
// if (settings[6] == "1")
// CellDays.So.isSelected = true
// else CellDays.So.isSelected = false
CellDays.setSo(state: true)
TableViewCell:
class TableViewCellDays: UITableViewCell
@IBOutlet var Mo: UIButton!
@IBOutlet var Di: UIButton!
@IBOutlet var Mi: UIButton!
@IBOutlet var Do: UIButton!
@IBOutlet var Fr: UIButton!
@IBOutlet var Sa: UIButton!
@IBOutlet var So: UIButton!
@IBOutlet var MoLeading: NSLayoutConstraint!
@IBOutlet var DiLeading: NSLayoutConstraint!
@IBOutlet var MiLeading: NSLayoutConstraint!
@IBOutlet var DoLeading: NSLayoutConstraint!
@IBOutlet var FrLeading: NSLayoutConstraint!
@IBOutlet var SaLeading: NSLayoutConstraint!
@IBOutlet var SoLeading: NSLayoutConstraint!
var offset: CGFloat = 10
override func awakeFromNib()
super.awakeFromNib()
// init Button states
Mo.isSelected = false
Di.isSelected = false
Mi.isSelected = false
Do.isSelected = false
Fr.isSelected = false
Sa.isSelected = false
So.isSelected = false
let screenWidth = UIScreen.main.bounds.width
let screenWidthCenter = screenWidth/2
let frameWidth = Do.frame.width
// Offset Settings depending on Device
offset = screenWidth / 37
print(offset)
// X Coordinate Settings
MoLeading.constant = screenWidthCenter - 3.5 * frameWidth - 3.75 * offset
DiLeading.constant = screenWidthCenter - 2.5 * frameWidth - 2.75 * offset
MiLeading.constant = screenWidthCenter - 1.5 * frameWidth - 1.75 * offset
DoLeading.constant = screenWidthCenter - 0.5 * frameWidth - 0.75 * offset
FrLeading.constant = screenWidthCenter + 0.5 * frameWidth + 0.25 * offset
SaLeading.constant = screenWidthCenter + 1.5 * frameWidth + 1.25 * offset
SoLeading.constant = screenWidthCenter + 2.5 * frameWidth + 2.25 * offset
@IBAction func MoToggle(_ sender: UIButton)
self.Mo.isSelected = !self.Mo.isSelected;
@IBAction func DiToggle(_ sender: UIButton)
self.Di.isSelected = !self.Di.isSelected;
@IBAction func MiToggle(_ sender: UIButton)
self.Mi.isSelected = !self.Mi.isSelected;
@IBAction func DoToggle(_ sender: UIButton)
self.Do.isSelected = !self.Do.isSelected;
@IBAction func FrToggle(_ sender: UIButton)
self.Fr.isSelected = !self.Fr.isSelected;
@IBAction func SaToggle(_ sender: UIButton)
self.Sa.isSelected = !self.Sa.isSelected;
@IBAction func SoToggle(_ sender: UIButton)
self.So.isSelected = !self.So.isSelected;
func setSo(state: Bool)
self.Mo.isSelected = state
【问题讨论】:
你能检查一下你所有的 IBOutlets 是否都正确连接 是的,这是我检查的第一件事。每个按钮都连接正确。 能否在 setSo 中放一个断点,然后检查是否所有按钮都已启动并且不是 nil ? 在您发送新状态时,您的所有按钮似乎都为零。这意味着您尝试设置新状态太早(您的控制器或包含按钮的父视图尚未加载)或太晚(您的控制器或父视图已解除分配、关闭)如果您将显示整个状态会更好代码 我看到你已经接受了一个答案。好的!但是你为什么不使用UISegmentedControl
? (我没有深入了解 UITableView
代码,因为我希望您不会在每个单元格中包含 7 个 UIButtons
。这是非常糟糕的 UI。)分段控件完全正确 当用户有(a)他们可以更改的几个选择但(b)只允许一个选择时,您想要的东西。对此进行编码非常容易。
【参考方案1】:
首先,您必须为表格视图注册 nib 才能使用它。
添加viewDidLoad
:
self.tableView.register(UINib(nibName:"TableViewCellDays", bundle:nil), forCellReuseIdentifier: "TableViewCellDays")
如下替换你的变量声明:
var CellDays:TableViewCellDays?
稍后您将在数据源方法中为其分配一个值。
接下来在您的tableView: UITableView, cellForRowAt
中获取此单元格并将实例变量CellDays
分配给它:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
if(indexPath.section == 0)
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCellDays") as! TableViewCellDays
self.CellDays = cell
return cell
else
return Bundle.main.loadNibNamed("TableViewCellPicker", owner: self, options: nil)?.first as! TableViewCellPicker
只有之后,您才能调用您的 setSettingsButtons
方法。
【讨论】:
我收到错误:“参数标签与任何可用的重载都不匹配。” @J.Doe 你的TableViewCellDays
是视图控制器吗?
TableViewCellDays 是一个自定义的 TableViewCell 笔尖。该函数由 ViewController 调用。
@J.Doe 那么你是在初始化tableView: UITableView, cellForRowAt
中的单元格吗?
我只是包含了整个代码来查看。 “setSettingsButtons”函数被赋予一个包含 7 个布尔值的数组来切换按钮。我只是出于测试目的将其注释掉。以上是关于从 Swift 中的函数设置 UiButton 的状态的主要内容,如果未能解决你的问题,请参考以下文章
Swift - 从 CollectionViewCell 中的 UIButton 推送到 ViewController
不...当 UIButton (Swift) 中的文本太长时