SwiftUI-第一次避免使用AnyPublisher

时间:2020-08-01 20:28:30

标签: ios swiftui

我创建了发布者来验证用户输入,在这种情况下,只需验证他们的长度为32个字符即可。

ConnectionVM

import UIKit
import Combine

class ConnectionVM: ObservableObject {
    private var cancellableSet: Set<AnyCancellable> = []
    //INPUT
    @Published var uuid1: String = ""
    @Published var uuid2: String = ""
    //OUTPUT
    @Published var uuid1Message = ""
    @Published var uuid2Message = ""
    
    init() {
        isUUID1ValidPublisher
            .receive(on: RunLoop.main)
            .map { valid in
                valid ? "" : "UUID1 must have 32 characters"
            }
            .assign(to: \.uuid1Message, on: self)
            .store(in: &cancellableSet)
        
        isUUID2ValidPublisher
            .receive(on: RunLoop.main)
            .map { valid in
              valid ? "" : "UUID2 must have 32 characters"
            }
            .assign(to: \.uuid2Message, on: self)
            .store(in: &cancellableSet)
    }
    
    private var isUUID1ValidPublisher: AnyPublisher<Bool, Never> {
      $uuid1
        .debounce(for: 0.8, scheduler: RunLoop.main)
        .removeDuplicates()
        .map { input in
          return input.count == 32
        }
        .eraseToAnyPublisher()
    }
    private var isUUID2ValidPublisher: AnyPublisher<Bool, Never> {
      $uuid2
        .debounce(for: 0.8, scheduler: RunLoop.main)
        .removeDuplicates()
        .map { input in
          return input.count == 32
        }
        .eraseToAnyPublisher()
    }
    private var isFormValidPublisher: AnyPublisher<Bool, Never> {
      Publishers.CombineLatest(isUUID1ValidPublisher, isUUID2ValidPublisher)
        .map { uuid1IsValid, uuid2IsValid in
          return uuid1IsValid && uuid2IsValid
        }
      .eraseToAnyPublisher()
    }
}

ConnectionView

import SwiftUI

let lightGreyColor = Color(red: 239.0/255.0, green: 243.0/255.0, blue: 244.0/255.0, opacity: 1.0)

struct ConnectionView: View {
    @ObservedObject var keyboardResponder = KeyboardResponder()
    @ObservedObject var viewModel = ConnectionVM()
//    @State var uuid1: String = ""
//    @State var uuid2: String = ""
    @State var authenticationDidFail: Bool = false
    
    var body: some View {
        return VStack {
            WelcomeText()
            LogoImage()
            UUIDTextField(uuid: $viewModel.uuid1)
            if !viewModel.uuid1Message.isEmpty {
                Text(viewModel.uuid1Message)
                .offset(y: -10)
                .foregroundColor(.red)
            }
            UUIDTextField(uuid: $viewModel.uuid2)
            if !viewModel.uuid2Message.isEmpty {
                Text(viewModel.uuid2Message)
                .offset(y: -10)
                .foregroundColor(.red)
            }
            Button(action: {
                print("Button tapped")
            }) {
               LoginButtonContent()
            }
        }
        .padding()
        .offset(y: -keyboardResponder.currentHeight*0.5)
    }
    struct WelcomeText : View {
        var body: some View {
            return Text("Welcome!")
                .font(.largeTitle)
                .fontWeight(.semibold)
                .padding(.bottom, 20)
        }
    }
    struct LogoImage : View {
        var body: some View {
            return Image("logo")
                .resizable()
                .aspectRatio(contentMode: .fill)
                .frame(width: 150, height: 150)
                .clipped()
                .cornerRadius(150)
                .padding(.bottom, 75)
        }
    }
    struct UUIDTextField : View {
        @Binding var uuid: String
        var body: some View {
        return TextField("UUID", text: $uuid)
                    .padding()
                    .background(lightGreyColor)
                    .cornerRadius(5.0)
                    .padding(.bottom, 20)
            }
    }
    struct LoginButtonContent : View {
        var body: some View {
            return Text("LOGIN")
                .font(.headline)
                .foregroundColor(.white)
                .padding()
                .frame(width: 220, height: 60)
                .background(Color.green)
                .cornerRadius(15.0)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ConnectionView()
    }
}

问题是第一次打开屏幕时,错误消息会自动出现。

enter image description here

1 个答案:

答案 0 :(得分:0)

您基本上需要另一个条件来保护是否显示消息。

这种情况可能是该字段已先更改,因此您要计算每个字段已更改的次数,并就其是否已更改一次以上(即超出{{1 }})

""

let hasUUID1Changed = $uuid1.scan(0, { a, _ in a + 1}).map { $0 > 1 } let hasUUID2Changed = $uuid2.scan(0, { a, _ in a + 1}).map { $0 > 1 } 在这种情况下充当计数器/累加器。生命周期就是视图模型的生命周期。

然后,您可以结合使用此发布者和Publishers.Scan来确定是否显示消息:

isUUID1ValidPublisher
相关问题