gpt4 book ai didi

swiftui - 一个 View 中的多个警报只能在 swiftui 中始终只有最后一个警报起作用

转载 作者:行者123 更新时间:2023-12-02 03:04:10 25 4
gpt4 key购买 nike

我有两个警报,如果 bool 值为 true,就会调用它们。

Alert - 1 - 如果蓝牙状态存在除开机以外的任何问题,则会调用该警报。这直接从名为 BLE 的 swift 包中调用。代码片段如下。

警报 - 2 - 当您想要取消外围设备配对时调用它,为用户提供两个选项。取消配对或保留在同一页面上。

问题:两个警报似乎都工作正常,但如果它们没有放置在同一 View 中。当我将警报放置在同一 View 中时,将从上到下的顺序调用最后显示的警报。

操作系统读取第一个警报,但仅在调用时激活第二个警报。

有没有办法让两个警报在被调用时都起作用。我引用了下面的解决方案,但得到了相同的结果。

Solution 1Solution 2

有2个代码片段

<强>1。主要应用

import SwiftUI
import BLE

struct Dashboard: View {

@EnvironmentObject var BLE: BLE
@State private var showUnpairAlert: Bool = false

private var topLayer: HeatPeripheral {
self.BLE.peripherals.baseLayer.top
}

var body: some View {
VStack(alignment: .center, spacing: 0) {
// MARK: - Menu Bar
VStack(alignment: .center, spacing: 4) {
Button(action: {
print("Unpair tapped!")
self.showUnpairAlert = true
}) {
HStack {
Text("Unpair")
.fontWeight(.bold)
.font(.body)
}
.frame(minWidth: 85, minHeight: 35)
.cornerRadius(30)
}
}

}
.onAppear(perform: {
self.BLE.update()
})

// Alert 1 - It is called if it meets one of the cases and returns the alert
// It is presented in the function centralManagerDidUpdateState
.alert(isPresented: $BLE.showStateAlert, content: { () -> Alert in

let state = self.BLE.centralManager!.state
var message = ""

switch state {
case .unknown:
message = "Bluetooth state is unknown"
case .resetting:
message = "Bluetooth is resetting..."
case .unsupported:
message = "This device doesn't have a bluetooth radio."
case .unauthorized:
message = "Turn On Bluetooth In The Settings App to Allow Battery to Connect to App."
case .poweredOff:
message = "Turn On Bluetooth to Allow Battery to Connect to App."
break
@unknown default:
break
}

return Alert(title: Text("Bluetooth is \(self.BLE.getStateString())"), message: Text(message), dismissButton: .default(Text("OK")))
})

// Alert 2 - It is called when you tap the unpair button

.alert(isPresented: $showUnpairAlert) {
Alert(title: Text("Unpair from \(checkForDeviceInformation())"), message: Text("*Your peripheral command will stay on."), primaryButton: .destructive(Text("Unpair")) {
self.unpairAndSetDefaultDeviceInformation()
}, secondaryButton: .cancel())
}
}
func unpairAndSetDefaultDeviceInformation() {
defaults.set(defaultDeviceinformation, forKey: Keys.deviceInformation)
disconnectPeripheral()
print("Pod unpaired and view changed to Onboarding")
self.presentationMode.wrappedValue.dismiss()
DispatchQueue.main.async {
self.activateLink = true
}

}
func disconnectPeripheral(){
if skiinBLE.peripherals.baseLayer.top.cbPeripheral != nil {
self.skiinBLE.disconnectPeripheral()
}
}

}

<强>2。 BLE 封装

import SwiftUI
import Combine
import CoreBluetooth

public class BLE: NSObject, ObservableObject {

public var centralManager: CBCentralManager? = nil
public let baseLayerServices = "XXXXXXXXXXXXXXX"
let defaults = UserDefaults.standard
@Published public var showStateAlert: Bool = false

public func start() {
self.centralManager = CBCentralManager(delegate: self, queue: nil, options: nil)
self.centralManager?.delegate = self
}

public func getStateString() -> String {
guard let state = self.centralManager?.state else { return String() }
switch state {
case .unknown:
return "Unknown"
case .resetting:
return "Resetting"
case .unsupported:
return "Unsupported"
case .unauthorized:
return "Unauthorized"
case .poweredOff:
return "Powered Off"
case .poweredOn:
return "Powered On"
@unknown default:
return String()
}
}

}

extension BLE: CBCentralManagerDelegate {

public func centralManagerDidUpdateState(_ central: CBCentralManager) {
print("state: \(self.getStateString())")
if central.state == .poweredOn {
self.showStateAlert = false

if let connectedPeripherals = self.centralManager?.retrieveConnectedPeripherals(withServices: self.baseLayerServices), connectedPeripherals.count > 0 {
print("Already connected: \(connectedPeripherals.map{$0.name}), self.peripherals: \(self.peripherals)")
self.centralManager?.stopScan()

}
else {
print("scanForPeripherals")
self.centralManager?.scanForPeripherals(withServices: self.baseLayerServices, options: nil)
}
}
else {
self.showStateAlert = true // Alert is called if there is any issue with the state.
}
}
}

谢谢!!!

最佳答案

要记住的是, View 修饰符实际上不仅仅修改 View ,它们还返回一个全新的 View 。因此,第一个 alert 修饰符返回一个以第一种方式处理警报的新 View 。第二个 alert 修饰符返回一个新 View ,该 View 以第二种方式修改警报(覆盖第一个方法),并且这是唯一最终有效的方法。最外面的修饰符才是重要的。

您可以尝试以下几种方法,首先尝试将不同的警报修饰符附加到两个不同的 View ,而不是同一个 View 。

其次,您可以尝试 alert 的替代形式,它接受可选 Identifying 的 Binding 并将其传递给闭包。当值为零时,什么也不会发生。当状态更改为 nil 以外的状态时,应该出现警报。

下面是一个使用 alert(item:) 形式的示例,而不是基于 Bool 的 alert(isPresented:)

enum Selection: Int, Identifiable {
case a, b, c
var id: Int { rawValue }
}


struct MultiAlertView: View {

@State private var selection: Selection? = nil

var body: some View {

HStack {
Button(action: {
self.selection = .a
}) { Text("a") }

Button(action: {
self.selection = .b
}) { Text("b") }

}.alert(item: $selection) { (s: Selection) -> Alert in
Alert(title: Text("selection: \(s.rawValue)"))
}
}
}

关于swiftui - 一个 View 中的多个警报只能在 swiftui 中始终只有最后一个警报起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59399949/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com