初学者在这里,我创建了一个带有3个分段控件的VC,每个控件有3个段。每个段选择显示不同的文本视图。在任何给定时间,显示2个分段控件,因此您可以选择在6个文本视图中的任何一个之间切换。总共有9个文本视图。
我现在写这个的方式在模拟器中看起来有点小问题,所以我想知道一种更好的方法来编写这种重复代码。我在任何时候显示的2/3分段控件的所有选择之间有很多.isHidden = false和isHidden = true行。谁能告诉我怎样才能以更安全的方式写出来?如果你想举一个简短的例子或者告诉我谷歌的内容,我很感激。
这就是我所拥有的:
class ViewController: UIViewController {
@IBOutlet weak var segmentedControl: UISegmentedControl!
@IBOutlet weak var textSegmentedControl: UISegmentedControl!
@IBOutlet weak var translationSegmentedControl: UISegmentedControl!
@IBOutlet weak var firstLangText: UITextView!
@IBOutlet weak var secondLangText: UITextView!
@IBOutlet weak var thirdLangText: UITextView!
@IBOutlet weak var translationA: UITextView!
@IBOutlet weak var translationB: UITextView!
@IBOutlet weak var translationC: UITextView!
@IBOutlet weak var textInfo: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
style(control: segmentedControl)
segmentedControl.addTarget(self, action: #selector(updateMainSegmentedControl), for: .valueChanged)
textSegmentedControl.addTarget(self, action: #selector(updateTextSegmentedControl), for: .valueChanged)
translationSegmentedControl.addTarget(self, action: #selector(updateTranslationSegmentedControl), for: .valueChanged)
secondLangText.isHidden = true
thirdLangText.isHidden = true
translationSegmentedControl.isHidden = true
translationA.isHidden = true
translationB.isHidden = true
translationC.isHidden = true
}
//Mark: Stye SegmentControls & underlineBar
func style(control: UISegmentedControl) {
control.backgroundColor = .clear
control.tintColor = .clear
control.setTitleTextAttributes([NSAttributedStringKey.font : UIFont.systemFont(ofSize: 16), NSAttributedStringKey.foregroundColor: UIColor.secondaryColor], for: .normal)
control.setTitleTextAttributes([NSAttributedStringKey.font : UIFont.systemFont(ofSize: 16),NSAttributedStringKey.foregroundColor: UIColor.primaryColor], for: .selected)
}
@IBAction func textOrTranslationChange(_ sender: UISegmentedControl) {
switch segmentedControl.selectedSegmentIndex {
case 0:
textSegmentedControl.isHidden = false
translationSegmentedControl.isHidden = true
translationUnderlineBar.isHidden = true
firstLangText.isHidden = false
translationA.isHidden = true
textInfo.isHidden = true
case 1:
textSegmentedControl.isHidden = true
translationSegmentedControl.isHidden = false
firstLangText.isHidden = true
translationA.isHidden = false
textInfo.isHidden = true
case 2:
textSegmentedControl.isHidden = true
translationSegmentedControl.isHidden = true
firstLangText.isHidden = true
textInfo.isHidden = false
default:
break;
}
}
@IBAction func selectTextLanguage(_ sender: UISegmentedControl) {
switch textSegmentedControl.selectedSegmentIndex {
case 0:
firstLangText.isHidden = false
secondLangText.isHidden = true
thirdLangText.isHidden = true
translationA.isHidden = true
translationB.isHidden = true
translationC.isHidden = true
case 1:
firstLangText.isHidden = true
secondLangText.isHidden = false
thirdLangText.isHidden = true
translationA.isHidden = true
translationB.isHidden = true
translationC.isHidden = true
case 2:
firstLangText.isHidden = true
secondLangText.isHidden = true
thirdLangText.isHidden = false
translationA.isHidden = true
translationB.isHidden = true
translationC.isHidden = true
default:
break;
}
}
@IBAction func selectTranslationLanguage(_ sender: UISegmentedControl) {
switch translationSegmentedControl.selectedSegmentIndex {
case 0:
translationA.isHidden = false
translationB.isHidden = true
translationC.isHidden = true
firstLangText.isHidden = true
secondLangText.isHidden = true
thirdLangText.isHidden = true
case 1:
translationA.isHidden = true
translationB.isHidden = false
translationC.isHidden = true
firstLangText.isHidden = true
secondLangText.isHidden = true
thirdLangText.isHidden = true
case 2:
translationA.isHidden = true
translationB.isHidden = true
translationC.isHidden = false
firstLangText.isHidden = true
secondLangText.isHidden = true
thirdLangText.isHidden = true
default:
break;
}
}
您可以在切换之前将它们全部设置为默认值,然后只更新案例中的不同值。这在您的第三种方法中尤其有效,其中大多数视图的默认状态为true。
@IBAction func selectTranslationLanguage(_ sender: UISegmentedControl)
{
[translationA, translationB, translationC, firstLangText,
secondLangText, thirdLangText].forEach { $0.isHidden = true }
switch translationSegmentedControl.selectedSegmentIndex
{
case 0: translationA.isHidden = false
case 1: translationB.isHidden = false
case 2: translationC.isHidden = false
default: break
}
}
首先,您需要从switch case中提取常见的行为,以便删除一些重复的行为。
@IBAction func textOrTranslationChange(_ sender: UISegmentedControl) {
switch segmentedControl.selectedSegmentIndex {
case 0:
translationUnderlineBar.isHidden = true
textInfo.isHidden = true
firstLangText.isHidden = false
translationA.isHidden = true
textSegmentedControl.isHidden = false
translationSegmentedControl.isHidden = true
case 1:
textInfo.isHidden = true
firstLangText.isHidden = true
translationA.isHidden = false
textSegmentedControl.isHidden = true
translationSegmentedControl.isHidden = false
case 2:
textInfo.isHidden = false
firstLangText.isHidden = true
textSegmentedControl.isHidden = true
translationSegmentedControl.isHidden = true
default:
break;
}
}
@IBAction func selectTextLanguage(_ sender: UISegmentedControl) {
switch textSegmentedControl.selectedSegmentIndex {
case 0:
showLanaguage(which: firstLangText)
case 1:
showLanaguage(which: secondLangText)
case 2:
showLanaguage(which: thirdLangText)
default:
break;
}
translationA.isHidden = true
translationB.isHidden = true
translationC.isHidden = true
}
func showLanaguage(which: UITextView){
[firstLangText,secondLangText,thirdLangText].forEach({
$0?.isHidden = $0 != which
})
}
func showTranslation(which: UITextView){
[translationA,translationB,translationC].forEach({
$0?.isHidden = $0 != which
})
}
@IBAction func selectTranslationLanguage(_ sender: UISegmentedControl) {
switch translationSegmentedControl.selectedSegmentIndex {
case 0:
showTranslation(which: translationA)
case 1:
showTranslation(which: translationB)
case 2:
showTranslation(which: translationC)
default:
break;
}
firstLangText.isHidden = true
secondLangText.isHidden = true
thirdLangText.isHidden = true
}
如果文本视图具有相同的位置,则可以重复使用它们。如果它们不同,您可以使用outlet集合对它们进行分组。所以你会有
@IBOutlet weak var langTextViews: [UITextView]!
代替:
@IBOutlet weak var firstLangText: UITextView!
@IBOutlet weak var secondLangText: UITextView!
@IBOutlet weak var thirdLangText: UITextView!
它将使您的代码更有条理和可读。您可以优化textView隐藏/显示部分。例如,textOrTranslationChange
mehtod看起来像这样:
@IBAction func textOrTranslationChange(_ sender: UISegmentedControl) {
textSegmentedControl.isHidden = (segmentedControl.selectedSegmentIndex != 0)
langTextViews[0].isHidden = (segmentedControl.selectedSegmentIndex != 0)
translationSegmentedControl.isHidden = (segmentedControl.selectedSegmentIndex != 1)
textInfo.isHidden = (segmentedControl.selectedSegmentIndex != 2)
etc...
}
优雅的解决方案是使用UISegmentedControl
的美丽。 Swift Dictionaries和标签属性。
您可以通过设置分段控件的初始UITextView
来使用单个tag
,然后引用tag
和selectedIndex
来确定要更改的字段或值。然后,您可以轻松地将值存储在Dictionary
中,而无需复杂的switch
语句。
这是一个最小的,可重复的例子。你应该在输入之后实现自己的处理值的方法,比如验证。
import Foundation
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
// Properties
var activeSegment: UISegmentedControl?
var activeIndex: Int?
var values:[String: String] = [:]
lazy var segmentedController: UISegmentedControl = {
let seg = UISegmentedControl(items: ["Name", "Age", "Language"])
seg.translatesAutoresizingMaskIntoConstraints = false
seg.tag = 0
seg.addTarget(self, action: #selector(segmentedControllerValueChanged(sender:)), for: .valueChanged)
return seg
}()
lazy var secondSegmentedController: UISegmentedControl = {
let seg = UISegmentedControl(items: ["Type", "Kind", "Thing"])
seg.translatesAutoresizingMaskIntoConstraints = false
seg.tag = 1
seg.addTarget(self, action: #selector(segmentedControllerValueChanged(sender:)), for: .valueChanged)
return seg
}()
let textField: UITextField = {
let tf = UITextField(frame: CGRect.zero)
tf.translatesAutoresizingMaskIntoConstraints = false
tf.placeholder = "Select Field"
return tf
}()
override func viewDidLoad() {
super.viewDidLoad()
textField.delegate = self
self.layoutSubviews()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
func layoutSubviews() {
let guide = self.view.safeAreaLayoutGuide
let spacing:CGFloat = 12.0
self.view.addSubview(segmentedController)
self.view.addSubview(secondSegmentedController)
self.view.addSubview(textField)
segmentedController.widthAnchor.constraint(equalTo: guide.widthAnchor).isActive = true
segmentedController.heightAnchor.constraint(equalToConstant: 55.0).isActive = true
segmentedController.bottomAnchor.constraint(equalTo: guide.bottomAnchor, constant: -spacing).isActive = true
segmentedController.centerXAnchor.constraint(equalTo: guide.centerXAnchor).isActive = true
secondSegmentedController.widthAnchor.constraint(equalTo: guide.widthAnchor).isActive = true
secondSegmentedController.heightAnchor.constraint(equalToConstant: 55.0).isActive = true
secondSegmentedController.bottomAnchor.constraint(equalTo: segmentedController.topAnchor, constant: -spacing).isActive = true
secondSegmentedController.centerXAnchor.constraint(equalTo: guide.centerXAnchor).isActive = true
textField.centerXAnchor.constraint(equalTo: guide.centerXAnchor).isActive = true
textField.centerYAnchor.constraint(equalTo: guide.centerYAnchor).isActive = true
textField.heightAnchor.constraint(equalToConstant: 55.0).isActive = true
textField.widthAnchor.constraint(equalTo: guide.widthAnchor, constant: -spacing*2).isActive = true
}
@objc func segmentedControllerValueChanged(sender: UISegmentedControl) {
// Clear all other segments
let segmentedcontrols = [segmentedController, secondSegmentedController]
segmentedcontrols.forEach { (control) in
if (control.tag != sender.tag) {
control.selectedSegmentIndex = -1
}
}
// Safely get the title for the index
guard let titleForIndex = sender.titleForSegment(at: sender.selectedSegmentIndex) else {
self.textField.placeholder = "Select Field"
return
}
// Set the active fields.
self.textField.text = nil
self.textField.placeholder = "Input " + titleForIndex
self.activeSegment = sender
self.activeIndex = sender.selectedSegmentIndex
// Handle Text Input with your own methods / switch statements
print("Value did change to: \( sender.selectedSegmentIndex) with tag \(sender.tag)" )
print("values: \(values)")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: - Text Field Delegate
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// Safely get the title for the index
guard let segment = activeSegment, let index = activeIndex, let activeSegmentTitle = segment.titleForSegment(at: index) else {
return false
}
guard let text = textField.text else {
return false
}
values[activeSegmentTitle] = text
textField.resignFirstResponder()
return true
}
}