Slide 1

Slide 1 text

Swift Package all the things! Federico Zanetello Μ£Μ£Μ£Μ£Μ£ fivestars.blog β€’ @zntfdr

Slide 2

Slide 2 text

fivestars.blog WWDCNotes.com Bangkok Metro

Slide 3

Slide 3 text

What's a Swift Package? β€” New way to build frameworks β€” Swi! project since 2015 β€” Xcode 11 ❀ iOS Apps β€” Swi!, Objective-C, Objective-C++, C, or C++ β€” Can bundle code, binaries, assets, ...

Slide 4

Slide 4 text

Why should we use one? β€” modularization β€” single-responsibility β€” testability β€” share between different projects/platforms β€” blessed by ο£Ώ β€” fun β€” easy to use β€” ...much more

Slide 5

Slide 5 text

Getting Started

Slide 6

Slide 6 text

MyApp

Slide 7

Slide 7 text

Create a Swift Package 1. Open your project 2. File > New > Swi! Package... 3. Name it and add it to your project

Slide 8

Slide 8 text

Create a Swift Package (1/2)

Slide 9

Slide 9 text

Create a Swift Package (2/2)

Slide 10

Slide 10 text

Done!

Slide 11

Slide 11 text

Add Package to your App 1. Open app Project Editor 2. Add the package under Frameworks, Libraries, and Embedded Content

Slide 12

Slide 12 text

Add Package to your App (1/2)

Slide 13

Slide 13 text

Add Package to your App (2/2)

Slide 14

Slide 14 text

Done!

Slide 15

Slide 15 text

The Package Structure β”œβ”€β”€ .gitignore β”œβ”€β”€ Package.swift β”œβ”€β”€ README.md β”œβ”€β”€ Sources β”‚ └── MyLibrary β”‚ └── MyLibrary.swift └── Tests β”œβ”€β”€ MyLibraryTests β”‚ β”œβ”€β”€ MyLibraryTests.swift β”‚ └── XCTestManifests.swift └── LinuxMain.swift

Slide 16

Slide 16 text

Package.swift // swift-tools-version:5.3 import PackageDescription let package = Package( name: "MyLibrary", products: [ .library(name: "MyLibrary", targets: ["MyLibrary"]), ], dependencies: [], targets: [ .target(name: "MyLibrary", dependencies: []), .testTarget(name: "MyLibraryTests", dependencies: ["MyLibrary"]), ] )

Slide 17

Slide 17 text

The Package Structure β”œβ”€β”€ .gitignore β”œβ”€β”€ Package.swift β”œβ”€β”€ README.md β”œβ”€β”€ Sources β”‚ └── MyLibrary β”‚ └── MyLibrary.swift └── Tests β”œβ”€β”€ MyLibraryTests β”‚ β”œβ”€β”€ MyLibraryTests.swift β”‚ └── XCTestManifests.swift └── LinuxMain.swift

Slide 18

Slide 18 text

MyLibrary.swift struct MyLibrary { var text = "Hello, World!" }

Slide 19

Slide 19 text

MyLibrary.swift import SwiftUI public struct MyCoolView: View { public init() {} public var body: some View { Text("This view is totally cool") } }

Slide 20

Slide 20 text

Package.swift // swift-tools-version:5.3 import PackageDescription let package = Package( name: "MyLibrary", platforms: [.iOS(.v13)], products: [ .library(name: "MyLibrary", targets: ["MyLibrary"]), ], dependencies: [], targets: [ .target(name: "MyLibrary", dependencies: []), .testTarget(name: "MyLibraryTests", dependencies: ["MyLibrary"]), ] )

Slide 21

Slide 21 text

MyLibrary.swift import SwiftUI public struct MyCoolView: View { public init() {} public var body: some View { Text("This view is totally cool") } }

Slide 22

Slide 22 text

Add images import SwiftUI public struct MyCoolView: View { public init() {} public var body: some View { VStack { Image("coolImage", bundle: .module) Text("This view is totally cool") } } }

Slide 23

Slide 23 text

The Package Structure β”œβ”€β”€ .gitignore β”œβ”€β”€ Package.swift β”œβ”€β”€ README.md β”œβ”€β”€ Sources β”‚ └── MyLibrary β”‚ β”œβ”€β”€ Assets.xcassets β”‚ └── MyLibrary.swift └── Tests β”œβ”€β”€ MyLibraryTests β”‚ β”œβ”€β”€ MyLibraryTests.swift β”‚ └── XCTestManifests.swift └── LinuxMain.swift

Slide 24

Slide 24 text

import SwiftUI public struct MyCoolView: View { public init() {} public var body: some View { VStack { Image("coolImage", bundle: .module) Text("This view is totally cool") } } }

Slide 25

Slide 25 text

Add localization import SwiftUI public struct MyCoolView: View { public init() {} public var body: some View { VStack { Image("coolImage", bundle: .module) Text("cool_view_text", bundle: .module) } } }

Slide 26

Slide 26 text

