Bird
Raised Fist0
iOS Swiftmobile~20 mins

Protocol-oriented architecture in iOS Swift - Mini App: Build & Ship

Choose your learning style10 modes available
Build: User Profile
This screen shows a user profile using protocol-oriented architecture to separate data and UI logic.
Target UI
-------------------------
|       User Profile     |
|-----------------------|
| Name: John Appleseed  |
| Age: 28               |
| Email: john@apple.com |
|-----------------------|
| [Edit Profile]        |
-------------------------
Create a User protocol with properties for name, age, and email.
Create a struct that conforms to User protocol.
Create a protocol for displaying user info with a method to show user details.
Implement a view controller that uses these protocols to display user info.
Add an Edit Profile button that prints 'Edit tapped' when pressed.
Starter Code
iOS Swift
import UIKit

// TODO: Define User protocol here

// TODO: Create a struct conforming to User

// TODO: Define a protocol for displaying user info

class UserProfileViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        // TODO: Setup UI and display user info
    }

    @objc func editProfileTapped() {
        // TODO: Handle edit button tap
    }
}
Task 1
Task 2
Task 3
Task 4
Task 5
Task 6
Solution
iOS Swift
import UIKit

protocol User {
    var name: String { get }
    var age: Int { get }
    var email: String { get }
}

struct UserModel: User {
    let name: String
    let age: Int
    let email: String
}

protocol UserDisplayable {
    func display(user: User)
}

class UserProfileViewController: UIViewController, UserDisplayable {
    private let nameLabel = UILabel()
    private let ageLabel = UILabel()
    private let emailLabel = UILabel()
    private let editButton = UIButton(type: .system)

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        setupUI()

        let user = UserModel(name: "John Appleseed", age: 28, email: "john@apple.com")
        display(user: user)
    }

    func setupUI() {
        nameLabel.translatesAutoresizingMaskIntoConstraints = false
        ageLabel.translatesAutoresizingMaskIntoConstraints = false
        emailLabel.translatesAutoresizingMaskIntoConstraints = false
        editButton.translatesAutoresizingMaskIntoConstraints = false

        nameLabel.font = UIFont.systemFont(ofSize: 18, weight: .bold)
        ageLabel.font = UIFont.systemFont(ofSize: 16)
        emailLabel.font = UIFont.systemFont(ofSize: 16)

        editButton.setTitle("Edit Profile", for: .normal)
        editButton.addTarget(self, action: #selector(editProfileTapped), for: .touchUpInside)

        view.addSubview(nameLabel)
        view.addSubview(ageLabel)
        view.addSubview(emailLabel)
        view.addSubview(editButton)

        NSLayoutConstraint.activate([
            nameLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 40),
            nameLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),

            ageLabel.topAnchor.constraint(equalTo: nameLabel.bottomAnchor, constant: 20),
            ageLabel.leadingAnchor.constraint(equalTo: nameLabel.leadingAnchor),

            emailLabel.topAnchor.constraint(equalTo: ageLabel.bottomAnchor, constant: 20),
            emailLabel.leadingAnchor.constraint(equalTo: nameLabel.leadingAnchor),

            editButton.topAnchor.constraint(equalTo: emailLabel.bottomAnchor, constant: 40),
            editButton.centerXAnchor.constraint(equalTo: view.centerXAnchor)
        ])
    }

    func display(user: User) {
        nameLabel.text = "Name: \(user.name)"
        ageLabel.text = "Age: \(user.age)"
        emailLabel.text = "Email: \(user.email)"
    }

    @objc func editProfileTapped() {
        print("Edit tapped")
    }
}

We defined a User protocol with the required properties. Then, UserModel struct conforms to it, holding actual user data.

The UserDisplayable protocol declares a method to display user info. The UserProfileViewController conforms to this protocol and implements the method to update UI labels.

The UI is built programmatically with labels and a button. The button triggers a method that prints a message when tapped, simulating an edit action.

Final Result
Completed Screen
-------------------------
|       User Profile     |
|-----------------------|
| Name: John Appleseed  |
| Age: 28               |
| Email: john@apple.com |
|-----------------------|
| [Edit Profile]        |
-------------------------
Tapping 'Edit Profile' prints 'Edit tapped' in the console.
Stretch Goal
Add a protocol for editable users with a method to update email, and implement it in UserModel.
💡 Hint
Create a protocol EditableUser with a method updateEmail(newEmail: String). Make UserModel conform and add a mutating method to change email.

Practice

