Slide 1

Slide 1 text

Re:valua t ion https://fril.jp/ L ead & Delight User F irst Ownership Fail Smart 1SPQFSUZ8SBQQFST͕΋ͨΒ͢ ৽͍͠4XJGUϓϩάϥϛϯά !J04%$+BQBO

Slide 2

Slide 2 text

J04&OHJOFFS 3BLVUFO JOD ϥΫϚ "CPVU.F EBSRVSP :VLJ,VSPEB !EBSRVSP !EBSRVSP

Slide 3

Slide 3 text

1SPQFSUZ8SBQQFST

Slide 4

Slide 4 text

1SPQFSUZ8SBQQFST w "WBJMBCMF4XJGU w ϓϩύςΟΞΫηεʹԠͯ͡ڍಈΛXSBQ w ϓϩύςΟΠϯελϯε͝ͱʹσʔλΛอ࣋Մೳ w ॳظ஋஗Ԇ࣮ߦ

Slide 5

Slide 5 text

6TFS%FGBVMUT&YBNQMF @propertyWrapper struct UserDefault { var wrappedValue: T { get { return UserDefaults.standard .object(forKey: key) as? T ?? defaultValue } set { UserDefaults.standard.set(newValue, forKey: key) } } }

Slide 6

Slide 6 text

6TFS%FGBVMUT&YBNQMF @propertyWrapper struct UserDefault { let key: String let defaultValue: T init(_ key: String, defaultValue: T) { self.key = key self.defaultValue = defaultValue UserDefaults.standard .register(defaults: [key: defaultValue]) } var wrappedValue: T { … } }

Slide 7

Slide 7 text

6TFS%FGBVMUT&YBNQMF struct Foo { @UserDefault("IS_LOGGED_IN", defaultValue: false) static var isLoggedIn: Bool } Foo.isLoggedIn = true // UserDefaults.standard.object(forKey: "IS_LOGGED_IN") -> 1 Foo.isLoggedIn = false // UserDefaults.standard.object(forKey: "IS_LOGGED_IN") -> 0

Slide 8

Slide 8 text

6TFS%FGBVMUT&YBNQMF

Slide 9

Slide 9 text

4UBUF&YBNQMF struct LandmarkList: View { @State var showFavoriteOnly = true var body: some View { NavigationView { List { Toggle(isOn: $showFavoriteOnly) { Text("Favorite Only") } … } … }

Slide 10

Slide 10 text

4UBUF&YBNQMF @propertyWrapper public struct State : DynamicProperty, BindingConvertible { …… /// The current state value. public var wrappedValue: Value { get nonmutating set } …… /// Produces the binding referencing this state value public var projectedValue: Binding { get } }

Slide 11

Slide 11 text

7BMJEBUJPO&YBNQMF @propertyWrapper struct Validate { var wrappedValue: Value? var isValid: Bool { guard let value = wrappedValue else { return false } return validateion(value) } private let validateion: (Value) -> Bool private let messageClosure: (Value) -> String init(_ validation: @escaping (Value) -> Bool, message messageClosure: @escaping (Value) -> String) { self.validateion = validation self.messageClosure = messageClosure } }

Slide 12

Slide 12 text

7BMJEBUJPO&YBNQMF enum StringValidationType { case email case phoneNumber var regex: String { switch self { case .email: return #"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\.[A-Za- z]{2,64}"# case .phoneNumber: return "^[0-9]{6,14}$" } } }

Slide 13

Slide 13 text

7BMJEBUJPO&YBNQMF extension Validate where Value == String { init(_ type: StringValidationType) { self.init({ $0.range(of: type.regex, options: .regularExpression) != nil }, message: { "Error:\($0) does not match email" }) } }

Slide 14

Slide 14 text

7BMJEBUJPO&YBNQMF struct Foo { @Validate(.email) var email: String? @Validate(.phoneNumber) var phoneNumber: String? var isValidAll: Bool { _email.isValid && _phoneNumber.isValid } } var foo = Foo() foo.email = "abc@example.com" foo.phoneNumber = "09012341234" foo.isValidAll // -> "true"

Slide 15

Slide 15 text

ந৅Խ

Slide 16

Slide 16 text

ந৅Խ w ܧঝ w 1SPUPDPM w &YUFOTJPOT w 1SPQFSUZ8SBQQFST

Slide 17

Slide 17 text

ந৅Խ 1SPQFSZ8SBQQFST ࣮૷ίετ ந৅౓ 1SPUPDPM &YUFOTJPOT ܧঝ

Slide 18

Slide 18 text

ల๬ ΞʔΩςΫνϟ ϑϨʔϜϫʔΫ σβΠϯύλʔϯ 044ϥΠϒϥϦ

Slide 19

Slide 19 text

·ͱΊ

Slide 20

Slide 20 text

·ͱΊ 1SPQFSUZ8SBQQFST w ΑΓந৅తʹػೳΛϓϩύςΟͷΈʹఏڙͰ͖Δ w ϘΠϥʔϓϨʔτͷলུʹͳΔ w !YYY@YYYYYYͱ͍ͬͨಠࣗͷγϯλοΫε

Slide 21

Slide 21 text

4XJGU&WPMVUJPO1SPQPTBM IUUQTHJUIVCDPNBQQMFTXJGUFWPMVUJPOCMPCNBTUFSQSPQPTBMTQSPQFSUZXSBQQFSTNE

Slide 22

Slide 22 text

5IBOLZPV