SwiftUI

SwiftUI 사진 가져오기(1)

Daesiker 2021. 3. 17. 15:31
반응형

[참조]

Document-Based Apps Using SwiftUI
SwiftUI makes it easier than ever to create document-based apps that work with the iOS document interaction system. In this tutorial, you'll learn how to create a SwiftUI document-based meme-maker app.
https://www.raywenderlich.com/14971928-document-based-apps-using-swiftui#toc-anchor-013

 


개요

xCode의 multi-platform 프로젝트를 사용해서 swiftUI를 통해 해당 디바이스의 사진에 접근해서 새로운 파일로 만들어 주는 프로젝트에 대해 공부할 예정이다. 앞의 링크를 통해 완성된 프로젝트를 다운 받을 수 있다.

이미지를 추가하면 이미지의 상단과 하단에 Text를 적는 공간이 생기고 거기에 원하는 Text를 입력하면 사진이 새로운 확장자로 변환이 되어서 나온다.

 


프로젝트 구조

멀티 플랫폼 프로젝트를 보면 총 4개의 폴더가 기본으로 생성된다. 멀티 프로젝트에서 소스파일을 새로 만들면 Target이라는 부분을 볼 수 있는데 여기서 iOS에서 사용할 것인지 macOS에서 사용할 것인지 아니면 둘다 사용할것인지 정해준다. Shared는 말그대로 iOS와 macOS에서 둘다 사용가능한 파일들을 나열한다. iOS 폴더에는 Target이 iOS만 설정되있는 파일과 Info.plist가 있고 macOS에는 macOS만 타깃인 파일들과 Info.plist, macOS.entiltements 파일이 있다.

 


Meme.swift

import Foundation

struct Meme: Codable {
  var imageData: Data?
  var topText: String
  var bottomText: String
}

Image와 Text로 이루어진 구조체이다. 데이터를 받고 내보내는 과정에서 encoding과 decoding이 필요하기 때문에 Codable 프로토콜을 채택했다.

 

MemeMakerDocument.swift

import SwiftUI
import UniformTypeIdentifiers

extension UTType {
  static let memeDocument = UTType(exportedAs: "com.raywenderlich.MemeMaker.meme")
}

struct MemeMakerDocument: FileDocument {
  var meme: Meme

  init(imageData: Data? = nil, topText: String = "Top Text", bottomText: String = "Bottom Text") {
    self.meme = Meme(imageData: imageData, topText: topText, bottomText: bottomText)
  }

  static var readableContentTypes: [UTType] { [.memeDocument] }

  init(configuration: ReadConfiguration) throws {
    guard let data = configuration.file.regularFileContents else {
      throw CocoaError(.fileReadCorruptFile)
    }
    meme = try JSONDecoder().decode(Meme.self, from: data)
  }

  func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
    let data = try JSONEncoder().encode(meme)
    return .init(regularFileWithContents: data)
  }
}

 

UniformTypeIdentifiers

UTI는 Apple에서 특정 파일유형, 데이터 유형, 디렉토리 같은 유형에 대한 고유 식별자를 나타낸다. 이것을 통해 기존의 사용하는 jpg, docs, ppt 등의 확장자가 아닌 나만의 확장자를 만들어 현 APP에서만 open할 수 있게 가능하다.

우선 macOS 폴더의 Info.plist와 iOS 폴더의 Info.plist에 Exported Type Identifiers를 추가하여 나만의 확장자를 만들어준다.

Description에는 파일의 설명을 대한 부분을 작성하고 Identifier은 이 확장자를 식별할 수 있게 도와주는 식별자가 들어있다. 그다음 Extensions는 이 파일의 확장자 이름이 담겨있다. Conforms to Type Identifier에는 새롭게 만든 이 Exported Type이 채용하는 프로토콜의 종류들을 나열한 것이다. 여기서는 "Public.data", "public.content"를 채용하는데 아마 가장 기본적인 UTI 프로토콜인 것 같다.

 

extension UTType {
  static let memeDocument = UTType(exportedAs: "com.raywenderlich.MemeMaker.meme")
}

현 프로젝트에서는 extension을 통해 exportedAs 파라미터에 아까 만든 확장자의 identifier을 추가하여 UTType에 새로운 확장자를 추가하였다.

 

FileDocument

앱에서 문서를 읽고 쓸 수 있게 도와주는 프로토콜이다.

struct MemeMakerDocument: FileDocument {
  var meme: Meme

  init(imageData: Data? = nil, topText: String = "Top Text", bottomText: String = "Bottom Text") {
    self.meme = Meme(imageData: imageData, topText: topText, bottomText: bottomText)
  }
  
}

우선 구조체에 사용할 변수와 init을 만들어준다. 변수는 전에 만든 Meme구조체를 사용하고 init에는 String만 nil일 때 기본값을 주었다.

 

static var readableContentTypes: [UTType] { [.memeDocument] }

  init(configuration: ReadConfiguration) throws {
    guard let data = configuration.file.regularFileContents else {
      throw CocoaError(.fileReadCorruptFile)
    }
    meme = try JSONDecoder().decode(Meme.self, from: data)
  }

  func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
    let data = try JSONEncoder().encode(meme)
    return .init(regularFileWithContents: data)
  }

이 1개의 변수와 2개의 함수는 FileDocument의 필수 함수 및 변수이다.

 

readableContentTypes

readableContentTypes는 열 수 있는 파일 형식을 나열하는 UTType 자료구조로 된 배열이다. 여기 안에 열고 싶은 확장자들을 입력하면 된다. 이 프로젝트에서는 앞서 만든 memeDocument만 배열안에 넣었다.

 

func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper

이 함수에서는 데이터를 인코딩한 뒤에 파일시스템의 노드로 바꿔주는 함수이다. init이 실행되기 전에 이 함수가 호출되어서 meme을 인코딩한 data를 FileWrapper 클래스로 반환시켜준다.

 

init(configuration: ReadConfiguration) throws

이 init은 존재하는 문서를 열려고 할 때 호출된다. fileWrapper 로 만든 데이터를 통해 Meme을 data로 디코딩하여 문서를 열어준다.

반응형

'SwiftUI' 카테고리의 다른 글

SwiftUI 사진 가져오기(3)  (0) 2021.03.20
SwiftUI 사진 가져오기(2)  (0) 2021.03.19
SwiftUI TabView  (1) 2021.03.02
SwiftUI GroupBox, Menu  (0) 2021.02.26
swiftUI List, Navigation  (2) 2021.02.25