Convert UIView from the simple Xib-file to Swift source code.
Source Xib Source
The simple Xib-file – is a Xib-file which holds design bound to the single UIView. Think about it as a "one to one" relationship between UI and Code.
Here is how the simple Xib-file may look like:
It has the two UILabels bound to IBOutlets and one UIButton bound to IBAction.
public class View: UIView {
@IBOutlet private weak var titleLabel: UILabel!
@IBOutlet private weak var numberOfTapsLabel: UILabel!
private var numberOfTaps = 0
public override func awakeFromNib() {
super.awakeFromNib()
titleLabel.textColor = .blue
}
@IBAction private func onIncrement(_ sender: UIButton) {
numberOfTaps += 1
numberOfTapsLabel.text = "The button tapped \"\(numberOfTaps)\" times."
}
}
In iOS Simulator this Xib-file looks as shown below:
Tapping on UIButton will change title of the second label.
Generated code
The source code generated by Decode.app looks like below:
public class Generated: UIView {
private lazy var titleLabel = UILabel()
private lazy var button = UIButton(type: .system)
private lazy var numberOfTapsLabel = UILabel()
private lazy var stackView = UIStackView()
public init() {
super.init(frame: CGRect())
setupUI()
setupLayout()
}
required init?(coder: NSCoder) {
fatalError("Please use this class from code.")
}
private func setupUI() {
addSubview(stackView)
autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin, .flexibleTopMargin, .flexibleBottomMargin]
backgroundColor = UIColor.white
frame = CGRect(x: 0, y: 0, width: 320, height: 480)
stackView.addArrangedSubview(titleLabel)
stackView.addArrangedSubview(button)
stackView.addArrangedSubview(numberOfTapsLabel)
stackView.alignment = .top
stackView.axis = .vertical
stackView.spacing = 10
stackView.translatesAutoresizingMaskIntoConstraints = false
numberOfTapsLabel.contentMode = .left
numberOfTapsLabel.font = UIFont.systemFont(ofSize: 17)
numberOfTapsLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 251), for: .horizontal)
numberOfTapsLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 251), for: .vertical)
numberOfTapsLabel.text = "The button tapped \"0\" times."
numberOfTapsLabel.textAlignment = .natural
numberOfTapsLabel.translatesAutoresizingMaskIntoConstraints = false
button.contentVerticalAlignment = .center
button.titleLabel?.font = UIFont.systemFont(ofSize: 17, weight: .medium)
button.titleLabel?.lineBreakMode = .byTruncatingMiddle
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle("Tap", for: .normal)
titleLabel.contentMode = .left
titleLabel.font = UIFont.systemFont(ofSize: 17, weight: .semibold)
titleLabel.numberOfLines = 0
titleLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 251), for: .horizontal)
titleLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 251), for: .vertical)
titleLabel.text = "Hi, This is an example UI!"
titleLabel.translatesAutoresizingMaskIntoConstraints = false
}
private func setupLayout() {
trailingAnchor.constraint(equalTo: stackView.trailingAnchor, constant: 16).isActive = true
stackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16).isActive = true
stackView.topAnchor.constraint(equalTo: topAnchor, constant: 16).isActive = true
}
}
The generated code contains UILabel and UIButton as in original source file.
In iOS Simulator the generated UIView looks as shown below:
Almost like in the original view, but there is few issues:
- The label has a black color instead of blue.
- Tapping on button not changing a title of second label. The IBAction is not working.
Such issues are expected. Here is why:
- The label color was set in awakeFromNib method. This method is not called when no Xib-file is involved (which is a case after the Xib-file was converted to source code).
- The IBAction is not called because there is no IBOutlet and Xib-file anymore. We need to restore this connection manually.
Resolving issues
The diff-file below shows what was changed in order to restore connection between UI elements setup and remaining source code.
@@ -1,5 +1,5 @@
import UIKit
-public class Generated: UIView {
+public class Adjusted: UIView {
private lazy var titleLabel = UILabel()
@@ -8,4 +8,6 @@
private lazy var stackView = UIStackView()
+ private var numberOfTaps = 0
+
public init() {
super.init(frame: CGRect())
@@ -18,4 +20,9 @@
}
+ @IBAction private func onIncrement(_ sender: UIButton) {
+ numberOfTaps += 1
+ numberOfTapsLabel.text = "The button tapped \"\(numberOfTaps)\" times."
+ }
+
private func setupUI() {
@@ -48,4 +55,6 @@
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle("Tap", for: .normal)
+ // 2️⃣ Button connected to the existing function (which was previously an IBAction).
+ button.addTarget(self, action: #selector(onIncrement(_:)), for: .touchUpInside)
titleLabel.contentMode = .left
@@ -56,4 +65,5 @@
titleLabel.text = "Hi, This is an example UI!"
titleLabel.translatesAutoresizingMaskIntoConstraints = false
+ titleLabel.textColor = .blue // 1️⃣ Moved from `awakeFromNib`
}
The generated view after maintenance in iOS Simulator looks as shown below:
Summary
An example above shows that converting the simple Xib-file to Swift source code is an easy doable task. The few things needs attention:
- View settings made in awakeFromNib method have to be moved to setupUI method.
- The connections from controls made via IBAction methods have to be reestablished manually via target-action assignments.
Downloads
- Example Xcode project: XibAndStoryboardsConversionApp.zip