iPad를 구매할 때 Apple Pencil을 대부분 같이 구매하게 됩니다.
만약 iPad를 지원하는 App을 만든다면, 그 App에 Apple Pencil을 이용한 기능을 개발해야한다면?
그래서 오늘 공부할 것은 Pencil Kit! (사실 제가 공부 해보고 싶었음..ㅎ)
기초적으로 Apple Pencil을 이용하여 그림을 그릴 수 있는 방법부터 살펴보자!
Pencil Kit을 이용하여 그림을 그릴 수 있는 가장 중요한 두가지 요소는
PKCanvasView 와 PKToolPicker
항상 그렇듯 공식 문서를 통해 천천히 살펴보자!
PKCanvasView는 Apple Pencil을 이용하거나 손가락을 사용해서 그린 콘텐츠를 앱에 표시해줍니다.
class PKCanvasView : UIScrollView
Scroll View를 상속하니 뷰를 그릴 때 크기를 지정해주면 좋지만, 자동적으로 사이즈를 조정해준다고 합니다!
Swift에 Delegate가 빠져서는 안되겠죠?
protocol PKCanvasViewDelegate
Canvas view에 그려진 내용이나 선택한 도구의 변경사항에 응답하기 위해 사용됩니다.
총 4가지의 종류가 있습니다.
현재 도면의 내용이 변경되었음을 알리는 메소드
optional func canvasViewDrawingDidChange(_ canvasView: PKCanvasView)
이전에 그린 내용을 표시할 준비가 되었음을 알리는 메소드
optional func canvasViewDidFinishRendering(_ canvasView: PKCanvasView)
사용자가 현재 선택한 도구로 그리기 시작했음을 알리는 메소드
optional func canvasViewDidBeginUsingTool(_ canvasView: PKCanvasView)
사용자가 사용중인 도구로 그리기 종료했음을 알리는 메소드
optional func canvasViewDidEndUsingTool(_ canvasView: PKCanvasView)
Canvas View에서는 그림을 그리는 도화지 역할을 할 뿐만 아니라 그림을 그리는 도구의 케이스 역할도 제공 해줍니다.
@MainActor var tool: PKTool { get set }
어라라? 평소에 자주 보지 못하던 MainActor라는 녀석이 있군요. 이 친구가 어떤 친구인지 잠깐 알아보고 가죠!
https://developer.apple.com/documentation/swift/mainactor
공식문서에 따르면
메인 디스패치 대기열과 동일한 싱글톤 작업자.
디스패치 큐를 사용할 때 좀더 편리하게 사용하기 위해 만들어진 친구 같군요!
중요한 친구 같으니 나중에 좀 더 집중적으로 알아보도록 합시다!
Canvas View에 Pencil만 이용할 수 있게, 혹은 손으로도 그릴 수 있게 설정이 가능합니다.
var drawingPolicy: PKCanvasViewDrawingPolicy { get set }
enum PKCanvasViewDrawingPolicy : UInt, @unchecked Sendable
// 기본 그리기 설정
case: default
// 어떤 입력도 캔버스 그리기에 허용
case: anyInput
// Apple Pencil 전용
case: pencilOnly
Canvas View에서 제스쳐, 터치 이벤트를 인식할 수 있게해주는 속성
var drawingGestureRecognizer: UIGestureRecognizer { get }
마지막으로 Canvas View에 그려진 데이터를 저장시킬 수 있게해주는 속성
var drawing: PKDrawing { get set }
이제 유저가 그림을 그릴 수 있게 도구를 제공해야 겠죠??!
Apple pencil을 사용할 때 필요한 지우개라던지 형광펜이라던지! 모두 PKToolPicker에서 제공합니다!
class PKToolPicker : NSObject
PKToolPicker에서는 그리기 도구, 색상 및 추가 옵션을 표시할 수 있는 팔레트를 관리한다고 하네요!
ToolPicker를 만들어주기만 해도 화면 어느 곳에서나 움직여서 사용자가 관리할 수 있게 하다니 너무 편하겠군요..!
사용자가 그림을 그리다가 도구를 바꾸면 Canvas View에서 감지를 해 변경할 수 있게 해줘야 겠네요.
인스턴스로 초기화 시켜 ToolPicker로 만들어줄 수 있습니다!
var toolPicker: PKToolPicker!
toolPicker = PKToolPicker()
그릴 도구를 선택하고 반영할 수 있게, ToolPicker에 Cavas View를 추가시켜 확인할 수 있게 하는 메소드
func addObserver(_ observer: PKToolPickerObserver)
추가가 있으니 해제할 수도 있게!
func removeObserver(_ observer: PKToolPickerObserver)
이제 ToolPicker의 변경사항이 있을 경우의 ToolPickerObserver 델리게이트를 살펴봅시다!
// ToolPicker 자체를 변경할 때 (다른 그리기 도구로 변경할 때)
optional func toolPickerSelectedToolDidChange(_ toolPicker: PKToolPicker)
// ToolPicker에서 제공하는 눈금자를 표시하거나 숨겨졌을 때 발생하는 메소드
optional func toolPickerIsRulerActiveDidChange(_ toolPicker: PKToolPicker)
// ToolPicker가 유저한테서 보여지거나 숨겨질때 발생하는 메소드
optional func toolPickerVisibilityDidChange(_ toolPicker: PKToolPicker)
// ToolPicker에서 그리기 도구가 변경될 때 발생하는 메소드
optional func toolPickerFramesObscuredDidChange(_ toolPicker: PKToolPicker)
마지막으로 ToolPicker가 사용자에게 보여지기 않는다면 의미가 없겠죠?!
그걸 위해 설정해야 하는 메소드!
func setVisible(
_ visible: Bool,
forFirstResponder responder: UIResponder
)
보여지기 위해서 파라미터로 Bool 값을 받는것은 알겠는데 뒤에 있는 forFirstResponder 파라미터는 무엇일까요?
ToolPicker와 처음 응답할 수 있게 연결해주는 값이라고 합니다!
그럼 이제 공부했던 것들을 써먹어 봅시다!
import UIKit
import PencilKit
class DrawViewController: UIViewController, PKCanvasViewDelegate, PKToolPickerObserver {
// 캔버스 뷰를 만들어줌
@IBOutlet weak var canvasView: PKCanvasView!
// Tool Picker를 만들어줄 변수 생성
var toolPicker: PKToolPicker!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
canvasView.delegate = self
// Tool Picker 인스턴스 생성
toolPicker = PKToolPicker()
// Tool Picker를 사용자에게 보여줄 수 있게 설정
toolPicker.setVisible(true, forFirstResponder: canvasView)
// Tool Picker에 Canvas View가 인식할 수 있게 설정
toolPicker.addObserver(canvasView)
// 해당 뷰 컨트롤러에도 같은 설정
toolPicker.addObserver(self)
// Tool Picker 위치 설정
updateLayout(for: toolPicker)
// Canvas View가 처음 인식할 수 있게 설정
canvasView.becomeFirstResponder()
}
// 툴피커가 변경될 때
func toolPickerFramesObscuredDidChange(_ toolPicker: PKToolPicker) {
updateLayout(for: toolPicker)
}
// 툴피커가 숨겨지거나 안보이게할 때
func toolPickerVisibilityDidChange(_ toolPicker: PKToolPicker) {
updateLayout(for: toolPicker)
}
// 툴피커는 적당한 크기의 캔버스위에 표시 되지만 작은 크기의 혹은 조정된 크기의 캔버스에는 화면 일부에 표시될 수 있게 함
func updateLayout(for toolPicker: PKToolPicker) {
let obscuredFrame = toolPicker.frameObscured(in: view)
// 툴피커가 캔버스 위에 표시될 때는 실행 취소 및 다시 실행 버튼이 추가.
if obscuredFrame.isNull {
canvasView.contentInset = .zero
navigationItem.leftBarButtonItems = []
} else { // 그렇지 않다면 캔버스 뷰의 상단에 툴피커를 위치시키고, 실행 취소 및 다시 실행 버튼이 사라짐
canvasView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: view.bounds.maxY - obscuredFrame.minY, right: 0)
}
canvasView.scrollIndicatorInsets = canvasView.contentInset
}
}
끝!
참고 자료 : https://developer.apple.com/documentation/pencilkit
'iOS' 카테고리의 다른 글
AVCapture Session (0) | 2022.10.17 |
---|---|
iOS ARKit LiDAR 에 대해 (0) | 2022.09.27 |
View Life Cycle (0) | 2022.09.06 |
Watch Connectivity (watchOS) (0) | 2022.07.31 |
DispatchQueue, sync 와 async (0) | 2022.06.10 |