Protocol은 메서드, 프로퍼티 등 필요한 기능의 최소 규칙(blueprint)을 정의한다. 그리고 class, struct, enum에 의해 채택(adopted)되어 그 요구사항이 구현된다. 프로토콜의 요구사항을 충족시킨 타입을 프로토콜을 준수(conform)했다라고 한다.
프로토콜에 요구사항을 추가하거나 추가적인 기능을 구현하기 위해 프로토콜을 extend 할 수 있다.
프로토콜은 여러 개 채택할 수 있다. 만약 클래스를 상속한다면 채택할 프로토콜 앞에 상속할 클래스를 명시해야 한다.
protocol SomeProtocol {
// protocol definition goes here
}
class SomeClass: SomeSuperclass, FirstProtocol, AnotherProtocol {
// class definition goes here
}
프로토콜은 instance 또는 type property를 요구할 수 있다. property name, type, gettable, settable만을 명시하며, 항상 var
로 선언한다.
protocol SomeProtocol {
var mustBeSettable: Int { get set }
var doesNotNeedToBeSettable: Int { get }
}
그러므로 프로퍼티 요구를 준수할 때, gettable and settable 프로퍼티는 let
이 될 수 없고, read-only도 될 수 없다.
Always prefix type property requirements with the static keyword when you define them in a protocol. This rule pertains even though type property requirements can be prefixed with the class or static keyword when implemented by a class:
타입 프로퍼티 요구는 항상 static
키워드만을 사용한다.
protocol AnotherProtocol {
static var someTypeProperty: Int { get set }
}
프로토콜은 stored property 또는 computed property를 구분해서 명시하지 않는다. 프로퍼티 요구를 준수할 때 원하는대로 해석할 수 있다.
프로토콜은 instance 또는 type method를 요구할 수 있다. method를 정의할 때 curly braces {}
와 method body는 작성하지 않는다.
파라미터의 기본값도 작성하지 않는다.
Variadic parameters are allowed, subject to the same rules as for normal methods. Default values, however, can’t be specified for method parameters within a protocol’s definition.
프로토콜의 메서드가 자신이 속한 value type의 인스턴스 값을 변경해야 하는 경우, mutating
키워드를 붙여주어야 한다.
protocol Togglable {
mutating func toggle()
}
프로토콜도 하나의 data type이다.
Delegation은 인스턴스의 책임을 넘기는(Delegation) 디자인 패턴 중 하나로, protocol에 의해 구현된다.
// View
class UITableView : UIScrollView {
weak var delegate: UITableViewDelegate?
}
// Controller
class UIViewController: UITableViewDelegate {
let tableView = UITableView()
override func viewDidLoad() {
tableView.delegate = self
}
// method implement...
}
view.delegate = self
AnyObject
를 상속해서 채택 가능한 타입을 class로 제한할 수 있다.
protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {
// class-only protocol definition goes here
}
프로토콜을 선언하면서 선택적 요구사항을 정의할 수도 있다.
선택적 요구사항을 정의한 프로토콜은 @objc
붙이며, @objc
protocol은 class 타입에 의해서만 채택될 수 있다.
@objc protocol CounterDataSource {
@objc optional func increment(forCount count: Int) -> Int
@objc optional var fixedIncrement: Int { get }
}
Extensions은 class, struct, enum 또는 protocol에 기능을 추가하는 것이다.
extension
키워드를 사용해 선언한다.
extension SomeType {
// new functionality to add to SomeType goes here
}
extension
을 통해서 더 많은 프로토콜을 채택할 수 있다.
extension SomeType: SomeProtocol, AnotherProtocol {
// implementation of protocol requirements goes here
}
Extensions can add computed instance properties and computed type properties to existing types.
// extension으로 코드를 깔끔하게
// self가 navigation controller라면, navigation 되어 보여지는 view를 리턴
extension UIViewController {
var contents: UIViewController {
if let navcon = self as? UINavigationController {
return navcon.visibleViewController ?? self
} else {
return self
}
}
}
// Extension.swift
extension UIView {
public var width: CGFloat {
return frame.size.width
}
public var height: CGFloat {
return frame.size.height
}
public var top: CGFloat {
return frame.origin.y
}
public var bottom: CGFloat {
return frame.origin.y + frame.size.height
}
public var left: CGFloat {
return frame.origin.x
}
public var right: CGFloat {
return frame.origin.x + frame.size.width
}
}
https://docs.swift.org/swift-book/LanguageGuide/Protocols.html
https://docs.swift.org/swift-book/LanguageGuide/Extensions.html