(1/5)
1. What is the main purpose of a protocol in Swift's protocol-oriented architecture?
easy
A. To store data persistently in an app
B. To define a blueprint of methods and properties that conforming types must implement
C. To create a concrete class with implemented methods
D. To handle user interface layout automatically

Solution

  1. Step 1: Understand what a protocol is

    A protocol defines a set of rules or requirements for methods and properties that any conforming type must implement.
  2. Step 2: Differentiate from other concepts

    Protocols do not implement functionality themselves but specify what must be implemented, unlike classes or structs.
  3. Final Answer:

    To define a blueprint of methods and properties that conforming types must implement -> Option B
  4. Quick Check:

    Protocol = Blueprint for behavior [OK]
Hint: Protocols specify required methods and properties only [OK]
Common Mistakes:
  • Confusing protocols with classes or structs
  • Thinking protocols store data
  • Assuming protocols handle UI layout
2. Which of the following is the correct syntax to declare a protocol named Drivable with a method drive()?
easy
A. func Drivable() { drive() }
B. class Drivable { func drive() }
C. struct Drivable { func drive() }
D. protocol Drivable { func drive() }

Solution

  1. Step 1: Recall protocol declaration syntax

    Protocols are declared with the keyword protocol followed by the protocol name and curly braces containing method signatures.
  2. Step 2: Identify correct method declaration

    The method drive() is declared without a body inside the protocol.
  3. Final Answer:

    protocol Drivable { func drive() } -> Option D
  4. Quick Check:

    Protocol syntax = protocol + name + method signatures [OK]
Hint: Protocols use 'protocol' keyword, not class or struct [OK]
Common Mistakes:
  • Using class or struct instead of protocol keyword
  • Adding method bodies inside protocol
  • Incorrect function declaration syntax
3. Given the code below, what will be printed when car.start() is called?
protocol Startable {
  func start()
}

struct Car: Startable {
  func start() {
    print("Car started")
  }
}

let car = Car()
car.start()
medium
A. Car started
B. start() method not implemented
C. Compilation error
D. No output

Solution

  1. Step 1: Check protocol conformance

    The struct Car conforms to Startable and implements the required start() method.
  2. Step 2: Analyze method call output

    Calling car.start() executes the method which prints "Car started" to the console.
  3. Final Answer:

    Car started -> Option A
  4. Quick Check:

    Implemented method prints output [OK]
Hint: Implemented protocol methods run normally [OK]
Common Mistakes:
  • Assuming missing implementation error
  • Thinking protocol methods print automatically
  • Confusing compilation errors with runtime
4. Identify the error in the following code snippet:
protocol Runnable {
  func run()
}

struct Athlete: Runnable {
  func run(distance: Int) {
    print("Running \(distance) meters")
  }
}
medium
A. Structs cannot conform to protocols
B. Protocol Runnable cannot have methods
C. Method signature in Athlete does not match protocol requirement
D. Missing return type in run() method

Solution

  1. Step 1: Compare protocol and struct method signatures

    The protocol requires func run() with no parameters, but Athlete implements func run(distance: Int) which has a parameter.
  2. Step 2: Understand conformance rules

    Method signatures must match exactly for conformance; differing parameters cause a mismatch error.
  3. Final Answer:

    Method signature in Athlete does not match protocol requirement -> Option C
  4. Quick Check:

    Method signatures must match exactly [OK]
Hint: Method signatures must match protocol exactly [OK]
Common Mistakes:
  • Adding parameters to protocol methods in implementation
  • Thinking structs can't conform to protocols
  • Ignoring method signature differences
5. You want to create a flexible system where different types can be "playable" with a play() method, and some can also be "recordable" with a record() method. Which protocol-oriented approach below best supports this design?
hard
A. Define separate protocols Playable and Recordable, then have types conform to one or both as needed
B. Create a single protocol with both play() and record() methods, and require all types to implement both
C. Use a base class with play() and record() methods and inherit from it
D. Implement play() and record() as global functions

Solution

  1. Step 1: Understand protocol composition

    Defining separate protocols allows types to conform only to behaviors they support, making the design flexible and reusable.
  2. Step 2: Evaluate other options

    Single protocol forces all types to implement all methods, base class limits flexibility, and global functions do not enforce behavior contracts.
  3. Final Answer:

    Define separate protocols Playable and Recordable, then have types conform to one or both as needed -> Option A
  4. Quick Check:

    Separate protocols = flexible conformance [OK]
Hint: Use multiple protocols for flexible behavior [OK]
Common Mistakes:
  • Forcing all types to implement all methods
  • Using inheritance instead of protocols
  • Not leveraging protocol composition
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard