0
0
iOS Swiftmobile~20 mins

Dependency injection in iOS Swift - Mini App: Build & Ship

Choose your learning style9 modes available
Build: Greeting Screen
This screen shows a greeting message using a service injected via dependency injection.
Target UI
-----------------------
| Greeting Screen      |
|---------------------|
| Hello, User!        |
|                     |
| [Change Greeting]   |
-----------------------
Create a GreetingService protocol with a method to get a greeting string.
Implement a DefaultGreetingService that returns a greeting message.
Inject the GreetingService into the GreetingViewController via initializer.
Display the greeting message in a UILabel.
Add a UIButton labeled 'Change Greeting' that changes the greeting message when tapped.
Starter Code
iOS Swift
import UIKit

protocol GreetingService {
    func getGreeting() -> String
}

class GreetingViewController: UIViewController {
    private let greetingService: GreetingService
    private let greetingLabel = UILabel()
    private let changeButton = UIButton(type: .system)

    init(greetingService: GreetingService) {
        self.greetingService = greetingService
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        setupViews()
        // TODO: Display initial greeting
        // TODO: Add action for button tap
    }

    private func setupViews() {
        greetingLabel.translatesAutoresizingMaskIntoConstraints = false
        greetingLabel.textAlignment = .center
        greetingLabel.font = UIFont.systemFont(ofSize: 24)
        view.addSubview(greetingLabel)

        changeButton.translatesAutoresizingMaskIntoConstraints = false
        changeButton.setTitle("Change Greeting", for: .normal)
        view.addSubview(changeButton)

        NSLayoutConstraint.activate([
            greetingLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            greetingLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            changeButton.topAnchor.constraint(equalTo: greetingLabel.bottomAnchor, constant: 20),
            changeButton.centerXAnchor.constraint(equalTo: view.centerXAnchor)
        ])
    }
}
Task 1
Task 2
Task 3
Solution
iOS Swift
import UIKit

protocol GreetingService {
    func getGreeting() -> String
}

class DefaultGreetingService: GreetingService {
    private var toggle = false
    func getGreeting() -> String {
        toggle.toggle()
        return toggle ? "Hello, User!" : "Welcome back!"
    }
}

class GreetingViewController: UIViewController {
    private let greetingService: GreetingService
    private let greetingLabel = UILabel()
    private let changeButton = UIButton(type: .system)

    init(greetingService: GreetingService) {
        self.greetingService = greetingService
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        setupViews()
        greetingLabel.text = greetingService.getGreeting()
        changeButton.addTarget(self, action: #selector(changeGreeting), for: .touchUpInside)
    }

    private func setupViews() {
        greetingLabel.translatesAutoresizingMaskIntoConstraints = false
        greetingLabel.textAlignment = .center
        greetingLabel.font = UIFont.systemFont(ofSize: 24)
        view.addSubview(greetingLabel)

        changeButton.translatesAutoresizingMaskIntoConstraints = false
        changeButton.setTitle("Change Greeting", for: .normal)
        view.addSubview(changeButton)

        NSLayoutConstraint.activate([
            greetingLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            greetingLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            changeButton.topAnchor.constraint(equalTo: greetingLabel.bottomAnchor, constant: 20),
            changeButton.centerXAnchor.constraint(equalTo: view.centerXAnchor)
        ])
    }

    @objc private func changeGreeting() {
        greetingLabel.text = greetingService.getGreeting()
    }
}

We created a GreetingService protocol to define a contract for greeting messages. The DefaultGreetingService class implements this protocol and toggles between two greetings each time getGreeting() is called.

The GreetingViewController receives the service via its initializer, demonstrating dependency injection. This means the controller does not create the service itself but gets it from outside, making the code easier to test and change.

We set the initial greeting in viewDidLoad and update the label when the button is tapped by calling the service again.

Final Result
Completed Screen
-----------------------
| Greeting Screen      |
|---------------------|
| Hello, User!        |
|                     |
| [Change Greeting]   |
-----------------------
When the user taps 'Change Greeting', the greeting text toggles between 'Hello, User!' and 'Welcome back!'
Stretch Goal
Add a second implementation of GreetingService that returns greetings in another language and allow switching between services.
💡 Hint
Create a new class implementing GreetingService with different greetings. Add a segmented control to switch the service instance injected into the view controller.