Share
Embed
バリデーション付きフォームを宣言的に実装する / Declaratively Implementing a Form with Validation
Studio Rookery
May 30, 2024
Transcript
229 slides
-
͜ΕʹόϦσʔγϣϯॲཧΛ͍ͯ͘͠ struct RegisterView: View { @State var id = ""
@State var password = "" @State var favoriteFruit: Fruit? var body: some View { ScrollView { VStack(spacing: 16) { MyTextField(name: "ID", text: $id) MyTextField(name: "PW", text: $password) FruitPicker(name: "͖ͳϑϧʔπ", selection: $favoriteFruit) Button("ొ") { } .buttonStyle(.myButtonStyle) } .padding() } } } -
·ͣঢ়ଶ͔Βߟ͑Δ struct RegisterView: View { @State var id = ""
@State var password = "" @State var favoriteFruit: Fruit? var body: some View { ScrollView { VStack(spacing: 16) { MyTextField(name: "ID", text: $id) MyTextField(name: "PW", text: $password) FruitPicker(name: "͖ͳϑϧʔπ", selection: $favoriteFruit) Button("ొ") { } .buttonStyle(.myButtonStyle) } .padding() } } } -
͜͏ͳΔ @State var id = “" @State var idErrorMessage: String?
@State var isIDErrorActive = false -
͜͏ͳΔ @State var id = “" @State var idErrorMessage: String?
@State var isIDErrorActive = false Τϥʔϝοηʔδͷ༗ແΛද͢ OJMͳΒΤϥʔϝοηʔδͳ͠ TPNFͳΒΤϥʔϝοηʔδ͋Γ -
͜͏ͳΔ @State var id = “" @State var idErrorMessage: String?
@State var isIDErrorActive = false ઢͷ༗ແΛද͢ -
͜͏ͳΔ @State var id = “" @State var idErrorMessage: String?
@State var isIDErrorActive = false ϑΟʔϧυʹ͖ͭม͕ඞཁʂ -
ͭ·Γ͜Ε͕ @State var id = "" @State var password =
"" @State var favoriteFruit: Fruit? -
͜͏ͳΔ @State var id = "" @State var idErrorMessage: String?
@State var isIDErrorActive = false @State var password = "" @State var passwordErrorMessage: String? @State var isPasswordErrorActive = false @State var favoriteFruit: Fruit? @State var favoriteFruitErrorMessage: String? @State var isFavoriteFruitErrorActive = false -
͜͏ͳΔ @State var id = "" @State var idErrorMessage: String?
@State var isIDErrorActive = false @State var password = "" @State var passwordErrorMessage: String? @State var isPasswordErrorActive = false @State var favoriteFruit: Fruit? @State var favoriteFruitErrorMessage: String? @State var isFavoriteFruitErrorActive = false ͢Ͱʹେมͦ͏͚ͩͲ ·۪ͣʹ࡞ΔͷͰ͜ΕͰਐΊΔ -
func register() { idErrorMessage = nil isIDErrorActive = false passwordErrorMessage
= nil isPasswordErrorActive = false favoriteFruitErrorMessage = nil isFavoriteFruitErrorActive = false if id.isEmpty || id.count > 20 { idErrorMessage = "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isIDErrorActive = true } if password.isEmpty || password.count > 20 { passwordErrorMessage = "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isPasswordErrorActive = true } if favoriteFruit == nil { favoriteFruitErrorMessage = "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" isFavoriteFruitErrorActive = true } if isIDErrorActive || isPasswordErrorActive || isFavoriteFruitErrorActive { return } let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) Task { await API.send(request) } } -
func register() { idErrorMessage = nil isIDErrorActive = false passwordErrorMessage
= nil isPasswordErrorActive = false favoriteFruitErrorMessage = nil isFavoriteFruitErrorActive = false if id.isEmpty || id.count > 20 { idErrorMessage = "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isIDErrorActive = true } if password.isEmpty || password.count > 20 { passwordErrorMessage = "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isPasswordErrorActive = true } if favoriteFruit == nil { favoriteFruitErrorMessage = "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" isFavoriteFruitErrorActive = true } if isIDErrorActive || isPasswordErrorActive || isFavoriteFruitErrorActive { return } let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) Task { await API.send(request) } } Τϥʔͷঢ়ଶΛϦηοτ -
func register() { idErrorMessage = nil isIDErrorActive = false passwordErrorMessage
= nil isPasswordErrorActive = false favoriteFruitErrorMessage = nil isFavoriteFruitErrorActive = false if id.isEmpty || id.count > 20 { idErrorMessage = "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isIDErrorActive = true } if password.isEmpty || password.count > 20 { passwordErrorMessage = "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isPasswordErrorActive = true } if favoriteFruit == nil { favoriteFruitErrorMessage = "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" isFavoriteFruitErrorActive = true } if isIDErrorActive || isPasswordErrorActive || isFavoriteFruitErrorActive { return } let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) Task { await API.send(request) } } όϦσʔγϣϯΛύε͠ͳ͚ΕΤϥʔঢ়ଶʹ͢Δ -
func register() { idErrorMessage = nil isIDErrorActive = false passwordErrorMessage
= nil isPasswordErrorActive = false favoriteFruitErrorMessage = nil isFavoriteFruitErrorActive = false if id.isEmpty || id.count > 20 { idErrorMessage = "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isIDErrorActive = true } if password.isEmpty || password.count > 20 { passwordErrorMessage = "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isPasswordErrorActive = true } if favoriteFruit == nil { favoriteFruitErrorMessage = "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" isFavoriteFruitErrorActive = true } if isIDErrorActive || isPasswordErrorActive || isFavoriteFruitErrorActive { return } let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) Task { await API.send(request) } } શ෦ύε͚ͨ࣌ͩ͠"1*Λ͛Δ -
͜Ε͕ MyTextField(name: "ID", text: $id) MyTextField(name: "PW", text: $password) FruitPicker(name:
"͖ͳϑϧʔπ", selection: $favoriteFruit) -
͜͏ͳΔ MyTextField(name: "ID", text: $id) .onChange(of: id) { _ in
isIDErrorActive = false } MyTextField(name: "PW", text: $password) .onChange(of: password) { _ in isPasswordErrorActive = false } FruitPicker(name: "͖ͳϑϧʔπ", selection: $favoriteFruit) .onChange(of: favoriteFruit) { _ in isFavoriteFruitErrorActive = false } -
.PEJ fi FSʹΤϥʔঢ়ଶΛ͚ͩ͢ MyTextField(name: "ID", text: $id) .errorStyled(isActive: isIDErrorActive, errorMessage:
idErrorMessage) .onChange(of: id) { _ in isIDErrorActive = false } MyTextField(name: "PW", text: $password) .errorStyled(isActive: isPasswordErrorActive, errorMessage: passwordErrorMessage) .onChange(of: password) { _ in isPasswordErrorActive = false } FruitPicker(name: "͖ͳϑϧʔπ", selection: $favoriteFruit) .errorStyled(isActive: isFavoriteFruitErrorActive, errorMessage: favoriteFruitErrorMessage) .onChange(of: favoriteFruit) { _ in isFavoriteFruitErrorActive = false } ৄࡉׂѪ -
struct RegisterView: View { @State var id = "" @State
var idErrorMessage: String? @State var isIDErrorActive = false @State var password = "" @State var passwordErrorMessage: String? @State var isPasswordErrorActive = false @State var favoriteFruit: Fruit? @State var favoriteFruitErrorMessage: String? @State var isFavoriteFruitErrorActive = false var body: some View { ScrollView { VStack(spacing: 16) { MyTextField(name: "ID", text: $id) .errorStyled(isActive: isIDErrorActive, errorMessage: idErrorMessage) .onChange(of: id) { _ in isIDErrorActive = false } MyTextField(name: "PW", text: $password) .errorStyled(isActive: isPasswordErrorActive, errorMessage: passwordErrorMessage) .onChange(of: password) { _ in isPasswordErrorActive = false } FruitPicker(name: "͖ͳϑϧʔπ", selection: $favoriteFruit) .errorStyled(isActive: isFavoriteFruitErrorActive, errorMessage: favoriteFruitErrorMessage) .onChange(of: favoriteFruit) { _ in isFavoriteFruitErrorActive = false } Button("ొ") { register() } .buttonStyle(.myButtonStyle) } .padding() } } func register() { idErrorMessage = nil isIDErrorActive = false passwordErrorMessage = nil isPasswordErrorActive = false favoriteFruitErrorMessage = nil isFavoriteFruitErrorActive = false if id.isEmpty || id.count > 20 { idErrorMessage = "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isIDErrorActive = true } if password.isEmpty || password.count > 20 { passwordErrorMessage = "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isPasswordErrorActive = true } if favoriteFruit == nil { favoriteFruitErrorMessage = "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" isFavoriteFruitErrorActive = true } if isIDErrorActive || isPasswordErrorActive || isFavoriteFruitErrorActive { return } let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) Task { await API.send(request) } } } -
struct RegisterView_ver1: View { @State var id = "" @State
var idErrorMessage: String? @State var isIDErrorActive = false @State var password = "" @State var passwordErrorMessage: String? @State var isPasswordErrorActive = false @State var favoriteFruit: Fruit? @State var favoriteFruitErrorMessage: String? @State var isFavoriteFruitErrorActive = false var body: some View { ScrollView { VStack(spacing: 16) { MyTextField(name: "ID", text: $id) .errorStyled(isActive: isIDErrorActive, errorMessage: idErrorMessage) .onChange(of: id) { _ in isIDErrorActive = false } MyTextField(name: "PW", text: $password) .errorStyled(isActive: isPasswordErrorActive, errorMessage: passwordErrorMessage) .onChange(of: password) { _ in isPasswordErrorActive = false } FruitPicker(name: "͖ͳϑϧʔπ", selection: $favoriteFruit) .errorStyled(isActive: isFavoriteFruitErrorActive, errorMessage: favoriteFruitErrorMessage) .onChange(of: favoriteFruit) { _ in isFavoriteFruitErrorActive = false } Button("ొ") { register() } .buttonStyle(.myButtonStyle) } .padding() } } func register() { idErrorMessage = nil isIDErrorActive = false passwordErrorMessage = nil isPasswordErrorActive = false favoriteFruitErrorMessage = nil isFavoriteFruitErrorActive = false if id.isEmpty || id.count > 20 { idErrorMessage = "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isIDErrorActive = true } if password.isEmpty || password.count > 20 { passwordErrorMessage = "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isPasswordErrorActive = true } if favoriteFruit == nil { favoriteFruitErrorMessage = "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" isFavoriteFruitErrorActive = true } if isIDErrorActive || isPasswordErrorActive || isFavoriteFruitErrorActive { return } let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) Task { await API.send(request) } } } !4UBUFଟ͗͢ !4UBUFΛ͍ͬͯΔͱςετॻ͚ͳ͍ -
struct RegisterView_ver1: View { @State var id = "" @State
var idErrorMessage: String? @State var isIDErrorActive = false @State var password = "" @State var passwordErrorMessage: String? @State var isPasswordErrorActive = false @State var favoriteFruit: Fruit? @State var favoriteFruitErrorMessage: String? @State var isFavoriteFruitErrorActive = false var body: some View { ScrollView { VStack(spacing: 16) { MyTextField(name: "ID", text: $id) .errorStyled(isActive: isIDErrorActive, errorMessage: idErrorMessage) .onChange(of: id) { _ in isIDErrorActive = false } MyTextField(name: "PW", text: $password) .errorStyled(isActive: isPasswordErrorActive, errorMessage: passwordErrorMessage) .onChange(of: password) { _ in isPasswordErrorActive = false } FruitPicker(name: "͖ͳϑϧʔπ", selection: $favoriteFruit) .errorStyled(isActive: isFavoriteFruitErrorActive, errorMessage: favoriteFruitErrorMessage) .onChange(of: favoriteFruit) { _ in isFavoriteFruitErrorActive = false } Button("ొ") { register() } .buttonStyle(.myButtonStyle) } .padding() } } func register() { idErrorMessage = nil isIDErrorActive = false passwordErrorMessage = nil isPasswordErrorActive = false favoriteFruitErrorMessage = nil isFavoriteFruitErrorActive = false if id.isEmpty || id.count > 20 { idErrorMessage = "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isIDErrorActive = true } if password.isEmpty || password.count > 20 { passwordErrorMessage = "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isPasswordErrorActive = true } if favoriteFruit == nil { favoriteFruitErrorMessage = "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" isFavoriteFruitErrorActive = true } if isIDErrorActive || isPasswordErrorActive || isFavoriteFruitErrorActive { return } let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) Task { await API.send(request) } } } ϨΠΞτͷίʔυͱൺΔͱ όϦσʔγϣϯॲཧ͗͢ -
TUSVDUΛ༻ҙ struct RegisterForm { } struct RegisterView: View { @State
var id = "" @State var idErrorMessage: String? @State var isIDErrorActive = false @State var password = "" @State var passwordErrorMessage: String? @State var isPasswordErrorActive = false @State var favoriteFruit: Fruit? @State var favoriteFruitErrorMessage: String? @State var isFavoriteFruitErrorActive = false var body: some View { ScrollView { VStack(spacing: 16) { MyTextField(name: "ID", text: $id) .errorStyled(isActive: isIDErrorActive, errorMessage: idErrorMessage) .onChange(of: id) { _ in isIDErrorActive = false } MyTextField(name: "PW", text: $password) .errorStyled(isActive: isPasswordErrorActive, errorMessage: passwordErrorMessage) .onChange(of: password) { _ in isPasswordErrorActive = false } FruitPicker(name: "͖ͳϑϧʔπ", selection: $favoriteFruit) .errorStyled(isActive: isFavoriteFruitErrorActive, errorMessage: favoriteFruitErrorMessage) .onChange(of: favoriteFruit) { _ in isFavoriteFruitErrorActive = false } Button("ొ") { register() } .buttonStyle(.myButtonStyle) } .padding() } } func register() { idErrorMessage = nil isIDErrorActive = false passwordErrorMessage = nil isPasswordErrorActive = false favoriteFruitErrorMessage = nil isFavoriteFruitErrorActive = false if id.isEmpty || id.count > 20 { idErrorMessage = "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isIDErrorActive = true } if password.isEmpty || password.count > 20 { passwordErrorMessage = "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isPasswordErrorActive = true } if favoriteFruit == nil { favoriteFruitErrorMessage = "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" isFavoriteFruitErrorActive = true } if isIDErrorActive || isPasswordErrorActive || isFavoriteFruitErrorActive { return } let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) Task { await API.send(request) } } } -
͜ͷ෦Λ struct RegisterForm { } struct RegisterView_ver1: View { @State
var id = "" @State var idErrorMessage: String? @State var isIDErrorActive = false @State var password = "" @State var passwordErrorMessage: String? @State var isPasswordErrorActive = false @State var favoriteFruit: Fruit? @State var favoriteFruitErrorMessage: String? @State var isFavoriteFruitErrorActive = false var body: some View { ScrollView { VStack(spacing: 16) { MyTextField(name: "ID", text: $id) .errorStyled(isActive: isIDErrorActive, errorMessage: idErrorMessage) .onChange(of: id) { _ in isIDErrorActive = false } MyTextField(name: "PW", text: $password) .errorStyled(isActive: isPasswordErrorActive, errorMessage: passwordErrorMessage) .onChange(of: password) { _ in isPasswordErrorActive = false } FruitPicker(name: "͖ͳϑϧʔπ", selection: $favoriteFruit) .errorStyled(isActive: isFavoriteFruitErrorActive, errorMessage: favoriteFruitErrorMessage) .onChange(of: favoriteFruit) { _ in isFavoriteFruitErrorActive = false } Button("ొ") { register() } .buttonStyle(.myButtonStyle) } .padding() } } func register() { idErrorMessage = nil isIDErrorActive = false passwordErrorMessage = nil isPasswordErrorActive = false favoriteFruitErrorMessage = nil isFavoriteFruitErrorActive = false if id.isEmpty || id.count > 20 { idErrorMessage = "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isIDErrorActive = true } if password.isEmpty || password.count > 20 { passwordErrorMessage = "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isPasswordErrorActive = true } if favoriteFruit == nil { favoriteFruitErrorMessage = "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" isFavoriteFruitErrorActive = true } if isIDErrorActive || isPasswordErrorActive || isFavoriteFruitErrorActive { return } let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) Task { await API.send(request) } } } -
Ҡಈ struct RegisterForm { @State var id = "" @State
var idErrorMessage: String? @State var isIDErrorActive = false @State var password = "" @State var passwordErrorMessage: String? @State var isPasswordErrorActive = false @State var favoriteFruit: Fruit? @State var favoriteFruitErrorMessage: String? @State var isFavoriteFruitErrorActive = false } struct RegisterView_ver1: View { var body: some View { ScrollView { VStack(spacing: 16) { MyTextField(name: "ID", text: $id) .errorStyled(isActive: isIDErrorActive, errorMessage: idErrorMessage) .onChange(of: id) { _ in isIDErrorActive = false } MyTextField(name: "PW", text: $password) .errorStyled(isActive: isPasswordErrorActive, errorMessage: passwordErrorMessage) .onChange(of: password) { _ in isPasswordErrorActive = false } FruitPicker(name: "͖ͳϑϧʔπ", selection: $favoriteFruit) .errorStyled(isActive: isFavoriteFruitErrorActive, errorMessage: favoriteFruitErrorMessage) .onChange(of: favoriteFruit) { _ in isFavoriteFruitErrorActive = false } Button("ొ") { register() } .buttonStyle(.myButtonStyle) } .padding() } } func register() { idErrorMessage = nil isIDErrorActive = false passwordErrorMessage = nil isPasswordErrorActive = false favoriteFruitErrorMessage = nil isFavoriteFruitErrorActive = false if id.isEmpty || id.count > 20 { idErrorMessage = "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isIDErrorActive = true } if password.isEmpty || password.count > 20 { passwordErrorMessage = "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isPasswordErrorActive = true } if favoriteFruit == nil { favoriteFruitErrorMessage = "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" isFavoriteFruitErrorActive = true } if isIDErrorActive || isPasswordErrorActive || isFavoriteFruitErrorActive { return } let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) Task { await API.send(request) } } } -
͜ͷ෦Λ struct RegisterForm { @State var id = "" @State
var idErrorMessage: String? @State var isIDErrorActive = false @State var password = "" @State var passwordErrorMessage: String? @State var isPasswordErrorActive = false @State var favoriteFruit: Fruit? @State var favoriteFruitErrorMessage: String? @State var isFavoriteFruitErrorActive = false } struct RegisterView_ver1: View { var body: some View { ScrollView { VStack(spacing: 16) { MyTextField(name: "ID", text: $id) .errorStyled(isActive: isIDErrorActive, errorMessage: idErrorMessage) .onChange(of: id) { _ in isIDErrorActive = false } MyTextField(name: "PW", text: $password) .errorStyled(isActive: isPasswordErrorActive, errorMessage: passwordErrorMessage) .onChange(of: password) { _ in isPasswordErrorActive = false } FruitPicker(name: "͖ͳϑϧʔπ", selection: $favoriteFruit) .errorStyled(isActive: isFavoriteFruitErrorActive, errorMessage: favoriteFruitErrorMessage) .onChange(of: favoriteFruit) { _ in isFavoriteFruitErrorActive = false } Button("ొ") { register() } .buttonStyle(.myButtonStyle) } .padding() } } func register() { idErrorMessage = nil isIDErrorActive = false passwordErrorMessage = nil isPasswordErrorActive = false favoriteFruitErrorMessage = nil isFavoriteFruitErrorActive = false if id.isEmpty || id.count > 20 { idErrorMessage = "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isIDErrorActive = true } if password.isEmpty || password.count > 20 { passwordErrorMessage = "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isPasswordErrorActive = true } if favoriteFruit == nil { favoriteFruitErrorMessage = "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" isFavoriteFruitErrorActive = true } if isIDErrorActive || isPasswordErrorActive || isFavoriteFruitErrorActive { return } let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) Task { await API.send(request) } } } -
Ҡಈ struct RegisterForm { @State var id = "" @State
var idErrorMessage: String? @State var isIDErrorActive = false @State var password = "" @State var passwordErrorMessage: String? @State var isPasswordErrorActive = false @State var favoriteFruit: Fruit? @State var favoriteFruitErrorMessage: String? @State var isFavoriteFruitErrorActive = false func register() -> RegisterRequest? { idErrorMessage = nil isIDErrorActive = false passwordErrorMessage = nil isPasswordErrorActive = false favoriteFruitErrorMessage = nil isFavoriteFruitErrorActive = false if id.isEmpty || id.count > 20 { idErrorMessage = "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isIDErrorActive = true } if password.isEmpty || password.count > 20 { passwordErrorMessage = "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isPasswordErrorActive = true } if favoriteFruit == nil { favoriteFruitErrorMessage = "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" isFavoriteFruitErrorActive = true } if isIDErrorActive || isPasswordErrorActive || isFavoriteFruitErrorActive { return nil } let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) return request } } struct RegisterView_ver1: View { var body: some View { ScrollView { VStack(spacing: 16) { MyTextField(name: "ID", text: $id) .errorStyled(isActive: isIDErrorActive, errorMessage: idErrorMessage) .onChange(of: id) { _ in isIDErrorActive = false } MyTextField(name: "PW", text: $password) .errorStyled(isActive: isPasswordErrorActive, errorMessage: passwordErrorMessage) .onChange(of: password) { _ in isPasswordErrorActive = false } FruitPicker(name: "͖ͳϑϧʔπ", selection: $favoriteFruit) .errorStyled(isActive: isFavoriteFruitErrorActive, errorMessage: favoriteFruitErrorMessage) .onChange(of: favoriteFruit) { _ in isFavoriteFruitErrorActive = false } Button("ొ") { register() } .buttonStyle(.myButtonStyle) } .padding() } } func register() { Task { await API.send(request) } } } -
!4UBUFෆཁ struct RegisterForm { @State var id = "" @State
var idErrorMessage: String? @State var isIDErrorActive = false @State var password = "" @State var passwordErrorMessage: String? @State var isPasswordErrorActive = false @State var favoriteFruit: Fruit? @State var favoriteFruitErrorMessage: String? @State var isFavoriteFruitErrorActive = false } struct RegisterForm { var id = "" var idErrorMessage: String? var isIDErrorActive = false var password = "" var passwordErrorMessage: String? var isPasswordErrorActive = false var favoriteFruit: Fruit? var favoriteFruitErrorMessage: String? var isFavoriteFruitErrorActive = false } -
EJE4FU͕͑ΔΑ͏ʹͳͬͨ struct RegisterForm { var id = "" { didSet
{ guard id != oldValue else { return } isIDErrorActive = false } } var password = "" { didSet { guard password != oldValue else { return } isPasswordErrorActive = false } } var favoriteFruit: Fruit? { didSet { guard favoriteFruit != oldValue else { return } isFavoriteFruitErrorActive = false } } } struct RegisterForm { var id = "" var idErrorMessage: String? var isIDErrorActive = false var password = "" var passwordErrorMessage: String? var isPasswordErrorActive = false var favoriteFruit: Fruit? var favoriteFruitErrorMessage: String? var isFavoriteFruitErrorActive = false } -
EJE4FU͕͑ΔΑ͏ʹͳͬͨ MyTextField(name: "ID", text: $id) .errorStyled(isActive: isIDErrorActive, errorMessage: idErrorMessage) .onChange(of:
id) { _ in isIDErrorActive = false } MyTextField(name: "PW", text: $password) .errorStyled(isActive: isPasswordErrorActive, errorMessage: passwordErrorMessage) .onChange(of: password) { _ in isPasswordErrorActive = false } FruitPicker(name: "͖ͳϑϧʔπ", selection: $favoriteFruit) .errorStyled(isActive: isFavoriteFruitErrorActive, errorMessage: favoriteFruitErrorMessage) .onChange(of: favoriteFruit) { _ in isFavoriteFruitErrorActive = false } MyTextField(name: "ID", text: $id) .errorStyled(isActive: isIDErrorActive, errorMessage: idErrorM MyTextField(name: "PW", text: $password) .errorStyled(isActive: isPasswordErrorActive, errorMessage: pa FruitPicker(name: "͖ͳϑϧʔπ", selection: $favoriteFruit) .errorStyled(isActive: isFavoriteFruitErrorActive, errorMessag -
ͭ·Γ͜Ε͕ struct RegisterView: View { @State var id = ""
@State var idErrorMessage: String? @State var isIDErrorActive = false @State var password = "" @State var passwordErrorMessage: String? @State var isPasswordErrorActive = false @State var favoriteFruit: Fruit? @State var favoriteFruitErrorMessage: String? @State var isFavoriteFruitErrorActive = false var body: some View { ScrollView { VStack(spacing: 16) { MyTextField(name: "ID", text: $id) .errorStyled(isActive: isIDErrorActive, errorMessage: idErrorMessage) .onChange(of: id) { _ in isIDErrorActive = false } MyTextField(name: "PW", text: $password) .errorStyled(isActive: isPasswordErrorActive, errorMessage: passwordErrorMessage) .onChange(of: password) { _ in isPasswordErrorActive = false } FruitPicker(name: "͖ͳϑϧʔπ", selection: $favoriteFruit) .errorStyled(isActive: isFavoriteFruitErrorActive, errorMessage: favoriteFruitErrorMessage) .onChange(of: favoriteFruit) { _ in isFavoriteFruitErrorActive = false } Button("ొ") { register() } .buttonStyle(.myButtonStyle) } .padding() } } func register() { idErrorMessage = nil isIDErrorActive = false passwordErrorMessage = nil isPasswordErrorActive = false favoriteFruitErrorMessage = nil isFavoriteFruitErrorActive = false if id.isEmpty || id.count > 20 { idErrorMessage = "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isIDErrorActive = true } if password.isEmpty || password.count > 20 { passwordErrorMessage = "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isPasswordErrorActive = true } if favoriteFruit == nil { favoriteFruitErrorMessage = "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" isFavoriteFruitErrorActive = true } if isIDErrorActive || isPasswordErrorActive || isFavoriteFruitErrorActive { return } let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) Task { await API.send(request) } } } -
ϑΝΠϧʹׂ struct RegisterView: View { @State var form = RegisterForm()
var body: some View { ScrollView { VStack(spacing: 16) { MyTextField(name: "ID", text: $form.id) .errorStyled(isActive: form.isIDErrorActive, errorMessage: form.idErrorMessage) MyTextField(name: "PW", text: $form.password) .errorStyled(isActive: form.isPasswordErrorActive, errorMessage: form.passwordErrorMessage) FruitPicker(name: "͖ͳϑϧʔπ", selection: $form.favoriteFruit) .errorStyled(isActive: form.isFavoriteFruitErrorActive, errorMessage: form.favoriteFruitErrorMessage) Button("ొ") { register() } .buttonStyle(.myButtonStyle) } .padding() } } func register() { guard let request = form.validate() else { return } Task { await API.send(request) } } } struct RegisterForm { var id = "" { didSet { guard id != oldValue else { return } isIDErrorActive = false } } var idErrorMessage: String? var isIDErrorActive = false var password = "" { didSet { guard password != oldValue else { return } isPasswordErrorActive = false } } var passwordErrorMessage: String? var isPasswordErrorActive = false var favoriteFruit: Fruit? { didSet { guard favoriteFruit != oldValue else { return } isFavoriteFruitErrorActive = false } } var favoriteFruitErrorMessage: String? var isFavoriteFruitErrorActive = false mutating func validate() -> RegisterRequest? { idErrorMessage = nil isIDErrorActive = false passwordErrorMessage = nil isPasswordErrorActive = false favoriteFruitErrorMessage = nil isFavoriteFruitErrorActive = false if id.isEmpty || id.count > 20 { idErrorMessage = "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isIDErrorActive = true } if password.isEmpty || password.count > 20 { passwordErrorMessage = "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isPasswordErrorActive = true } if favoriteFruit == nil { favoriteFruitErrorMessage = "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" isFavoriteFruitErrorActive = true } if isIDErrorActive || isPasswordErrorActive || isFavoriteFruitErrorActive { return nil } let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) return request } } -
ঢ়ଶͱϩδοΫΛTUSVDUΓग़ͨ͠ w 4XJGU6*ͷ߹ʹҾͬுΒΕͳ͘ͳͬͨ w EJE4FU͕͑ΔΑ͏ʹͳͬͨ w ςετͰ͖ΔΑ͏ʹͳͬͨ w 7JFXͷϑΝΠϧ6*ͷ͜ͱ͚ͩʹूத͢Εྑ͘ͳͬͨ w
ϑΝΠϧʹ͔Εͨ͜ͱʹΑͬͯݟ௨͠গ͠μϯʁ w ྫ͕؆୯ͳͷͰϝϦοτײ͡ʹ͍͔͘Ͱ͕࣮͢ࡍೖྗ߲ͬͱଟ ͍ͷͰײ͡ํมΘΓͦ͏ -
struct RegisterForm { var id = "" { didSet {
guard id != oldValue else { return } isIDErrorActive = false } } var idErrorMessage: String? var isIDErrorActive = false var password = "" { didSet { guard password != oldValue else { return } isPasswordErrorActive = false } } var passwordErrorMessage: String? var isPasswordErrorActive = false var favoriteFruit: Fruit? { didSet { guard favoriteFruit != oldValue else { return } isFavoriteFruitErrorActive = false } } var favoriteFruitErrorMessage: String? var isFavoriteFruitErrorActive = false } -
struct RegisterForm { var id = "" { didSet {
guard id != oldValue else { return } isIDErrorActive = false } } var idErrorMessage: String? var isIDErrorActive = false var password = "" { didSet { guard password != oldValue else { return } isPasswordErrorActive = false } } var passwordErrorMessage: String? var isPasswordErrorActive = false var favoriteFruit: Fruit? { didSet { guard favoriteFruit != oldValue else { return } isFavoriteFruitErrorActive = false } } var favoriteFruitErrorMessage: String? var isFavoriteFruitErrorActive = false } ࣅͨΑ͏ͳॲཧ -
struct RegisterForm { var id = "" { didSet {
guard id != oldValue else { return } isIDErrorActive = false } } var idErrorMessage: String? var isIDErrorActive = false var password = "" { didSet { guard password != oldValue else { return } isPasswordErrorActive = false } } var passwordErrorMessage: String? var isPasswordErrorActive = false var favoriteFruit: Fruit? { didSet { guard favoriteFruit != oldValue else { return } isFavoriteFruitErrorActive = false } } var favoriteFruitErrorMessage: String? var isFavoriteFruitErrorActive = false } ࣅͨΑ͏ͳίʔυॻ͘ͷ͕໘ -
struct RegisterForm { mutating func validate() -> RegisterRequest? { idErrorMessage
= nil isIDErrorActive = false passwordErrorMessage = nil isPasswordErrorActive = false favoriteFruitErrorMessage = nil isFavoriteFruitErrorActive = false if id.isEmpty || id.count > 20 { idErrorMessage = "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isIDErrorActive = true } if password.isEmpty || password.count > 20 { passwordErrorMessage = "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isPasswordErrorActive = true } if favoriteFruit == nil { favoriteFruitErrorMessage = "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" isFavoriteFruitErrorActive = true } if isIDErrorActive || isPasswordErrorActive || isFavoriteFruitErrorActive { return nil } let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) return request } } ࣅͨΑ͏ͳॲཧ͍ -
δΣωϦοΫͳTUSVDUͰඞཁͳมΛ·ͱΊΔ struct Field<Value: Equatable> { var wrappedValue: Value var isErrorActive
= false var errorMessage: String? } -
δΣωϦοΫͳTUSVDUͰඞཁͳมΛ·ͱΊΔ struct Field<Value: Equatable> { var wrappedValue: Value var isErrorActive
= false var errorMessage: String? } struct RegisterForm { var id = "" { didSet { guard id != oldValue else { return } isIDErrorActive = false } } var idErrorMessage: String? var isIDErrorActive = false var password = "" { didSet { guard password != oldValue else { return } isPasswordErrorActive = false } } var passwordErrorMessage: String? var isPasswordErrorActive = false var favoriteFruit: Fruit? { didSet { guard favoriteFruit != oldValue else { return } isFavoriteFruitErrorActive = false } } var favoriteFruitErrorMessage: String? var isFavoriteFruitErrorActive = false } -
δΣωϦοΫͳTUSVDUͰඞཁͳมΛ·ͱΊΔ struct Field<Value: Equatable> { var wrappedValue: Value var isErrorActive
= false var errorMessage: String? } struct RegisterForm { var id = "" { didSet { guard id != oldValue else { return } isIDErrorActive = false } } var idErrorMessage: String? var isIDErrorActive = false var password = "" { didSet { guard password != oldValue else { return } isPasswordErrorActive = false } } var passwordErrorMessage: String? var isPasswordErrorActive = false var favoriteFruit: Fruit? { didSet { guard favoriteFruit != oldValue else { return } isFavoriteFruitErrorActive = false } } var favoriteFruitErrorMessage: String? var isFavoriteFruitErrorActive = false } -
δΣωϦοΫͳTUSVDUͰඞཁͳมΛ·ͱΊΔ struct Field<Value: Equatable> { var wrappedValue: Value var isErrorActive
= false var errorMessage: String? } struct RegisterForm { var id = "" { didSet { guard id != oldValue else { return } isIDErrorActive = false } } var idErrorMessage: String? var isIDErrorActive = false var password = "" { didSet { guard password != oldValue else { return } isPasswordErrorActive = false } } var passwordErrorMessage: String? var isPasswordErrorActive = false var favoriteFruit: Fruit? { didSet { guard favoriteFruit != oldValue else { return } isFavoriteFruitErrorActive = false } } var favoriteFruitErrorMessage: String? var isFavoriteFruitErrorActive = false } -
δΣωϦοΫͳTUSVDUͰඞཁͳมΛ·ͱΊΔ struct Field<Value: Equatable> { var wrappedValue: Value { didSet
{ guard wrappedValue != oldValue else { return } isErrorActive = false } } var isErrorActive = false var errorMessage: String? } struct RegisterForm { var id = "" { didSet { guard id != oldValue else { return } isIDErrorActive = false } } var idErrorMessage: String? var isIDErrorActive = false var password = "" { didSet { guard password != oldValue else { return } isPasswordErrorActive = false } } var passwordErrorMessage: String? var isPasswordErrorActive = false var favoriteFruit: Fruit? { didSet { guard favoriteFruit != oldValue else { return } isFavoriteFruitErrorActive = false } } var favoriteFruitErrorMessage: String? var isFavoriteFruitErrorActive = false } -
ͳͷͰ͜Ε͕ struct RegisterForm { var id = "" { didSet
{ guard id != oldValue else { return } isIDErrorActive = false } } var idErrorMessage: String? var isIDErrorActive = false var password = "" { didSet { guard password != oldValue else { return } isPasswordErrorActive = false } } var passwordErrorMessage: String? var isPasswordErrorActive = false var favoriteFruit: Fruit? { didSet { guard favoriteFruit != oldValue else { return } isFavoriteFruitErrorActive = false } } var favoriteFruitErrorMessage: String? var isFavoriteFruitErrorActive = false } -
͜͏ͳΔ struct RegisterForm { var id = "" { didSet
{ guard id != oldValue else { return } isIDErrorActive = false } } var idErrorMessage: String? var isIDErrorActive = false var password = "" { didSet { guard password != oldValue else { return } isPasswordErrorActive = false } } var passwordErrorMessage: String? var isPasswordErrorActive = false var favoriteFruit: Fruit? { didSet { guard favoriteFruit != oldValue else { return } isFavoriteFruitErrorActive = false } } var favoriteFruitErrorMessage: String? var isFavoriteFruitErrorActive = false } struct RegisterForm { var id: Field<String> = .init(wrappedValue: “") var password: Field<String> = .init(wrappedValue: "") var favoriteFruit: Field<Fruit?> = .init(wrappedValue: nil) } -
͜͏ͳΔ struct RegisterForm { var id = "" { didSet
{ guard id != oldValue else { return } isIDErrorActive = false } } var idErrorMessage: String? var isIDErrorActive = false var password = "" { didSet { guard password != oldValue else { return } isPasswordErrorActive = false } } var passwordErrorMessage: String? var isPasswordErrorActive = false var favoriteFruit: Fruit? { didSet { guard favoriteFruit != oldValue else { return } isFavoriteFruitErrorActive = false } } var favoriteFruitErrorMessage: String? var isFavoriteFruitErrorActive = false } struct RegisterForm { var id: Field<String> = .init(wrappedValue: “") var password: Field<String> = .init(wrappedValue: "") var favoriteFruit: Field<Fruit?> = .init(wrappedValue: nil) } -
͜Ε1SPQFSUZ8SBQQFSʹͰ͖ΔΜʂ @propertyWrapper struct Field<Value: Equatable> { var wrappedValue: Value {
didSet { guard wrappedValue != oldValue else { return } isErrorActive = false } } var isErrorActive = false var errorMessage: String? } -
ͳͷͰ͜Ε͕ struct RegisterForm { var id: Field<String> = .init(wrappedValue: "")
var password: Field<String> = .init(wrappedValue: "") var favoriteFruit: Field<Fruit?> = .init(wrappedValue: nil) } -
͜͏ͳΔ struct RegisterForm { var id: Field<String> = .init(wrappedValue: "")
var password: Field<String> = .init(wrappedValue: "") var favoriteFruit: Field<Fruit?> = .init(wrappedValue: nil) } struct RegisterForm { @Field var id = "" @Field var password = "" @Field var favoriteFruit: Fruit? } -
͜ΕεοΩϦͤ͞Δ mutating func validate() -> RegisterRequest? { idErrorMessage = nil
isIDErrorActive = false passwordErrorMessage = nil isPasswordErrorActive = false favoriteFruitErrorMessage = nil isFavoriteFruitErrorActive = false … } -
͜ΕεοΩϦͤ͞Δ @propertyWrapper struct Field<Value: Equatable> { … mutating func clearError()
{ isErrorActive = false errorMessage = nil } var projectedValue: Field<Value> { get { self } set { self = newValue } } } mutating func validate() -> RegisterRequest? { idErrorMessage = nil isIDErrorActive = false passwordErrorMessage = nil isPasswordErrorActive = false favoriteFruitErrorMessage = nil isFavoriteFruitErrorActive = false … } -
͜ΕεοΩϦͤ͞Δ @propertyWrapper struct Field<Value: Equatable> { … mutating func clearError()
{ isErrorActive = false errorMessage = nil } var projectedValue: Field<Value> { get { self } set { self = newValue } } } mutating func validate() -> RegisterRequest? { idErrorMessage = nil isIDErrorActive = false passwordErrorMessage = nil isPasswordErrorActive = false favoriteFruitErrorMessage = nil isFavoriteFruitErrorActive = false … } -
͜ΕεοΩϦͤ͞Δ mutating func validate() -> RegisterRequest? { $id.clearError() $password.clearError() $favoriteFruit.clearError()
… } @propertyWrapper struct Field<Value: Equatable> { … mutating func clearError() { isErrorActive = false errorMessage = nil } var projectedValue: Field<Value> { get { self } set { self = newValue } } } -
mutating func validate() -> RegisterRequest? { $id.clearError() $password.clearError() $favoriteFruit.clearError() …
} ͜ΕεοΩϦͤ͞Δ @propertyWrapper struct Field<Value: Equatable> { … mutating func clearError() { isErrorActive = false errorMessage = nil } var projectedValue: Field<Value> { get { self } set { self = newValue } } } -
εοΩϦͨ͠ mutating func validate() -> RegisterRequest? { idErrorMessage = nil
isIDErrorActive = false passwordErrorMessage = nil isPasswordErrorActive = false favoriteFruitErrorMessage = nil isFavoriteFruitErrorActive = false … } mutating func validate() -> RegisterRequest? { $id.clearError() $password.clearError() $favoriteFruit.clearError() … } -
struct RegisterForm { var id = "" { didSet {
guard id != oldValue else { return } isIDErrorActive = false } } var idErrorMessage: String? var isIDErrorActive = false var password = "" { didSet { guard password != oldValue else { return } isPasswordErrorActive = false } } var passwordErrorMessage: String? var isPasswordErrorActive = false var favoriteFruit: Fruit? { didSet { guard favoriteFruit != oldValue else { return } isFavoriteFruitErrorActive = false } } var favoriteFruitErrorMessage: String? var isFavoriteFruitErrorActive = false mutating func validate() -> RegisterRequest? { idErrorMessage = nil isIDErrorActive = false passwordErrorMessage = nil isPasswordErrorActive = false favoriteFruitErrorMessage = nil isFavoriteFruitErrorActive = false if id.isEmpty || id.count > 20 { idErrorMessage = "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isIDErrorActive = true } if password.isEmpty || password.count > 20 { passwordErrorMessage = "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isPasswordErrorActive = true } if favoriteFruit == nil { favoriteFruitErrorMessage = "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" isFavoriteFruitErrorActive = true } if isIDErrorActive || isPasswordErrorActive || isFavoriteFruitErrorActive { return nil } let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) return request } } struct RegisterForm { @Field var id = "" @Field var password = "" @Field var favoriteFruit: Fruit? mutating func validate() -> RegisterRequest? { $id.clearError() $password.clearError() $favoriteFruit.clearError() if id.isEmpty || id.count > 20 { idErrorMessage = "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isIDErrorActive = true } if password.isEmpty || password.count > 20 { passwordErrorMessage = "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isPasswordErrorActive = true } if favoriteFruit == nil { favoriteFruitErrorMessage = "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" isFavoriteFruitErrorActive = true } if isIDErrorActive || isPasswordErrorActive || isFavoriteFruitErrorActive { return nil } let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) return request } } -
mutating func validate() -> RegisterRequest? { $id.clearError() $password.clearError() $favoriteFruit.clearError() if
id.isEmpty || id.count > 20 { $id.errorMessage = "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" $id.isErrorActive = true } if password.isEmpty || password.count > 20 { $password.errorMessage = "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" $password.isErrorActive = true } if favoriteFruit == nil { $favoriteFruit.errorMessage = "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" $favoriteFruit.isErrorActive = true } … } ͍ͬͯΔ͜ͱಉ͡ ݅ͱΤϥʔϝοηʔδ͕ҧ͏͚ͩ -
mutating func validate() -> RegisterRequest? { $id.clearError() $password.clearError() $favoriteFruit.clearError() if
id.isEmpty || id.count > 20 { $id.errorMessage = "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" $id.isErrorActive = true } if password.isEmpty || password.count > 20 { $password.errorMessage = "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" $password.isErrorActive = true } if favoriteFruit == nil { $favoriteFruit.errorMessage = "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" $favoriteFruit.isErrorActive = true } … } Ͱ͖ΕόϦσʔγϣϯ͕ύε͢Δ࣌ͷ݅Λॻ͖͍ͨ -
extension Field { mutating func validate(errorMessage: String, with validate: (Value)
-> Bool) { if !validate(wrappedValue) { self.errorMessage = errorMessage isErrorActive = true } } } -
extension Field { mutating func validate(errorMessage: String, with validate: (Value)
-> Bool) { if !validate(wrappedValue) { self.errorMessage = errorMessage isErrorActive = true } } } ݅ͱΤϥʔϝοηʔδΛҾͰ͢ -
extension Field { mutating func validate(errorMessage: String, with validate: (Value)
-> Bool) { if !validate(wrappedValue) { self.errorMessage = errorMessage isErrorActive = true } } } όϦσʔγϣϯ͕௨Δ࣌ͷ݅ΛࢦఆͰ͖ΔΑ͏ʹͳͬͨ -
ͳͷͰ͜Ε͕ if id.isEmpty || id.count > 20 { $id.errorMessage =
"ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" $id.isErrorActive = true } if password.isEmpty || password.count > 20 { $password.errorMessage = "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" $password.isErrorActive = true } if favoriteFruit == nil { $favoriteFruit.errorMessage = "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" $favoriteFruit.isErrorActive = true } -
͜͏ͳΔ $id.validate(errorMessage: "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞") { 1 <= $0.count && $0.count <=
20 } $password.validate(errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞") { 1 <= $0.count && $0.count <= 20 } $favoriteFruit.validate(errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞") { $0 != nil } -
͜͏ͳΔ $id.validate(errorMessage: "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞") { 1 <= $0.count && $0.count <=
20 } $password.validate(errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞") { 1 <= $0.count && $0.count <= 20 } $favoriteFruit.validate(errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞") { $0 != nil } όϦσʔγϣϯ͕ύε͢Δ݅Λࢦఆ͢Εྑ͍ -
͜͏ͳΔ $id.validate(errorMessage: "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞") { 1 <= $0.count && $0.count <=
20 } $password.validate(errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞") { 1 <= $0.count && $0.count <= 20 } $favoriteFruit.validate(errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞") { $0 != nil } ΤϥʔจݴͱҰக͢Δ -
struct RegisterForm { @Field var id = "" @Field var
password = "" @Field var favoriteFruit: Fruit? mutating func validate() -> RegisterRequest? { $id.clearError() $password.clearError() $favoriteFruit.clearError() if id.isEmpty || id.count > 20 { idErrorMessage = "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isIDErrorActive = true } if password.isEmpty || password.count > 20 { passwordErrorMessage = "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isPasswordErrorActive = true } if favoriteFruit == nil { favoriteFruitErrorMessage = "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" isFavoriteFruitErrorActive = true } if isIDErrorActive || isPasswordErrorActive || isFavoriteFruitErrorActive { return nil } let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) return request } } struct RegisterForm { @Field var id = "" @Field var password = "" @Field var favoriteFruit: Fruit? mutating func validate() -> RegisterRequest? { $id.clearError() $password.clearError() $favoriteFruit.clearError() $id.validate(errorMessage: "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞") { 1 <= $0.count && $0.count <= 20 } $password.validate(errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞") { 1 <= $0.count && $0.count <= 20 } $favoriteFruit.validateNotNil(errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞") if $id.isErrorActive || $password.isErrorActive || $favoriteFruit.isErrorActive { return nil } let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) return request } } -
if $id.isErrorActive || $password.isErrorActive || $favoriteFruit.isErrorActive { return nil }
let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) return request ͜Ε -
if $id.isErrorActive || $password.isErrorActive || $favoriteFruit.isErrorActive { return nil }
let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) return request JGͰνΣοΫͯ͠Δ͔Β ͜ͷλΠϛϯάͰOJMʹͳΔ͜ͱͳ͍͕ͣͩ ҆શʹΞϯϥοϓ͍ͨ͠ͱ͜Ζ -
͜ΕΛ extension Field { mutating func validate(errorMessage: String, with validate:
(Value) -> Bool) { if !validate(wrappedValue) { self.errorMessage = errorMessage isErrorActive = true } } } -
͜͏͢Δ mutating func validate(errorMessage: String, with validate: (Value) -> Bool)
-> Value? { guard validate(wrappedValue) else { self.errorMessage = errorMessage isErrorActive = true return nil } return wrappedValue } ฦΓΛՃ ύεͨ͠ΒTPNF /(ͳΒOJM Λฦ͢ -
ͳͷͰ͜Ε͕ $id.validate(errorMessage: "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞") { 1 <= $0.count && $0.count <=
20 } $password.validate(errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞") { 1 <= $0.count && $0.count <= 20 } $favoriteFruit.validate(errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞") { $0 != nil } if $id.isErrorActive || $password.isErrorActive || $favoriteFruit.isErrorActive { return nil } let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) return request -
͜͏ͳͬͯ let idValue = $id.validate(errorMessage: "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞") { 1 <= $0.count
&& $0.count <= 20 } let passwordValue = $password.validate(errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞") { 1 <= $0.count && $0.count <= 20 } let favoriteFruitValue = $favoriteFruit.validateNotNil(errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞") if $id.isErrorActive || $password.isErrorActive || $favoriteFruit.isErrorActive { return nil } let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) return request -
͜͏ͳΔ let idValue = $id.validate(errorMessage: "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞") { 1 <= $0.count
&& $0.count <= 20 } let passwordValue = $password.validate(errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞") { 1 <= $0.count && $0.count <= 20 } let favoriteFruitValue = $favoriteFruit.validateNotNil(errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞") guard let idValue, let passwordValue, let favoriteFruitValue else { return nil } let request = RegisterRequest( id: idValue, password: passwordValue, favoriteFruit: favoriteFruitValue ) return request -
͜͏ͳΔ let idValue = $id.validate(errorMessage: "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞") { 1 <= $0.count
&& $0.count <= 20 } let passwordValue = $password.validate(errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞") { 1 <= $0.count && $0.count <= 20 } let favoriteFruitValue = $favoriteFruit.validateNotNil(errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞") guard let idValue, let passwordValue, let favoriteFruitValue else { return nil } let request = RegisterRequest( id: idValue, password: passwordValue, favoriteFruit: favoriteFruitValue ) return request ͕ফ͑ͨ -
let idValue = $id.validate(errorMessage: "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞") { 1 <= $0.count &&
$0.count <= 20 } let passwordValue = $password.validate(errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞") { 1 <= $0.count && $0.count <= 20 } จࣈνΣοΫΛ͍ͯ͠Δ ݅େମಉ͡ͳͷͰͬͱָ͍ͨ͠ -
͜͏ͨ͠Βָͦ͏ extension (String) -> Bool { static func count(isIn range:
ClosedRange<Int>) -> Self { { value in range.contains(value.count) } } } let idValue = $id.validate( errorMessage: "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞", with: .count(isIn: 1 ... 20) ) ͜Μͳײ͡ʹॻ͖͍ͨ Λଧͭͱิ͕ग़ͯ͘ΔΑ͏ͳੈք -
͜͏ͨ͠Βָͦ͏ extension (String) -> Bool { static func count(isIn range:
ClosedRange<Int>) -> Self { { value in range.contains(value.count) } } } let idValue = $id.validate( errorMessage: "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞", with: .count(isIn: 1 ... 20) ) ҾΫϩʔδϟͳͷͰ&YUFOTJPOΛੜ͍͍ͤͷͰʁ -
Ͱ͖·ͤΜ extension (String) -> Bool { static func count(isIn range:
ClosedRange<Int>) -> Self { { value in range.contains(value.count) } } } let idValue = $id.validate( errorMessage: "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞", with: .count(isIn: 1 ... 20) ) 💥/POOPNJOBMUZQF 4USJOH #PPMDBOOPUCFFYUFOEFE -
Ϋϩʔδϟ͚ͩͷTUSVDUΛ࡞ struct ValidationRule<Value> { let validate: (Value) -> Bool }
ͭͷΫϩʔδϟΛ࣋ͭ ࣮࣭ΫϩʔδϟͰ͋Δ -
TUSVDUͳΒTUBUJDGVOD͕͑Δ extension ValidationRule where Value == String { static func
count(isIn range: ClosedRange<Int>) -> Self { .init { value in range.contains(value.count) } } } -
TUSVDUͳΒTUBUJDGVOD͕͑Δ extension ValidationRule where Value == String { static func
count(isIn range: ClosedRange<Int>) -> Self { .init { value in range.contains(value.count) } } } -
͜ΕΛ mutating func validate(errorMessage: String, with validate: (Value) -> Bool)
-> Value? { guard validate(wrappedValue) else { self.errorMessage = errorMessage isErrorActive = true return nil } return wrappedValue } -
͜͏͢Δ mutating func validate(errorMessage: String, with rule: ValidationRule<Value>) -> Value?
{ guard rule.validate(wrappedValue) else { self.errorMessage = errorMessage isErrorActive = true return nil } return wrappedValue } -
ݟӫ͑ͷͨΊҾͷॱ൪Λม͑Δ mutating func validate(with rule: ValidationRule<Value>, errorMessage: String) -> Value?
{ guard rule.validate(wrappedValue) else { self.errorMessage = errorMessage isErrorActive = true return nil } return wrappedValue } -
ͳͷͰ͜Ε͕ let idValue = $id.validate(errorMessage: "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞") { 1 <= $0.count
&& $0.count <= 20 } let passwordValue = $password.validate(errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞") { 1 <= $0.count && $0.count <= 20 } -
͜͏ͳΔ let idValue = $id.validate( with: .count(isIn: 1 ... 20),
errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) let passwordValue = $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) ҙਤ͕ΘΓ͘͢ͳͬͨ ॻ͘ͱ͖ͱΓ͋͑ͣͱଧͯԿ͔͠Βิ͞ΕΔ -
ྫ͑ʮ֯ӳࣈͷΈͰdจࣈҎʯͷ߹ extension ValidationRule where Value == String { static func
isOnlyAlphanumericAndCount(isIn range: ClosedRange<Int>) -> Self { .init { value in value.range(of: "[^a-zA-Z0-9]", options: .regularExpression) == nil && range.contains(value.count) } } } -
ྫ͑ʮ֯ӳࣈͷΈͰdจࣈҎʯͷ߹ extension ValidationRule where Value == String { static func
isOnlyAlphanumericAndCount(isIn range: ClosedRange<Int>) -> Self { .init { value in value.range(of: "[^a-zA-Z0-9]", options: .regularExpression) == nil && range.contains(value.count) } } } จࣈνΣοΫ ֯ӳࣈͷΈͷνΣοΫ ͍͍࣮ͪͪ͠ͳ͍ͱ͍͚ͳ͍ʜʁ -
Ͱ߹͍ͨ͠ let idValue = $id.validate( with: .count(isIn: 1 ... 20)
&& .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) ͜͏͍͏;͏ʹॻ͖͍ͨ -
ΫϩʔδϟΛ߹͢Δ struct ValidationRule<Value> { let validate: (Value) -> Bool static
func && (_ lhs: Self, _ rhs: Self) -> Self { ValidationRule { value in lhs.validate(value) && rhs.validate(value) } } } ͭͷ7BMJEBUJPO3VMFΛड͚औΔ -
struct ValidationRule<Value> { let validate: (Value) -> Bool static func
&& (_ lhs: Self, _ rhs: Self) -> Self { ValidationRule { value in lhs.validate(value) && rhs.validate(value) } } } ෦తʹ྆ऀͷ݁ՌΛͰܨ͛Δ ΫϩʔδϟΛ߹͢Δ -
struct ValidationRule<Value> { let validate: (Value) -> Bool static func
&& (_ lhs: Self, _ rhs: Self) -> Self { ValidationRule { value in lhs.validate(value) && rhs.validate(value) } } } ͦͷॲཧΛ৽ͨͳ7BMJEBUJPO3VMFͰϥοϓ͢Δ ΫϩʔδϟΛ߹͢Δ -
Ͱ͖ͨ let idValue = $id.validate( with: .count(isIn: 1 ... 20)
&& .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) ಠࣗͷϧʔϧΛఆٛ͢Δඞཁ͕ͳ͘ͳΔ -
struct RegisterForm { @Field var id = "" @Field var
password = "" @Field var favoriteFruit: Fruit? mutating func validate() -> RegisterRequest? { $id.clearError() $password.clearError() $favoriteFruit.clearError() let idValue = $id.validate( with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) let passwordValue = $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) let favoriteFruitValue = $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) guard let idValue, let passwordValue, let favoriteFruitValue else { return nil } let request = RegisterRequest( id: idValue, password: passwordValue, favoriteFruit: favoriteFruitValue ) return request } } -
struct RegisterForm { @Field var id = "" @Field var
password = "" @Field var favoriteFruit: Fruit? mutating func validate() -> RegisterRequest? { $id.clearError() $password.clearError() $favoriteFruit.clearError() let idValue = $id.validate( with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) let passwordValue = $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) let favoriteFruitValue = $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) guard let idValue, let passwordValue, let favoriteFruitValue else { return nil } let request = RegisterRequest( id: idValue, password: passwordValue, favoriteFruit: favoriteFruitValue ) return request } } Τϥʔͷঢ়ଶ!'JFMEʹؚ·Ε͍ͯΔ -
struct RegisterForm { @Field var id = "" @Field var
password = "" @Field var favoriteFruit: Fruit? mutating func validate() -> RegisterRequest? { $id.clearError() $password.clearError() $favoriteFruit.clearError() let idValue = $id.validate( with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) let passwordValue = $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) let favoriteFruitValue = $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) guard let idValue, let passwordValue, let favoriteFruitValue else { return nil } let request = RegisterRequest( id: idValue, password: passwordValue, favoriteFruit: favoriteFruitValue ) return request } } όϦσʔγϣϯͷ݅ ࠶ར༻݁߹Մೳ -
struct RegisterForm { @Field var id = "" @Field var
password = "" @Field var favoriteFruit: Fruit? mutating func validate() -> RegisterRequest? { $id.clearError() $password.clearError() $favoriteFruit.clearError() let idValue = $id.validate( with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) let passwordValue = $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) let favoriteFruitValue = $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) guard let idValue, let passwordValue, let favoriteFruitValue else { return nil } let request = RegisterRequest( id: idValue, password: passwordValue, favoriteFruit: favoriteFruitValue ) return request } } όϦσʔγϣϯ݁Ռ ΦϓγϣφϧͰड͚औΔ -
struct RegisterForm { @Field var id = "" @Field var
password = "" @Field var favoriteFruit: Fruit? mutating func validate() -> RegisterRequest? { $id.clearError() $password.clearError() $favoriteFruit.clearError() let idValue = $id.validate( with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) let passwordValue = $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) let favoriteFruitValue = $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) guard let idValue, let passwordValue, let favoriteFruitValue else { return nil } let request = RegisterRequest( id: idValue, password: passwordValue, favoriteFruit: favoriteFruitValue ) return request } } શͯύε͚ͨ࣌ͩ͠ 3FHJTUFS3FRVFTUΛฦ͢ -
࠷ॳͱݟൺΔ struct RegisterForm { @Field var id = "" @Field
var password = "" @Field var favoriteFruit: Fruit? mutating func validate() -> RegisterRequest? { $id.clearError() $password.clearError() $favoriteFruit.clearError() let idValue = $id.validate( with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) let passwordValue = $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) let favoriteFruitValue = $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) guard let idValue, let passwordValue, let favoriteFruitValue else { return nil } let request = RegisterRequest( id: idValue, password: passwordValue, favoriteFruit: favoriteFruitValue ) return request } } struct RegisterForm { var id = "" { didSet { guard id != oldValue else { return } isIDErrorActive = false } } var idErrorMessage: String? var isIDErrorActive = false var password = "" { didSet { guard password != oldValue else { return } isPasswordErrorActive = false } } var passwordErrorMessage: String? var isPasswordErrorActive = false var favoriteFruit: Fruit? { didSet { guard favoriteFruit != oldValue else { return } isFavoriteFruitErrorActive = false } } var favoriteFruitErrorMessage: String? var isFavoriteFruitErrorActive = false mutating func validate() -> RegisterRequest? { idErrorMessage = nil isIDErrorActive = false passwordErrorMessage = nil isPasswordErrorActive = false favoriteFruitErrorMessage = nil isFavoriteFruitErrorActive = false if id.isEmpty || id.count > 20 { idErrorMessage = "ID1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isIDErrorActive = true } if password.isEmpty || password.count > 20 { passwordErrorMessage = "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" isPasswordErrorActive = true } if favoriteFruit == nil { favoriteFruitErrorMessage = "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" isFavoriteFruitErrorActive = true } if isIDErrorActive || isPasswordErrorActive || isFavoriteFruitErrorActive { return nil } let request = RegisterRequest( id: id, password: password, favoriteFruit: favoriteFruit! ) return request } } -
ϓϩύςΟΛՃ struct RegisterForm { @Field var id = "" @Field
var password = "" @Field var favoriteFruit: Fruit? var includesProfile = false @Field var nickName = "" @Field var age = "" } ϓϩϑΟʔϧΛؚΊΔ͔Ͳ͏͔ Τϥʔঢ়ଶʹͳΒͳ͍ͷͰ!'JFMEෆཁ -
struct RegisterForm { @Field var id = "" @Field var
password = "" @Field var favoriteFruit: Fruit? var includesProfile = false @Field var nickName = "" @Field var age = "" } χοΫωʔϜͱྸ ϓϩύςΟΛՃ -
όϦσʔγϣϯॲཧΛՃ let nickNameValue: String? = $nickName.validate( with: .count(isIn: 1 ...
20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) -
όϦσʔγϣϯॲཧΛՃ let nickNameValue: String? = $nickName.validate( with: .count(isIn: 1 ...
20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) ͜ΕͰຖճόϦσʔγϣϯ͞Εͯ͠·͏ -
όϦσʔγϣϯॲཧΛՃ let nickNameValue: String?? if includesProfile { nickNameValue = $nickName.validate(
with: .count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) } else { nickNameValue = .some(nil) } ϓϩϑΟʔϧΛؚΊΔ͚࣌ͩόϦσʔγϣϯ͢Δ -
όϦσʔγϣϯॲཧΛՃ let nickNameValue: String?? if includesProfile { nickNameValue = $nickName.validate(
with: .count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) } else { nickNameValue = .some(nil) } ೋॏΦϓγϣφϧʹͳ͍ͬͯΔ -
όϦσʔγϣϯॲཧΛՃ let nickNameValue: String?? if includesProfile { nickNameValue = $nickName.validate(
with: .count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) } else { nickNameValue = .some(nil) } w ͜ͷม͕औΓ͏Δͭ w 4USJOH TPNF TPNF MFUWBMVF ʜϓϩϑΟʔϧೖྗΦϯͰόϦσʔγϣϯύεͨ࣌͠ w 4USJOH TPNF OJM ʜϓϩϑΟʔϧೖྗΦϑͷ࣌ w 4USJOH OJMʜόϦσʔγϣϯʹࣦഊͨ࣌͠ w ͍͜͠ -
ϦΫΤετΈཱͯॲཧݟͯΈΔ let request = RegisterRequest( id: idValue, password: passwordValue, favoriteFruit:
favoriteFruitValue, profile: includesProfile ? .init(nickName: nickNameValue!, age: ageValue!) : nil ) -
ϦΫΤετΈཱͯॲཧ let request = RegisterRequest( id: idValue, password: passwordValue, favoriteFruit:
favoriteFruitValue, profile: includesProfile ? .init(nickName: nickNameValue!, age: ageValue!) : nil ) ϓϩϑΟʔϧΛؚΊΔ͔Ͳ͏͔ͰΛม͑Δ -
ϦΫΤετΈཱͯॲཧ let request = RegisterRequest( id: idValue, password: passwordValue, favoriteFruit:
favoriteFruitValue, profile: includesProfile ? .init(nickName: nickNameValue!, age: ageValue!) : nil ) ؚΊͳ͍ͳΒOJMΛઃఆ -
ϦΫΤετΈཱͯॲཧ let request = RegisterRequest( id: idValue, password: passwordValue, favoriteFruit:
favoriteFruitValue, profile: includesProfile ? .init(nickName: nickNameValue!, age: ageValue!) : nil ) ؚΊΔͳΒ1SP fi MFϞσϧΛઃఆ͢Δ͕ʜ -
ϦΫΤετΈཱͯॲཧ let request = RegisterRequest( id: idValue, password: passwordValue, favoriteFruit:
favoriteFruitValue, profile: includesProfile ? .init(nickName: nickNameValue!, age: ageValue!) : nil ) ·ͨڧ੍Ξϯϥοϓ͕ग़͖ͯͨ -
7BMJEBUJPO3FTVMUܕΛఆٛ enum ValidationResult<Value> { case success(Value) case failed } ࠓ·ͰखΛൈ͍ͯΤϥʔͳΒOJMͱ͍͕ͯͨ͠
ͦͷ͍ͤͰOJMͱͯ͠ѻ͍͍ͨॴͱͬͪ͝ΌʹͳΔ ͱ͍͏Θ͚Ͱઐ༻ͷܕΛ༻ҙ -
7BMJEBUJPO3FTVMUʹஔ͖͍͑ͯ͘ mutating func validate(with rule: ValidationRule<Value>, errorMessage: String) -> Value?
{ guard rule.validate(wrappedValue) else { self.errorMessage = errorMessage isErrorActive = true return nil } return wrappedValue } -
7BMJEBUJPO3FTVMUʹஔ͖͍͑ͯ͘ mutating func validate(with rule: ValidationRule<Value>, errorMessage: String) -> ValidationResult<Value>
{ guard rule.validate(wrappedValue) else { self.errorMessage = errorMessage isErrorActive = true return .failed } return .success(wrappedValue) } -
͜͏ͳΔ let nickNameValue: ValidationResult<String?> w ͜ͷม͕औΓ͏Δͭ w 7BMJEBUJPO3FTVMUTVDDFTT TPNF MFUWBMVF
ʜϓϩϑΟʔϧೖྗΦϯͰόϦσʔγϣϯύεͨ࣌͠ w 7BMJEBUJPO3FTVMUTVDDFTT OJM ʜϓϩϑΟʔϧೖྗΦϑͷ࣌ w 7BMJEBUJPO3FTVMUGBJMFEʜόϦσʔγϣϯʹࣦഊͨ࣌͠ w Ϛγʹͳͬͨ -
ܕ͕߹Θͳ͘ͳΔ let nickNameValue: ValidationResult<String?> if includesProfile { nickNameValue = $nickName.validate(
with: .count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) } else { nickNameValue = .success(nil) } ͜ͷϝιουͷฦΓ7BMJEBUJPO3FTVMU4USJOH ͔͠͠ೖઌͷม7BMJEBUJPO3FTVMU4USJOH ܕ͕߹Θͳ͍ 💥Cannot assign value of type 'ValidationResult<String>' to type 'ValidationResult<String?>' -
ܕ͕߹Θͳ͘ͳΔ let nickNameValue: ValidationResult<String?> if includesProfile { nickNameValue = $nickName.validate(
with: .count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) .map(Optional.some) } else { nickNameValue = .success(nil) } 7BMJEBUJPO3FTVMUʹNBQؔΛ࡞ͬͯܕΛ߹ΘͤΔ Τϥʔղফ͞Ε͕ͨΘ͔Γʹ͍͘ -
ิNBQͷ࣮ enum ValidationResult<Value> { case success(Value) case failed func map<R>(_
transform: (Value) -> R) -> ValidationResult<R> { switch self { case .success(let value): return .success(transform(value)) case .failed: return .failed } } } -
HVBSEMFU͕͑ͳ͍ guard let idValue, let passwordValue, let favoriteFruitValue, let ageValue,
let nickNameValue else { return nil } 💥Initializer for conditional binding must have Optional type, not 'ValidationResult<String?>' શͯ7BMJEBUJPO3FTVMUܕʢඇΦϓγϣφϧʣʹͳͬͨͷͰΤϥʔʹͳΔʢવʣ -
HVBSEMFU͕͑ͳ͍ guard let idValue, let passwordValue, let favoriteFruitValue, let ageValue,
let nickNameValue else { return nil } DBTFʹมߋͯ͠ղܾ ղফ͕ͨ͠ɺͳΜ͔͍ guard case .success(let idValue) = idValue, case .success(let passwordValue) = passwordValue, case .success(let favoriteFruitValue) = favoriteFruitValue, case .success(let ageValue) = ageValue, case .success(let nickNameValue) = nickNameValue else { return nil } -
let nickNameValue: ValidationResult<String?> if includesProfile { nickNameValue = $nickName.validate( with:
.count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) .map(Optional.some) } else { nickNameValue = .success(nil) } let ageValue: ValidationResult<Int?> if includesProfile { ageValue = $age.validate( byTransform: Int.init, with: .range(in: 0 ... 999), errorMessage: "ྸ0ʙ999ͷൣғͰೖྗ͍ͯͩ͘͠͞" ) .map(Optional.some) } else { ageValue = .success(nil) } guard case .success(let idValue) = idValue, case .success(let passwordValue) = passwordValue, case .success(let favoriteFruitValue) = favoriteFruitValue, case .success(let ageValue) = ageValue, case .success(let nickNameValue) = nickNameValue else { return nil } -
let nickNameValue: ValidationResult<String?> if includesProfile { nickNameValue = $nickName.validate( with:
.count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) .map(Optional.some) } else { nickNameValue = .success(nil) } let ageValue: ValidationResult<Int?> if includesProfile { ageValue = $age.validate( byTransform: Int.init, with: .range(in: 0 ... 999), errorMessage: "ྸ0ʙ999ͷൣғͰೖྗ͍ͯͩ͘͠͞" ) .map(Optional.some) } else { ageValue = .success(nil) } guard case .success(let idValue) = idValue, case .success(let passwordValue) = passwordValue, case .success(let favoriteFruitValue) = favoriteFruitValue, case .success(let ageValue) = ageValue, case .success(let nickNameValue) = nickNameValue else { return nil } ͖݅όϦσʔγϣϯͷͨΊͷJG -
let nickNameValue: ValidationResult<String?> if includesProfile { nickNameValue = $nickName.validate( with:
.count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) .map(Optional.some) } else { nickNameValue = .success(nil) } let ageValue: ValidationResult<Int?> if includesProfile { ageValue = $age.validate( byTransform: Int.init, with: .range(in: 0 ... 999), errorMessage: "ྸ0ʙ999ͷൣғͰೖྗ͍ͯͩ͘͠͞" ) .map(Optional.some) } else { ageValue = .success(nil) } guard case .success(let idValue) = idValue, case .success(let passwordValue) = passwordValue, case .success(let favoriteFruitValue) = favoriteFruitValue, case .success(let ageValue) = ageValue, case .success(let nickNameValue) = nickNameValue else { return nil } ܕΛ߹ΘͤΔͨΊͷNBQ ͺͬͱݟԿ͍ͯ͠Δ͔Θ͔Βͳ͍ -
let nickNameValue: ValidationResult<String?> if includesProfile { nickNameValue = $nickName.validate( with:
.count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) .map(Optional.some) } else { nickNameValue = .success(nil) } let ageValue: ValidationResult<Int?> if includesProfile { ageValue = $age.validate( byTransform: Int.init, with: .range(in: 0 ... 999), errorMessage: "ྸ0ʙ999ͷൣғͰೖྗ͍ͯͩ͘͠͞" ) .map(Optional.some) } else { ageValue = .success(nil) } guard case .success(let idValue) = idValue, case .success(let passwordValue) = passwordValue, case .success(let favoriteFruitValue) = favoriteFruitValue, case .success(let ageValue) = ageValue, case .success(let nickNameValue) = nickNameValue else { return nil } ͖݅όϦσʔγϣϯେมʜ ͬͱָʹॻ͚ͳ͍ͷ͔ -
3FTVMU#VJMEFSΛ࡞ @resultBuilder enum ValidationResultBuilder { static func buildExpression<Content>(_ expression: Content)
-> ValidationResult<Content> { .success(expression) } static func buildExpression<Content>(_ expression: ValidationResult<Content>) -> ValidationResult<Content> { expression } static func buildBlock<Content>(_ result: ValidationResult<Content>) -> ValidationResult<Content> { result } static func buildOptional<Component>(_ component: ValidationResult<Component>?) -> ValidationResult<Component?> { guard let component else { return .success(nil) } switch component { case .success(let value): return .success(value) case .failed: return .failed } } static func buildEither<Content>(first: ValidationResult<Content>?) -> ValidationResult<Content?> { buildOptional(first) } static func buildEither<Content>(second: ValidationResult<Content>?) -> ValidationResult<Content?> { buildOptional(second) } static func buildBlock() -> ValidationResult<Void> { .success(()) } static func buildBlock<C0, C1>(_ c0: ValidationResult<C0>, _ c1: ValidationResult<C1>) -> ValidationResult<(C0, C1)> { guard let c0 = c0.successValue, let c1 = c1.successValue else { return .failed } return .success((c0, c1)) } … } -
3FTVMU#VJMEFSΛ࡞ @resultBuilder enum ValidationResultBuilder { static func buildExpression<Content>(_ expression: Content)
-> ValidationResult<Content> { .success(expression) } static func buildExpression<Content>(_ expression: ValidationResult<Content>) -> ValidationResult<Content> { expression } static func buildBlock<Content>(_ result: ValidationResult<Content>) -> ValidationResult<Content> { result } static func buildOptional<Component>(_ component: ValidationResult<Component>?) -> ValidationResult<Component?> { guard let component else { return .success(nil) } switch component { case .success(let value): return .success(value) case .failed: return .failed } } static func buildEither<Content>(first: ValidationResult<Content>?) -> ValidationResult<Content?> { buildOptional(first) } static func buildEither<Content>(second: ValidationResult<Content>?) -> ValidationResult<Content?> { buildOptional(second) } static func buildBlock() -> ValidationResult<Void> { .success(()) } static func buildBlock<C0, C1>(_ c0: ValidationResult<C0>, _ c1: ValidationResult<C1>) -> ValidationResult<(C0, C1)> { guard let c0 = c0.successValue, let c1 = c1.successValue else { return .failed } return .success((c0, c1)) } … } ৄࡉׂѪ -
ྫ let result: ValidationResult<(Int, String)> = ValidationResult.combine { ValidationResult<Int>.success(0) ValidationResult<String>.success("string")
} DPNCJOFͱ͍͏ϝιουΛ༻ҙͨ͠ ෳͷ7BMJEBUJPO3FTVMUΛͭͷ7BMJEBUJPO3FTVMUʹ·ͱΊͯ͘ΕΔ -
ྫ let result: ValidationResult<(Int, String)> = ValidationResult.combine { ValidationResult<Int>.success(0) ValidationResult<String>.success("string")
} *OUͷ7BMJEBUJPO3FTVMU 4USJOHͷ7BMJEBUJPO3FTVMU Λ·ͱΊΔ -
ྫ let result: ValidationResult<(Int, String)> = ValidationResult.combine { ValidationResult<Int>.success(0) ValidationResult<String>.success("string")
} ݁ՌλϓϧͱͳΔ ValidationResult<Int> ValidationResult<String> ValidationResult<(Int, String)> -
ྫ let result: ValidationResult<(Int, String?)> = ValidationResult.combine { ValidationResult<Int>.success(0) if
.random() { ValidationResult<String>.success("string") } } -
ྫ let result: ValidationResult<(Int, String?)> = ValidationResult.combine { ValidationResult<Int>.success(0) if
.random() { ValidationResult<String>.success("string") } } JG͑Δ -
ྫ let result: ValidationResult<(Int, String?)> = ValidationResult.combine { ValidationResult<Int>.success(0) if
.random() { ValidationResult<String>.success("string") } } Φϓγϣφϧͱͯ͠ѻΘΕΔ *GͷதʹೖΔͱTPNF ೖΒͳ͍ͱOJM ͱͳΔ -
ྫ let result: ValidationResult<(Int, (String, Double)?)> = ValidationResult.combine { ValidationResult<Int>.success(0)
if .random() { ValidationResult<String>.success("string") ValidationResult<Double>.success(0.0) } } JGͷதͷཁૉΛ૿ͯ͠ΈΔ -
ྫ let result: ValidationResult<(Int, (String, Double)?)> = ValidationResult.combine { ValidationResult<Int>.success(0)
if .random() { ValidationResult<String>.success("string") ValidationResult<Double>.success(0.0) } } λϓϧͷΦϓγϣφϧͱͳΔ -
ྫ let result: ValidationResult<(Int, (String, Double)?)> = ValidationResult.combine { ValidationResult<Int>.success(0)
if .random() { ValidationResult<String>.success("string") ValidationResult<Double>.success(0.0) } } -
ྫ let result: ValidationResult<(Int, (String, Double)?)> = ValidationResult.combine { ValidationResult<Int>.success(0)
if .random() { ValidationResult<String>.success("string") ValidationResult<Double>.success(0.0) } } -
ྫ let result: ValidationResult<(Int, (String, Double)?)> = ValidationResult.combine { ValidationResult<Int>.success(0)
if .random() { ValidationResult<String>.success("string") ValidationResult<Double>.success(0.0) } } -
ྫ let result: ValidationResult<(Int, (String, Double)?)> = ValidationResult.combine { ValidationResult<Int>.success(0)
if .random() { ValidationResult<String>.success("string") ValidationResult<Double>.success(0.0) } } -
ྫ ValidationResult.combine { ValidationResult.combine { ValidationResult.combine { ValidationResult.combine { ValidationResult.combine
{ ValidationResult.success("string") } } } } } DPNCJOFͷதͰDPNCJOFΛ͑Δ 4XJGU6*Ͱ7JFXΛωετͰ͖Δͷͱಉ͡ -
mutating func validateProfile() -> ValidationResult<RegisterRequest.Profile> { let result: ValidationResult<(String, Int)>
= ValidationResult.combine { $nickName.validate( with: .count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $age.validate( byTransform: Int.init, with: .range(in: 0 ... 999), errorMessage: "ྸ0ʙ999ͷൣғͰೖྗ͍ͯͩ͘͠͞" ) } return result.map { (nickName: String, age: Int) in RegisterRequest.Profile(nickName: nickName, age: age) } } ͜ͷ෦ͷόϦσʔγϣϯॲཧ -
mutating func validateProfile() -> ValidationResult<RegisterRequest.Profile> { let result: ValidationResult<(String, Int)>
= ValidationResult.combine { $nickName.validate( with: .count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $age.validate( byTransform: Int.init, with: .range(in: 0 ... 999), errorMessage: "ྸ0ʙ999ͷൣғͰೖྗ͍ͯͩ͘͠͞" ) } return result.map { (nickName: String, age: Int) in RegisterRequest.Profile(nickName: nickName, age: age) } } -
mutating func validateProfile() -> ValidationResult<RegisterRequest.Profile> { let result: ValidationResult<(String, Int)>
= ValidationResult.combine { $nickName.validate( with: .count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $age.validate( byTransform: Int.init, with: .range(in: 0 ... 999), errorMessage: "ྸ0ʙ999ͷൣғͰೖྗ͍ͯͩ͘͠͞" ) } return result.map { (nickName: String, age: Int) in RegisterRequest.Profile(nickName: nickName, age: age) } } -
mutating func validateProfile() -> ValidationResult<RegisterRequest.Profile> { let result: ValidationResult<(String, Int)>
= ValidationResult.combine { $nickName.validate( with: .count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $age.validate( byTransform: Int.init, with: .range(in: 0 ... 999), errorMessage: "ྸ0ʙ999ͷൣғͰೖྗ͍ͯͩ͘͠͞" ) } return result.map { (nickName: String, age: Int) in RegisterRequest.Profile(nickName: nickName, age: age) } } -
mutating func validateProfile() -> ValidationResult<RegisterRequest.Profile> { let result: ValidationResult<(String, Int)>
= ValidationResult.combine { $nickName.validate( with: .count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $age.validate( byTransform: Int.init, with: .range(in: 0 ... 999), errorMessage: "ྸ0ʙ999ͷൣғͰೖྗ͍ͯͩ͘͠͞" ) } return result.map { (nickName: String, age: Int) in RegisterRequest.Profile(nickName: nickName, age: age) } } DPNCJOFϝιουͰแΉ -
mutating func validateProfile() -> ValidationResult<RegisterRequest.Profile> { let result: ValidationResult<(String, Int)>
= ValidationResult.combine { $nickName.validate( with: .count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $age.validate( byTransform: Int.init, with: .range(in: 0 ... 999), errorMessage: "ྸ0ʙ999ͷൣғͰೖྗ͍ͯͩ͘͠͞" ) } return result.map { (nickName: String, age: Int) in RegisterRequest.Profile(nickName: nickName, age: age) } } ྆ํͷόϦσʔγϣϯ͕ύεͨ࣌͠ʹ 4USJOH *OU ͷλϓϧΛೖखͰ͖Δ -
mutating func validateProfile() -> ValidationResult<RegisterRequest.Profile> { let result: ValidationResult<(String, Int)>
= ValidationResult.combine { $nickName.validate( with: .count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $age.validate( byTransform: Int.init, with: .range(in: 0 ... 999), errorMessage: "ྸ0ʙ999ͷൣғͰೖྗ͍ͯͩ͘͠͞" ) } return result.map { (nickName: String, age: Int) in RegisterRequest.Profile(nickName: nickName, age: age) } } ྆ํͷόϦσʔγϣϯ͕ύεͨ࣌͠ʹ 4USJOH *OU ͷλϓϧΛೖखͰ͖Δ -
mutating func validateProfile() -> ValidationResult<RegisterRequest.Profile> { let result: ValidationResult<(String, Int)>
= ValidationResult.combine { $nickName.validate( with: .count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $age.validate( byTransform: Int.init, with: .range(in: 0 ... 999), errorMessage: "ྸ0ʙ999ͷൣғͰೖྗ͍ͯͩ͘͠͞" ) } return result.map { (nickName: String, age: Int) in RegisterRequest.Profile(nickName: nickName, age: age) } } ྆ํͷόϦσʔγϣϯ͕ύεͨ࣌͠ʹ 4USJOH *OU ͷλϓϧΛೖखͰ͖Δ -
mutating func validateProfile() -> ValidationResult<RegisterRequest.Profile> { let result: ValidationResult<(String, Int)>
= ValidationResult.combine { $nickName.validate( with: .count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $age.validate( byTransform: Int.init, with: .range(in: 0 ... 999), errorMessage: "ྸ0ʙ999ͷൣғͰೖྗ͍ͯͩ͘͠͞" ) } return result.map { (nickName: String, age: Int) in RegisterRequest.Profile(nickName: nickName, age: age) } } ValidationResult<(String, Int)> ValidationResult<RegisterRequest.Profile> ܕΛม -
let result: ValidationResult<(String, String, Fruit, RegisterRequest.Profile?)> = ValidationResult.combine { $id.validate(
with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) if includesProfile { validateProfile() } } -
let result: ValidationResult<(String, String, Fruit, RegisterRequest.Profile?)> = ValidationResult.combine { $id.validate(
with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) if includesProfile { validateProfile() } } -
let result: ValidationResult<(String, String, Fruit, RegisterRequest.Profile?)> = ValidationResult.combine { $id.validate(
with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) if includesProfile { validateProfile() } } -
let result: ValidationResult<(String, String, Fruit, RegisterRequest.Profile?)> = ValidationResult.combine { $id.validate(
with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) if includesProfile { validateProfile() } } -
let result: ValidationResult<(String, String, Fruit, RegisterRequest.Profile?)> = ValidationResult.combine { $id.validate(
with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) if includesProfile { validateProfile() } } -
let result: ValidationResult<(String, String, Fruit, RegisterRequest.Profile?)> = ValidationResult.combine { $id.validate(
with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) if includesProfile { validateProfile() } } JODMVEFT1SP fi MF͕USVFͷ࣌TPNF GBMTFͷ࣌OJMʹͳΔ -
let result: ValidationResult<(String, String, Fruit, RegisterRequest.Profile?)> = ValidationResult.combine { $id.validate(
with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) if includesProfile { validateProfile() } } ʮϓϩϑΟʔϧೖྗཝ͕Φϯͷ࣌ʹϓϩϑΟʔϧ෦ΛόϦσʔγϣϯ͢Δʯ ͱ͍͏༷͕ίʔυͰදݱͰ͖͍ͯΔ -
let result: ValidationResult<(String, String, Fruit, RegisterRequest.Profile?)> = ValidationResult.combine { $id.validate(
with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) if includesProfile { validateProfile() } } return result.map { id, password, favoriteFruit, profile in RegisterRequest(id: id, password: password, favoriteFruit: favoriteFruit, profile: profile) } ValidationResult<(String, String, Fruit, RegisterRequest.Profile?)> ValidationResult<RegisterRequest> -
let result: ValidationResult<(String, String, Fruit, RegisterRequest.Profile?)> = ValidationResult.combine { $id.validate(
with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) if includesProfile { validateProfile() } } return result.map(RegisterRequest.init) Ҿͷॱ൪ͱλϓϧͷॱ൪͕ಉ͡ͳͷͰ͜ΕͰྑ͍ -
let result: ValidationResult<(String, String, Fruit, RegisterRequest.Profile?)> = ValidationResult.combine { $id.validate(
with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) if includesProfile { validateProfile() } } return result.map(RegisterRequest.init) 3FTVMU#VJMEFSʹΑ͖ͬͯ݅όϦσʔγϣϯΛײతʹॻ͚ΔΑ͏ʹͳͬͨ -
let result: ValidationResult<(String, String, Fruit, RegisterRequest.Profile?)> = ValidationResult.combine { $id.validate(
with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) if includesProfile { validateProfile() } } return result.map(RegisterRequest.init) ͍ͭͰʹHVBSEMFUෆཁʹͳͬͨ -
struct RegisterForm { @Field var id = "" @Field var
password = "" @Field var favoriteFruit: Fruit? var includesProfile = false @Field var nickName = "" @Field var age = "" mutating func validate() -> ValidationResult<RegisterRequest> { $id.clearError() $password.clearError() $favoriteFruit.clearError() $nickName.clearError() $age.clearError() return ValidationResult.combine { $id.validate( with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) if includesProfile { validateProfile() } } .map(RegisterRequest.init) } mutating func validateProfile() -> ValidationResult<RegisterRequest.Profile> { ValidationResult.combine { $nickName.validate( with: .count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $age.validate( byTransform: Int.init, with: .range(in: 0 ... 999), errorMessage: "ྸ0ʙ999ͷൣғͰೖྗ͍ͯͩ͘͠͞" ) } .map(RegisterRequest.Profile.init) } } -
struct RegisterForm { @Field var id = "" @Field var
password = "" @Field var favoriteFruit: Fruit? var includesProfile = false @Field var nickName = "" @Field var age = "" mutating func validate() -> ValidationResult<RegisterRequest> { $id.clearError() $password.clearError() $favoriteFruit.clearError() $nickName.clearError() $age.clearError() return ValidationResult.combine { $id.validate( with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) if includesProfile { validateProfile() } } .map(RegisterRequest.init) } mutating func validateProfile() -> ValidationResult<RegisterRequest.Profile> { ValidationResult.combine { $nickName.validate( with: .count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $age.validate( byTransform: Int.init, with: .range(in: 0 ... 999), errorMessage: "ྸ0ʙ999ͷൣғͰೖྗ͍ͯͩ͘͠͞" ) } .map(RegisterRequest.Profile.init) } } 7JFX͔Βঢ়ଶͱϩδοΫΛͤͨ͞ -
struct RegisterForm { @Field var id = "" @Field var
password = "" @Field var favoriteFruit: Fruit? var includesProfile = false @Field var nickName = "" @Field var age = "" mutating func validate() -> ValidationResult<RegisterRequest> { $id.clearError() $password.clearError() $favoriteFruit.clearError() $nickName.clearError() $age.clearError() return ValidationResult.combine { $id.validate( with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) if includesProfile { validateProfile() } } .map(RegisterRequest.init) } mutating func validateProfile() -> ValidationResult<RegisterRequest.Profile> { ValidationResult.combine { $nickName.validate( with: .count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $age.validate( byTransform: Int.init, with: .range(in: 0 ... 999), errorMessage: "ྸ0ʙ999ͷൣғͰೖྗ͍ͯͩ͘͠͞" ) } .map(RegisterRequest.Profile.init) } } ϘΠϥʔϓϨʔτΛ1SPQFSUZ8SBQQFSͰղܾ -
struct RegisterForm { @Field var id = "" @Field var
password = "" @Field var favoriteFruit: Fruit? var includesProfile = false @Field var nickName = "" @Field var age = "" mutating func validate() -> ValidationResult<RegisterRequest> { $id.clearError() $password.clearError() $favoriteFruit.clearError() $nickName.clearError() $age.clearError() return ValidationResult.combine { $id.validate( with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) if includesProfile { validateProfile() } } .map(RegisterRequest.init) } mutating func validateProfile() -> ValidationResult<RegisterRequest.Profile> { ValidationResult.combine { $nickName.validate( with: .count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $age.validate( byTransform: Int.init, with: .range(in: 0 ... 999), errorMessage: "ྸ0ʙ999ͷൣғͰೖྗ͍ͯͩ͘͠͞" ) } .map(RegisterRequest.Profile.init) } } όϦσʔγϣϯ݅Λ ࠶ར༻Մೳ ίʔυิՄೳ ݁߹Մೳ ʹͨ͠ -
struct RegisterForm { @Field var id = "" @Field var
password = "" @Field var favoriteFruit: Fruit? var includesProfile = false @Field var nickName = "" @Field var age = "" mutating func validate() -> ValidationResult<RegisterRequest> { $id.clearError() $password.clearError() $favoriteFruit.clearError() $nickName.clearError() $age.clearError() return ValidationResult.combine { $id.validate( with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) if includesProfile { validateProfile() } } .map(RegisterRequest.init) } mutating func validateProfile() -> ValidationResult<RegisterRequest.Profile> { ValidationResult.combine { $nickName.validate( with: .count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $age.validate( byTransform: Int.init, with: .range(in: 0 ... 999), errorMessage: "ྸ0ʙ999ͷൣғͰೖྗ͍ͯͩ͘͠͞" ) } .map(RegisterRequest.Profile.init) } } 3FTVMU#VJMEFSͰ͖݅όϦσʔγϣϯΛ ײతʹهड़ -
struct RegisterForm { @Field var id = "" @Field var
password = "" @Field var favoriteFruit: Fruit? var includesProfile = false @Field var nickName = "" @Field var age = "" mutating func validate() -> ValidationResult<RegisterRequest> { $id.clearError() $password.clearError() $favoriteFruit.clearError() $nickName.clearError() $age.clearError() return ValidationResult.combine { $id.validate( with: .count(isIn: 1 ... 20) && .isOnlyAlphanumeric, errorMessage: "ID1~20จࣈҎͷӳࣈͰೖྗ͍ͯͩ͘͠͞" ) $password.validate( with: .count(isIn: 1 ... 20), errorMessage: "ύεϫʔυ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $favoriteFruit.validateNotNil( errorMessage: "͖ͳϑϧʔπΛબ͍ͯͩ͘͠͞" ) if includesProfile { validateProfile() } } .map(RegisterRequest.init) } mutating func validateProfile() -> ValidationResult<RegisterRequest.Profile> { ValidationResult.combine { $nickName.validate( with: .count(isIn: 1 ... 20), errorMessage: "χοΫωʔϜ1~20จࣈҎͰೖྗ͍ͯͩ͘͠͞" ) $age.validate( byTransform: Int.init, with: .range(in: 0 ... 999), errorMessage: "ྸ0ʙ999ͷൣғͰೖྗ͍ͯͩ͘͠͞" ) } .map(RegisterRequest.Profile.init) } } 3FTVMU#VJMEFSʹΑΓ7BMJEBUJPO3FTVMUΛ߹Մೳʹ