관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] @_spi(Private) import 개념 (#@_api, Swift Private Interface, 프레임워크, 모듈) 본문

iOS 응용 (swift)

[iOS - swift] @_spi(Private) import 개념 (#@_api, Swift Private Interface, 프레임워크, 모듈)

jake-kim 2023. 8. 1. 01:15

@_spi 개념

  • swift의 접근 제어자는 open, public, internal, fileprivate, private이 있지만 프레임워크 사이의 또 다른 접근 제어자가 존재
  • SPI(Swift Private Interface)도 외부에 노출할 인터페이스 제어가 가능
  • @_spi(Private) 키워드를 property, func, class 등 앞에 붙이면 이 것을 접근하려면 사용하는 쪽에서 @_spi(Private)으로 import해야 접근이 가능
    • 접근제어자보다, @_spi(Private)우선순위가 더욱 커서 public으로 열어주어도 @_spi(Private) 없이 접근 불가
// Jake 프레임워크
@_spi(Private) public func myPrivateFunc() {}

// Jake 프레임워크를 사용하는 쪽
@_spi(Private) import Jake

예제

  • 예제로 사용할 프레임워크 생성
    • Xcode > 파일 추가 > Framework

  • 생성 완료

  • 예제로 사용할 .swift파일 생성

import Foundation

open class JakeString {
    public var name = "jake"
    
    public init() {
    }
    
    @_spi(Private) public func myPrivateFunc() {}
}
  • 이 프레임워크를 사용할 App 프로젝트 생성

  • Target > General > Frameworks, Libraries, and Embedded Content 영역으로 아까 만든 프레임워크 .xcodeproj파일을 드래그 앤 드롭
    • 주의) 프레임워크 프로젝트를 반드시 닫고 드래그 앤 드롭

(드래그 앤 드롭 후 + 버튼을 눌러서 product 파일도 추가하면 프레임워크 추가 완료)

  • Jake 프레임크를 import하고 @_spi(Private)를 붙인 myPrivateFunc()에 접근하려하면 컴파일 에러가 발생

  • import문에 @_spi를 사용하면 접근이 가능
import UIKit
//import Jake
@_spi(Private) import Jake

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let jakeString = JakeString()
        jakeString.myPrivateFunc()
    }
}

(빌드 성공)

정리

  • @_spi는 프레임워크 간의 또 다른 접근제어자이며, swift의 접근제어자 키워드 (open, public, internal, fileprivate, private)보다 우선순위가 높음
  • 마치 짝꿍처럼 @_spi가 선언된 프로퍼티를 사용하려면 이를 사용하는 쪽에서 import문 앞에 @_spi키워드를 선언해야 사용이 가능
  • 일반적으로 외부에 노출시키지 않아도 되는 정보지만, 필요한 순간에 꼭 써야하는 경우, @_spi를 붙여서 이 프로퍼티를 쓰려면 @_spi를 꼭 붙여서 사용하라는 의미로 사용하는 의도

* 전체 코드: https://github.com/JK0369/ExSPI

* 참고

https://forums.swift.org/t/implement-a-private-api-in-swift/47920

Comments