Package.swift // swift-tools-version:5.3 import PackageDescription let package = Package( name: "MyLibrary", defaultLocalization: LanguageTag("en"), platforms: [.iOS(.v13)], products: [ .library(name: "MyLibrary", targets: ["MyLibrary"]), ], dependencies: [], targets: [ .target(name: "MyLibrary", dependencies: []), .testTarget(name: "MyLibraryTests", dependencies: ["MyLibrary"]), ] )

Slide 27

Slide 27 text

The Package Structure β”œβ”€β”€ .gitignore β”œβ”€β”€ Package.swift β”œβ”€β”€ README.md β”œβ”€β”€ Sources β”‚ └── MyLibrary β”‚ β”œβ”€β”€ Assets.xcassets β”‚ β”œβ”€β”€ Localizations // ! Arbitrary name β”‚ β”‚ β”œβ”€β”€ en.lproj β”‚ β”‚ β”‚ └── Localizable.strings β”‚ β”‚ └── th.lproj β”‚ β”‚ └── Localizable.strings β”‚ └── MyLibrary.swift └── Tests β”œβ”€β”€ MyLibraryTests β”‚ β”œβ”€β”€ MyLibraryTests.swift β”‚ └── XCTestManifests.swift └── LinuxMain.swift

Slide 28

Slide 28 text

Add localization import SwiftUI public struct MyCoolView: View { public init() {} public var body: some View { VStack { Image("coolImage", bundle: .module) Text("cool_view_text", bundle: .module) } } }

Slide 29

Slide 29 text

Testing our package

Slide 30

Slide 30 text

Testing a package // swift-tools-version:5.3 import PackageDescription let package = Package( name: "MyLibrary", defaultLocalization: LanguageTag("en"), platforms: [.iOS(.v13)], products: [ .library(name: "MyLibrary", targets: ["MyLibrary"]), ], dependencies: [], targets: [ .target(name: "MyLibrary", dependencies: []), .testTarget(name: "MyLibraryTests", dependencies: ["MyLibrary"]), ] )

Slide 31

Slide 31 text

Testing a package β”œβ”€β”€ .gitignore β”œβ”€β”€ Package.swift β”œβ”€β”€ README.md β”œβ”€β”€ Sources β”‚ └── MyLibrary β”‚ β”œβ”€β”€ Assets.xcassets β”‚ β”œβ”€β”€ Localizations β”‚ β”‚ β”œβ”€β”€ en.lproj β”‚ β”‚ β”‚ └── Localizable.strings β”‚ β”‚ └── th.lproj β”‚ β”‚ └── Localizable.strings β”‚ └── MyLibrary.swift └── Tests β”œβ”€β”€ MyLibraryTests β”‚ β”œβ”€β”€ MyLibraryTests.swift β”‚ └── XCTestManifests.swift └── LinuxMain.swift

Slide 32

Slide 32 text

Testing a package β”œβ”€β”€ .gitignore β”œβ”€β”€ Package.swift β”œβ”€β”€ README.md β”œβ”€β”€ Sources β”‚ └── MyLibrary β”‚ β”œβ”€β”€ Assets.xcassets β”‚ β”œβ”€β”€ Localizations β”‚ β”‚ β”œβ”€β”€ en.lproj β”‚ β”‚ β”‚ └── Localizable.strings β”‚ β”‚ └── th.lproj β”‚ β”‚ └── Localizable.strings β”‚ └── MyLibrary.swift └── Tests └── MyLibraryTests └── MyLibraryTests.swift

Slide 33

Slide 33 text

Testing a package import XCTest @testable import MyLibrary final class MyLibraryTests: XCTestCase { func testExample() { XCTAssertEqual(..., "Hello, World!") } }

Slide 34

Slide 34 text

Using our package

Slide 35

Slide 35 text

Using our package import MyLibrary import SwiftUI struct ContentView: View { var body: some View { MyCoolView() } }

Slide 36

Slide 36 text

Done! ! import MyLibrary import SwiftUI struct ContentView: View { var body: some View { MyCoolView() } }

Slide 37

Slide 37 text

External packages

Slide 38

Slide 38 text

Adding an External Package 1. File > Swi! Packages > Add Package Dependency 2. Insert dependency .git URL and follow wizard

Slide 39

Slide 39 text

Adding an External Package (1/2)

Slide 40

Slide 40 text

Adding an External Package (2/2)

Slide 41

Slide 41 text

Adding an External Package (2/2)

Slide 42

Slide 42 text

Adding an External Package (2/2)

Slide 43

Slide 43 text

Done!

Slide 44

Slide 44 text

Adding an External Package import AStack import MyLibrary import SwiftUI struct ContentView: View { var body: some View { AHStack { MyCoolView() AnotherCoolView() } } }

Slide 45

Slide 45 text

Adding an External Package import AStack import MyLibrary import SwiftUI struct ContentView: View { var body: some View { AHStack { MyCoolView() AnotherCoolView() } } }

Slide 46

Slide 46 text

Swift Package all the things! Federico Zanetello Μ£Μ£Μ£Μ£Μ£ fivestars.blog β€’ @zntfdr