pvllnspk
pvllnspk

Reputation: 5767

Swift: declare protocols inside classes

In java I have:

public class Event {

        public enum State {
            PENDING,
            UPCOMING,
            ACTIVE,
            FINISHED,
            FAILURE
        }

        public interface Callback {
            void onUpdated();
            void onStateChanged(State state);
        }

        private State state;
        private Callback mCallback;
    }

How can I create something similar in Swift? Seems like I can not declare protocol inside class. But when I declare protocol outside I can not access State enum. Thanks.

I want to have something like

class Event {

    protocol Delegate {
        func onUpdated();
        func onStateChanged(state: State);
    }

    enum State {
        case PENDING
        case UPCOMING
        case ACTIVE
        case FINISHED
        case FAILURE
    }

    var delegate: Delegate?
}

Upvotes: 2

Views: 1740

Answers (2)

dfrib
dfrib

Reputation: 73186

You can access State using Event.State

/* delegate protocol */
protocol MyDelegate : class {
    func onStateChanged(state: Event.State) -> ()
}

/* default implementation of onStateChanged */
extension MyDelegate {
    func onStateChanged(state: Event.State) {
        print("State changed to: \(state)")
    }
}

/* your events */ 
class Event {
    enum State {
        case Pending
        case Upcoming
        case Active
        case Finished
        case Failure
    }

    weak var delegate: MyDelegate?

    var state : State {
        didSet {
            // call delegate
            delegate?.onStateChanged(state)
        }
    }

    init(state: State) {
        self.state = state
    }
}

Example usage with some naive handlers:

class EventHandler: MyDelegate {
    var myEvent : Event

    init(event: Event) {
        myEvent = event
        myEvent.delegate = self
    }
}

class AnotherHandler: MyDelegate {
    var myEvent : Event

    init(event: Event) {
        myEvent = event
        myEvent.delegate = self
    }

    func onStateChanged(state: Event.State) {
        if state == .Active {
            print("Event is active")
        }
        else {
            print("Event is not active")
        }
    }
}

/* example usage */
let handler1 = EventHandler(event: Event(state: .Pending))
let handler2 = AnotherHandler(event: Event(state: .Pending))

handler1.myEvent.state = .Active 
    /* prints "State changed to: Active" (uses default delegate function) */

handler2.myEvent.state = .Active 
    /* prints "Event is active" (uses custom delegate function) */

Upvotes: 1

user1585121
user1585121

Reputation:

You can access class scoped entities by using className.[entity] as in the following example:

protocol Callback {
  func onUpdated() -> Void
  func onStateChanged(state: MyClass.State) -> Void
}

class MyClass {
  enum State {
    case PENDING
    case UPCOMING
    case ACTIVE
    case FINISHED
    case FAILURE
  }

  private var state: State
  private var mCallback: Callback
}

Then you can just extend any other class with the Callback protocol like this:

class AnyOtherClass {
  ...
}

extension AnyOtherClass: Callback {
  func onUpdated() {
    ...
  }
  ...
}

Upvotes: 3

Related Questions