Waldo joins Tricentis, expanding mobile testing for higher-quality mobile apps – Learn more
App Development

Getting Started with SwifterSwift Extensions

Nabendu Biswas
Nabendu Biswas
Getting Started with SwifterSwift Extensions
December 27, 2022
6
min read

SwifterSwift is a collection of built-in methods which are much easier to use than the original Swift methods. They extend the functionality of the original methods, as well as properties like buttons, text fields, image views, calendars, and many others. The code to use them is much easier, so it helps to get an app up in less time, as you get built-in components with more functionalities. These methods and functions can be thought of as bootstrap components, which are much faster to use than writing the entire CSS code yourself.

In this post, we're going to build an app with an image view, text fields, and a button using SwifterSwift methods. After that, we're also going to do unit testing on the project.

The Setup

First, open Xcode and create a new project by clicking on New > Project.

First, open Xcode and create a new project by clicking on New > Project.

Next, a pop-up will be opened. Click on App and then the Next button.

Next, a pop-up will be opened. Click on App and then the Next button.

Now, give the product name, which is SwifterSwiftTutorials, in our case. The interface should be Storyboard, and we're also including the tests in our project.

Now, give the product name, which is SwifterSwiftTutorials, in our case.

In the next pop-up, just click on the Create button.

In the next pop-up, just click on the Create button.

Removing Storyboard from Project

We'll remove Storyboard from the project because we're going to create fields through SwifterSwift. So, we'll remove the Main file from our project. But make sure to click on Move to Trash in the pop-up.

Removing Storyboard from Project

Now, first, click on the root of the project, and after that, click on SwifterSwiftTutorials in TARGETS on the opened screen. Then click on the Info tab, and after that, expand Scene Configuration. Once the Storyboard Name row is shown, click on the minus sign (-) to remove the row.

Now, first, click on the root of the project, and after that, click on SwifterSwiftTutorials in TARGETS on the opened screen.

Next, click on the Build Settings tab and make sure the All and Combined sub-tabs are clicked. After that, find Info.plist Values and scroll down.

Next, click on the Build Settings tab and make sure the All and Combined sub-tabs are clicked.

Upon scrolling down, we'll see the UIKit Main Storyboard File Base Name row with Main as value.

Upon scrolling down, we'll see the UIKit Main Storyboard File Base Name row with Main as value.

After that, remove the text of Main by double-clicking on it and removing it.

After that, remove the text of Main by double-clicking on it and removing it.

Now, in the SceneDelegate file, add the below code. Here, we've added a new windowScene, which will be used instead of the Main file.


    window = UIWindow(windowScene: windowScene)
    window?.makeKeyAndVisible()
    window?.rootViewController = UINavigationController(rootViewController: ViewController())

Installing SwifterSwift

We can install SwifterSwift in a lot of ways. It also includes the pod install method. But we can also install external packages through the package manager in Xcode.

For this, we need to first go to the GitHub page of SwifterSwift and get the HTTPS link from the Code dropdown.

Next, go to the root directory and click on the PROJECT with the name SwifterSwiftTutorials. After that, go to the Package Dependencies tab and click on the plus (+) sign.

Next, go to the root directory and click on the PROJECT with the name SwifterSwiftTutorials

A pop-up will be opened. In the search bar, give the HTTPS link from the GitHub step earlier. Upon pressing enter, we'll get our SwifterSwift package. Now, click on the Add Package button.

In the search bar, give the HTTPS link from the GitHub step earlier.

In the next pop-up, just click on the Add Package button.

In the next pop-up, just click on the Add Package button.

Now, in the project sidebar, we'll see Package Dependencies. And it'll show SwifterSwift along with version 5.3.0.

Now, in the project sidebar, we'll see Package Dependencies

Project with SwifterSwift Methods

Finally, we'll create our project with SwifterSwift Methods. Here, we've first imported SwifterSwift and then given a background and a title in the viewDidLoad method. We've also called the function setupNavigation from the viewDidLoad method. In the function setupNavigation, we're using the Navigation bar from SwifterSwift. We're using the setColors and setTitleFont functions in the Navigation bar to easily set the Colors and Title font.

On running the project, everything is working fine, and we'll get a navigation bar with the required text shown in the iPhone Simulator.


    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .systemCyan
        title = "Swifter Swift Tutorials"
        setupNavigation()
     }
     
     func setupNavigation() {
        navigationController?.navigationBar.setColors(background: .systemRed, text: .white)
        navigationController?.navigationBar.setTitleFont(.monospacedDigitSystemFont(ofSize: 25, weight: .heavy), color: .white)
     }
On running the project, everything is working fine, and we'll get a navigation bar with the required text shown in the iPhone Simulator.

Next, we'll add an image view to our project. Here, we've first created a lazy loading function called imageView in our project. It'll get the image from an image URL and return it.

Now, we're calling a new function setupViews from the viewDidLoad method. Here, we're again using the SwifterSwift Method of addSubviews, through which we're adding the imageView first in our app. After that, we're using the SwifterSwift Method of anchor to set the image in the correct position.

On running the app, the image is being shown perfectly in our iOS Simulator.


    lazy var imageView: UIImageView = {
        let imageView = UIImageView()
        imageView.layer.masksToBounds = true
        if let url = URL(string: "https://picsum.photos/id/870/640/300?grayscale&blur=2"){
          imageView.download(from: url, contentMode: .scaleAspectFill, placeholder: nil, completionHandler: nil)
       }
       return imageView
     }()
     
     ...
     
     func setupViews() {
        view.addSubviews([imageView])
        imageView.anchor(top: view.safeAreaLayoutGuide.topAnchor, left: view.safeAreaLayoutGuide.leftAnchor, bottom: nil, right: view.safeAreaLayoutGuide.rightAnchor, topConstant: 0, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: 0, heightConstant: 200)
     }
Next, we'll add an image view to our project.

More Fields with SwifterSwift Methods

Now, we'll add an email field in our app. For this, we'll once again create a lazy loading function called emailTextField in our project. In this function, we're using a UITextField and giving it some styles, including an envelope icon.

Now, in the addSubviews method, we're adding the emailTextField. After that, we're again using an anchor to set the email field in the correct position.

Upon running the app, the email field is being shown perfectly in our iOS Simulator.


    lazy var emailTextField: UITextField = {
        let textField = UITextField()
        textField.borderStyle = .line
        textField.addPaddingLeftIcon(UIImage(systemName: "envelope.fill")!, padding: 10)
        textField.textType = .emailAddress
        return textField
     }()
     
     ...
      emailTextField.anchor(top: imageView.bottomAnchor, left: view.safeAreaLayoutGuide.leftAnchor, bottom: nil, right: view.safeAreaLayoutGuide.rightAnchor, topConstant: 12, leftConstant: 12, bottomConstant: 0, rightConstant: 12, widthConstant: 0, heightConstant: 0)
More Fields with SwifterSwift Methods

Now, we'll add a password field in our app. For this, we'll again create a lazy loading function called passwordTextField in our project. In this function, we're using an UITextField and giving it some styles, including an eye icon.

Now, in the addSubviews method, we're adding the passwordTextField. After that, we're again using an anchor to set the email field in the correct position.

Upon running the app, the password field is being shown correctly in our iOS Simulator.


    lazy var passwordTextField: UITextField = {
        let textField = UITextField()
        textField.borderStyle = .line
        textField.addPaddingLeftIcon(UIImage(systemName: "eye.fill")!, padding: 10)
        textField.textType = .password
        return textField
     }()
     
     ...
      passwordTextField.anchor(top: emailTextField.bottomAnchor, left: view.safeAreaLayoutGuide.leftAnchor, bottom: nil, right: view.safeAreaLayoutGuide.rightAnchor, topConstant: 12, leftConstant: 12, bottomConstant: 0, rightConstant: 12, widthConstant: 0, heightConstant: 0)
Now, we'll add a password field in our app.

Finally, we'll add a button to our project. For this, again create a lazy loading function called loginButton in our project. Now, this button will have styles, and it'll also be calling a tapButton function through the addTarget function. Again, we're doing the same thing of adding it in addSubviews and setting it up with anchor.


    lazy var loginButton: UIButton = {
        let button = UIButton()
        button.setTitleForAllStates("Login")
        button.setTitleColorForAllStates(.systemPurple)
        button.addTarget(self, action: #selector(tapButton), for: .touchUpOutside)
        return button
     }()
     ...
      loginButton.anchor(top: passwordTextField.bottomAnchor, left: view.safeAreaLayoutGuide.leftAnchor, bottom: nil, right: view.safeAreaLayoutGuide.rightAnchor, topConstant: 12, leftConstant: 12, bottomConstant: 0, rightConstant: 12, widthConstant: 0, heightConstant: 0)

Finally, we'll create the tapButton function, which is an Objective-C function. Here, we're doing some basic validation, and after that, printing the entered fields.


    @objc func tapButton() {
        guard !emailTextField.isEmpty else {
          print("Please enter email")
          return
        }
        guard !passwordTextField.isEmpty else {
          print("Please enter Password")
          return
        }
        guard emailTextField.hasValidEmail else {
           print("Please enter a valid Email")
           return
        }
        print("You entered - \(String(describing: emailTextField.text)) and \(String(describing: passwordTextField.text))")
     }
Finally, we'll create the tapButton function, which is an Objective-C function.

Testing the App

We'll test the app with the built-in XCTest in Xcode. The initial steps to prepare for test cases can be taken from our post on XCUI methods.

We'll need a unique ID for the element of our app for testing. This project will use the Accessibility Inspector to get the unique IDs. You can open it by clicking on Xcode > Open Developer Tool > Accessibility Inspector.

Also, open the running iOS Simulator on the side, and use the pointer from Accessibility Inspector to click on different elements. Here, we've clicked on Header to get its Label, or unique ID, which is Swifter Swift Tutorials for this element.

Writing and Executing Test Cases

It's time to write our test cases. Create the file SwifterSwiftTests inside the Tests folder. Here, we're overriding the rootElement to have staticTexts of the label.

Next, we'll create the checkLabel function, which will use XCTAssert to check if the label exists.


    import XCTest

    public class SwifterSwiftTests: BaseTest{
       override var rootElement: XCUIElement{
        return app.staticTexts["Swifter Swift Tutorials"]
      }
    
       lazy var labelText = app.staticTexts["Swifter Swift Tutorials"]
    
       @discardableResult
         func checkLabel(completion: Completion = nil) -> Self {
          log("Check if Label text exists")
          XCTAssert(labelText.exists)
          return self
        }
    }

Next, in the BasicTests file, we'll call the SwifterSwiftTests class and then the checkLabel function. On clicking on the play test button in the project, our test will pass.


func testAll(){
        SwifterSwiftTests().checkLabel()
      }
Next, in the BasicTests file, we'll call the SwifterSwiftTests class and then the checkLabel function

What We've Covered

In this post, we talked about using the open-source methods of SwifterSwift in an iOS project. We created a simple project in Xcode without Storyboard, using easy-to-use methods from SwifterSwift. We also wrote simple test cases using XCTest. 

But the setup is very complicated. And writing test cases in XCTest is also complex, with knowledge of Swift required. 

To test your app without complicated setups or having to write test cases, try  Waldo. You're only required to provide the APK or IPA file. Then you get to interact with the mobile app like a real user. Waldo automatically generates test cases and emails you the results.

Automated E2E tests for your mobile app

Creating tests in Waldo is as easy as using your app!
Learn more about our Automate product, or try our live testing tool Sessions today.

Reproduce, capture, and share bugs fast!

Waldo Sessions helps mobile teams reproduce bugs, while compiling detailed bug reports in real time.