So I am trying to keep my current up at iOS 13 + while bring in a few iOS 14 features.
One of the new features is monitoring if a user loses network connection.
However I am getting a strange error when I run the following code.
TaView.swift (default view)
import SwiftUI
struct TaView: View {
#StateObject var monitor = Monitor()
#ObservedObject var location = LocationManager()
#State var errorDetail = false
var lat: String{
return "\(location.lastKnownLocation?.coordinate.latitude ?? 0.0)"
}
var lon: String{
return "\(location.lastKnownLocation?.coordinate.longitude ?? 0.0)"
}
var state: String{
return "\(UserSettings().state)"
}
init() {
// print(self.data.connected)
self.location.startUpdating()
}
#ObservedObject var userSettings = UserSettings()
var body: some View {
if (self.lat == "0.0" && self.lon == "0.0"){
LocationDisabled()
}
else{
if #available(iOS 14.0, *) {
TabView {
ContentView()
.tabItem {
Image(systemName: "dot.radiowaves.left.and.right")
Text("Radio")
}
WinView()
.tabItem {
Image(systemName: "w.circle")
Text("Win")
}
SettingsView()
.tabItem {
Image(systemName: "gear")
Text("Settings")
}
}.accentColor(Color.red)
.onAppear(){
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { (timer) in
if monitor.score == 0{
DispatchQueue.main.asyncAfter(deadline: .now()) {
self.errorDetail = true
}
}
//print("this is the score \(monitor.score)")
}
}
.fullScreenCover(isPresented: self.$errorDetail, content: NetworkOutageView.init)
} else {
TabView {
ContentView()
.tabItem {
Image(systemName: "dot.radiowaves.left.and.right")
Text("Radio")
}
WinView()
.tabItem {
Image(systemName: "w.circle")
Text("Win")
}
SettingsView()
.tabItem {
Image(systemName: "gear")
Text("Settings")
}
}.accentColor(Color.red)
.onAppear(){
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { (timer) in
if monitor.score == 0{
DispatchQueue.main.asyncAfter(deadline: .now()) {
self.errorDetail = true
}
}
//print("this is the score \(monitor.score)")
}
}
.sheet(isPresented: self.$errorDetail, content: NetworkOutageView.init)
}
}
}
}
struct LocationDisabled: View {
#ObservedObject var location = LocationManager()
init() {
self.location.startUpdating()
}
var body: some View {
GeometryReader { geo in
VStack{
Spacer().frame(maxHeight: 100)
Image(systemName: "location.fill").resizable().scaledToFit().frame(width: 100).foregroundColor(Color.white)
VStack{
Text("Enable Location").font(.system(.largeTitle, design: .rounded)).bold().multilineTextAlignment(.leading).foregroundColor(Color.white)
Text("You'll need to enable your location.\nIn order to use access these features").fontWeight(.light).multilineTextAlignment(.center).fixedSize(horizontal: false, vertical: true).padding(.all, 8).foregroundColor(Color.white)
Text("\u{2022} Win Prizes\n\n\u{2022} Change Stations\n\n\u{2022} Access Podcasts\n\n\u{2022} Request Songs\n\n\u{2022} And More").bold().multilineTextAlignment(.center).fixedSize(horizontal: false, vertical: true).padding(.all, 8).foregroundColor(Color.white)
Spacer()
Button(action: {
self.location.requestLoc()
}) {
Text("ALLOW LOCATION")
.font(.headline)
.bold()
}.buttonStyle(LocationGradientButtonStyle())
.padding(.bottom, 100)
}
// ImageOverlay()
}.frame(maxWidth: .infinity,maxHeight: .infinity).edgesIgnoringSafeArea(.all).background(
Image("TooFarWallPaper").resizable().aspectRatio(contentMode: .fill).frame(maxWidth: .infinity,maxHeight: .infinity).edgesIgnoringSafeArea(.all)
)
}
}
}
struct LocationGradientButtonStyle: ButtonStyle {
func makeBody(configuration: Self.Configuration) -> some SwiftUI.View {
configuration.label
.foregroundColor(Color.white)
.padding()
.background(LinearGradient(gradient: Gradient(colors: [Color.blue, Color.purple]), startPoint: .topLeading, endPoint: .bottomTrailing))
.cornerRadius(15.0)
}
}
struct SaveGradientButtonStyle: ButtonStyle {
func makeBody(configuration: Self.Configuration) -> some SwiftUI.View {
configuration.label
.foregroundColor(Color.black)
.padding()
.background(LinearGradient(gradient: Gradient(colors: [Color.green, Color.green]), startPoint: .topLeading, endPoint: .bottomTrailing))
.cornerRadius(15.0)
}
}
Monitor.swift
import Network
import SwiftUI
// An enum to handle the network status
enum NetworkStatus: String {
case connected
case disconnected
}
class Monitor: ObservableObject {
private let monitor = NWPathMonitor()
private let queue = DispatchQueue(label: "Monitor")
#Published var score = 0
#Published var status: NetworkStatus = .connected
init() {
monitor.pathUpdateHandler = { [weak self] path in
guard let self = self else { return }
// Monitor runs on a background thread so we need to publish
// on the main thread
DispatchQueue.main.async {
if path.status == .satisfied {
print("We're connected!")
self.status = .connected
self.score = 1
} else {
print("No connection.")
self.score = 0
self.status = .disconnected
}
}
}
monitor.start(queue: queue)
}
}
The error is
Thread 1: signal SIGABRT
I am wondering how do I fix this?
Changing #StateObject to ObservedObject works great.
Note: you don't always need to write the same code again in if and else when checking for #availability (when doing backwards compatibility), you can just create one single variable for a View and reuse it, like in this case we reuse tabViewContent.
struct TaView: View {
#ObservedObject var monitor = Monitor()
#ObservedObject var location = LocationManager()
#State var errorDetail = false
var lat: String{
return "\(location.lastKnownLocation?.coordinate.latitude ?? 0.0)"
}
var lon: String{
return "\(location.lastKnownLocation?.coordinate.longitude ?? 0.0)"
}
var state: String{
return "\(UserSettings().state)"
}
init() {
// print(self.data.connected)
self.location.startUpdating()
}
#ObservedObject var userSettings = UserSettings()
var tabViewContent: some View {
TabView {
ContentView()
.tabItem {
Image(systemName: "dot.radiowaves.left.and.right")
Text("Radio")
}
WinView()
.tabItem {
Image(systemName: "w.circle")
Text("Win")
}
SettingsView()
.tabItem {
Image(systemName: "gear")
Text("Settings")
}
}.accentColor(Color.red)
.onAppear(){
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { (timer) in
if monitor.score == 0{
self.errorDetail = true
} else {
self.errorDetail = false
}
//print("this is the score \(monitor.score)")
}
}
}
var body: some View {
if (self.lat == "0.0" && self.lon == "0.0"){
LocationDisabled()
}
else{
if #available(iOS 14.0, *) {
tabViewContent
.fullScreenCover(isPresented: self.$errorDetail, content: NetworkOutageView.init)
} else {
tabViewContent
.sheet(isPresented: self.$errorDetail, content: NetworkOutageView.init)
}
}
}
}
Tested with Xcode 12.4, on iOS13.3.1 and iOS 14.4.2
Related
When I turn the wifi on and off the mainChatView init is called again but not the landingView init. Why?
So when the wifi is toggled in the console it is printed main chat init again
this is the code of the landingView:
struct LandingView: View {
#State private var selection:Int = 2
#State var connected: Bool = true
#State var supposeToBeConnected: Bool = true
#StateObject var networkReachability = NetworkReachability()
var timer = Timer()
init(){
print("landing page init")
}
var body: some View {
if connected {
content
}else{
connectingView()
}
}
var content: some View {
ZStack{
VStack{
TabView(){
MainChatView()
.tabItem {
Image(systemName: "message")
}
HomeView()
.tabItem {
Image(systemName: "house.fill")
}
yourGroups()
.tabItem {
Image(systemName: "rectangle.3.group.fill")
}
AccontView()
.tabItem {
Image(systemName: "person.fill")
}
}
.padding(.all, -2.0)
.onAppear() {
UITabBar.appearance().barTintColor = .black
Auth.auth().addStateDidChangeListener { auth, user in
if let user = user {
if user != nil {
self.connected = true
self.supposeToBeConnected = true
}else{
self.supposeToBeConnected = false
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
if !supposeToBeConnected{
print("cont changed")
self.connected = false
}
}
}
}
}
OnligneStatus()
Timer.scheduledTimer(withTimeInterval: 60, repeats: true, block: { _ in
OnligneStatus()
})
}
.statusBar(hidden: true)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.edgesIgnoringSafeArea(.all)
}
.frame(maxWidth: .infinity, maxHeight: .infinity,alignment: .top)
.ignoresSafeArea(.all)
.padding(.all, -1.0)
}
}
func OnligneStatus(){
print("online")
let db = Firestore.firestore()
if Auth.auth().currentUser != nil{
db.collection("users").document(Auth.auth().currentUser!.uid).updateData([
"onLine":Date()])
}
}
}
And this is the init:
init(){
print("main chat init")
}
Thanks for helping me this bug caused image loading errors and text loading bugs
I am trying through an external library to obtain the temperature of a device,
when the screen starts the temperature value is "----" when the device gives me the temperature result through a delegate I want to update the view with the value that is to save in the class (ts28bControllerDelegate) the value of the temperature and retrieve it in the view to show it, as I have my code always remains blank (Text ("\ (global.temp)"))
//
// TakeTemperatureTS28BUIView.swift
// aidicarev3UI
//
// Created by Laura Ramirez on 26/08/21.
//
import SwiftUI
struct ContentView2: View {
#State private var index = 1
#EnvironmentObject private var global: GlobalTs28b
init() {
Theme.navigationBarColors(background: .white , titleColor: UIColor( red: CGFloat(92/255.0), green: CGFloat(203/255.0), blue: CGFloat(207/255.0), alpha: CGFloat(1.0)))
}
var body: some View {
VStack{
ScrollView{
VStack{
VStack(){
Image("bluetooth-5")
.resizable()
.frame(width: UIScreen.main.bounds.width / 2, height: 140.0)
.padding()
Text("temp15Tittle")
.modifier(Fonts(fontName: .bold, size: 16))
.foregroundColor(Color("blueColor"))
.fixedSize(horizontal: false, vertical: true)
.padding(.top,30)
}
Divider()
.padding()
Text("temp1Tittle")
.frame(maxWidth: .infinity, alignment: .center)
.modifier(Fonts(fontName: .bold, size: 16))
.foregroundColor(Color("blackColor"))
.fixedSize(horizontal: false, vertical: true)
.padding(.top,10)
.padding()
HStack{
Text("\(global.temp)")
.autocapitalization(.none)
.foregroundColor(Color("blackColor"))
.padding(.leading,20)
Text("°C")
.modifier(Fonts(fontName: .bold, size: 16))
.foregroundColor(Color("blackColor"))
.padding()
}
.foregroundColor(Color("blackColor"))
.overlay(RoundedRectangle(cornerRadius: 40).stroke(Color("grayColor"), lineWidth: 1)).background(RoundedRectangle(cornerRadius: 40).fill(Color("whiteColor")))
.padding(.trailing,60)
.padding(.leading,60)
Button(action:{
SaveTemp()
}){
HStack{
Text("temp16Tittle")
.foregroundColor(Color("whiteColor"))
.modifier(Fonts(fontName: .bold, size: 16))
.frame(width: 150 , height: 10, alignment: .center)
}
.foregroundColor(Color("whiteColor"))
.modifier(Fonts(fontName: .medium, size: 16))
.padding()
.background(Color("blueColor"))
.cornerRadius(80)
.padding(.top,30)
}
}
}
.padding()
.padding()
Spacer()
MenuMain(index: self.$index)
}
.background(Color("backgroundColor"))
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .principal) {
VStack {
Text("temp7Tittle").font(.headline)
.modifier(Fonts(fontName: .light, size: 18))
.foregroundColor(Color("grayDarkColor"))
.fixedSize(horizontal: false, vertical: true)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
}
.onAppear {
iHealthAuthTS28B()
}
.onDisappear {
//desconectar dispositivos
}
}
}
struct TakeTemperatureTS28BUIView_Previews: PreviewProvider {
static var previews: some View {
NavigationView{
TakeTemperatureTS28BUIView()
.navigationBarTitleDisplayMode(.inline)
.accentColor(.black)
.toolbar { // <2>
ToolbarItem(placement: .principal) { // <3>
HStack {
Text("temp7Tittle").font(.headline)
.modifier(Fonts(fontName: .light, size: 18))
.foregroundColor(Color("grayDarkColor"))
.fixedSize(horizontal: false, vertical: true)
.frame(maxWidth: .infinity, alignment: .leading)
Spacer()
}
}
}
}
}
}
struct TakeTemperatureTS28BUIView: View {
#StateObject private var global = GlobalTs28b()
var body: some View {
ContentView2()
.environmentObject(global)
}
}
func iHealthAuthTS28B() {
print("ENTRA EN AUTENTIFICACION DE IHEALTH TS28B")
let bundle = Bundle.main
let path = bundle.path(forResource: "com_aidicare_aidicarev3UI_ios", ofType: ".pem")
let cert = NSData(contentsOfFile: path!)
print(cert as Any)
let delegate = ts28bControllerDelegate.init()
IHSDKCloudUser.commandGetSDKUserInstance().commandSDKUserValidation(withLicense: cert as Data?, userDeviceAccess: {
devices in
print("--devices--")
print(devices as Any)
}, userValidationSuccess: { UserAuthenResult in
print("--UserAuthenResult--")
print(UserAuthenResult)
delegate.StartSync()
}, disposeErrorBlock: { UserAuthenResult in
print("--UserAuthenResult--")
print(UserAuthenResult)
switch (UserAuthenResult) {
case UserAuthen_InputError:
print("error")
break;
case UserAuthen_CertificateExpired:
print("certiificado expirado")
break;
case UserAuthen_InvalidCertificate:
print("certificado no valido")
break;
default:
break;
}
})
}
func Sincroniza(){
print("ENTRA EN TOMA DE TEMPERATURA TS28B")
iHealthAuthTS28B()
}
func SaveTemp(){
print("ENTRA EN GUARDAR DE TEMPERATURA")
let global = GlobalTs28b()
print("VALOR: ", global.temp)
}
class GlobalTs28b: ObservableObject {
#Published var temp: String = "----"
#Published var state: String = "----"
}
class ts28bControllerDelegate: NSObject, TS28BControllerDelegate {
var myCentralManager: CBCentralManager = CBCentralManager()
var controllerTS28B: TS28BController = TS28BController()
let user: HealthUser = HealthUser()
var device: TS28B = TS28B()
var connectedDevice: TS28B?
var global = GlobalTs28b()
override init() {
super.init()
print("ENTRA EN StartDiscoverTS28B")
controllerTS28B = TS28BController.shared()
controllerTS28B.delegate = self
}
func StartSync(){
print("empieza StartSync")
controllerTS28B.startScan()
}
// MARK: - delegate
public func controller(_ controller: TS28BController?, didDiscoverDevice device: TS28B?) {
print("The agent of the device is found")
connectedDevice = device
controller?.connectDevice(connectedDevice)
if let device = device {
print("DiscoverDevice: \(device)")
}
}
public func controller(_ controller: TS28BController?, didConnectSuccessDevice device: TS28B?) {
print("Successfully connected agent")
connectedDevice = device
if let device = device {
print("DiscoverDevice: \(device)")
}
}
public func controller(_ controller: TS28BController?, didConnectFailDevice device: TS28B?) {
print("Proxy failed to connect")
// self.recordTextView.text = #"连接失败";
}
public func controller(_ controller: TS28BController?, didDisconnectDevice device: TS28B?) {
print("Disconnected proxy")
// self.recordTextView.text = #"连接断开";
if let device = device {
print("DisConnectDevice: \(device) ")
}
}
public func controller(_ controller: TS28BController?, device: TS28B?, didUpdateTemperature value: Float, temperatureUnit unit: TemperatureUnit, measure date: Date?, measureLocation type: TemperatureType) {
print("Temperature UNIDAD:", unit)
print("Temperature:", value)
let valueFinal = ((value - 32) * 5/9)
let stringFloat = String(describing: valueFinal)
global.temp = stringFloat
print("centigadros:", global.temp)
}
}
can someone help me understand this?
thanks!
Regarding your (second) question in your comment,
here is some code that shows an approach to "send" a value from a
class (does not have to be a view) and receive that value in a View.
You could use this approach in your "ts28bControllerDelegate",
to send the temperature updates as they arrive in your ts28bControllerDelegate and
receive them in your views using .onReceive(...)
public func controller(_ controller: TS28BController?, device: TS28B?, didUpdateTemperature value: Float, temperatureUnit unit: TemperatureUnit, measure date: Date?, measureLocation type: TemperatureType) {
print("Temperature UNIDAD:", unit)
print("Temperature:", value)
let valueFinal = ((value - 32) * 5/9)
let stringFloat = String(valueFinal)
// send a message with the temp value
NotificationCenter.default.post(name: GlobalTs28b.globalMsg, object: stringFloat)
}
class GlobalTs28b: ObservableObject {
#Published var temp: String = "----"
#Published var state: String = "----"
// for testing, does not have to be in this class
static let globalMsg = Notification.Name("GlobalTs28b")
}
struct ContentView: View {
#StateObject var global = GlobalTs28b() // for testing
var body: some View {
NavigationView {
VStack (spacing: 55) {
NavigationLink("go to next view", destination: ViewTest2())
Text(global.temp).foregroundColor(.red)
}
.onReceive(NotificationCenter.default.publisher(for: GlobalTs28b.globalMsg)) { msg in
if let temp = msg.object as? String {
// update the StateObject with the new info, so the view will update
global.temp = temp
}
}
}.navigationViewStyle(.stack)
}
}
struct ViewTest2: View {
var body: some View {
VStack {
Button(action: {
// send a message to all listeners with the new temp,
// could be used in any class such as ts28bControllerDelegate
NotificationCenter.default.post(name: GlobalTs28b.globalMsg, object: "new temp")
}) {
Text("click to update temp")
}
}
}
}
I like to re-build a customEditMode like same editMode in SwiftUI for learning purpose, I could made my code until a full error codes as possible, that was not my plan! However here is what I tried until now, need help to get this codes work. thanks
Update:
Why this Circle color does not change?
struct ContentView: View {
#Environment(\.customEditMode) var customEditMode
var body: some View {
CircleView()
VStack {
Button("active") { customEditMode?.wrappedValue = CustomEditMode.active }.padding()
Button("inactive") { customEditMode?.wrappedValue = CustomEditMode.inactive }.padding()
Button("none") { customEditMode?.wrappedValue = CustomEditMode.none }.padding()
}
.onChange(of: customEditMode?.wrappedValue) { newValue in
if newValue == CustomEditMode.active {
print("customEditMode is active!")
}
else if newValue == CustomEditMode.inactive {
print("customEditMode is inactive!")
}
else if newValue == CustomEditMode.none {
print("customEditMode is none!")
}
}
}
}
struct CircleView: View {
#Environment(\.customEditMode) var customEditMode
var body: some View {
Circle()
.fill(customEditMode?.wrappedValue == CustomEditMode.active ? Color.green : Color.red)
.frame(width: 150, height: 150, alignment: .center)
}
}
If you take a closer look at the editMode:
#available(macOS, unavailable)
#available(watchOS, unavailable)
public var editMode: Binding<EditMode>?
you can see that it is in fact a Binding. That's why you access its value using wrappedValue.
You need to do the same for your CustomEditModeEnvironmentKey:
enum CustomEditMode {
case active, inactive, none
// optionally, if you need mapping to `Bool?`
var boolValue: Bool? {
switch self {
case .active: return true
case .inactive: return false
case .none: return nil
}
}
}
struct CustomEditModeEnvironmentKey: EnvironmentKey {
static let defaultValue: Binding<CustomEditMode>? = .constant(.none)
}
extension EnvironmentValues {
var customEditMode: Binding<CustomEditMode>? {
get { self[CustomEditModeEnvironmentKey] }
set { self[CustomEditModeEnvironmentKey] = newValue }
}
}
Here is a demo:
struct ContentView: View {
#State private var customEditMode = CustomEditMode.none
var body: some View {
TestView()
.environment(\.customEditMode, $customEditMode)
}
}
struct TestView: View {
#Environment(\.customEditMode) var customEditMode
var body: some View {
Circle()
.fill(customEditMode?.wrappedValue == .active ? Color.green : Color.red)
.frame(width: 150, height: 150, alignment: .center)
VStack {
Button("active") { customEditMode?.wrappedValue = .active }.padding()
Button("inactive") { customEditMode?.wrappedValue = .inactive }.padding()
Button("none") { customEditMode?.wrappedValue = .none }.padding()
}
.onChange(of: customEditMode?.wrappedValue) { newValue in
print(String(describing: newValue))
}
}
}
I am currently creating a FaceID-aware app using Swift UI.
What I am trying to do is try FaceID authentication when the user presses the button. When I call class in button action, I get the error message "Result of 'DashboardView' initializer is unused". The related sources are as below. Any help would be appreciated!
struct FaceLoginView: View {
#State private var isUnlocked = false
var body: some View {
VStack {
Button(action: {
print("face id tapped!")
if self.isUnlocked {
// print("unlocked")
DashboardView()
} else {
// Text("Locked")
LoginView()
}
}) {
HStack {
Image(systemName: "faceid")
.font(.title)
Text("faceid")
.fontWeight(.semibold)
.font(.title)
}
.frame(minWidth: 0, maxWidth: .infinity)
.padding()
.foregroundColor(.white)
.background(LinearGradient(gradient: Gradient(colors: [Color("DarkGreen"), Color("LightGreen")]), startPoint: .leading, endPoint: .trailing))
.cornerRadius(40)
}
}
.onAppear(perform: authenticate)
}
func authenticate() {
let context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
let reason = "Log in to your account by unlocking FaceID."
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, authenticationError in
DispatchQueue.main.async {
if success {
// authenticated successfully
self.isUnlocked = true
} else {
// there was a problem
self.isUnlocked = false
print(error?.localizedDescription ?? "Failed to authenticate")
}
}
}
} else {
// no biometrics
print(error?.localizedDescription ?? "Can't evaluate policy")
}
}
}
check this out:
i had to comment out some things and change some things because your example wasn't compilable at all but things should be clear to you if you see it ;)
struct DashboardView : View {
var body: some View {
Text("Dashboardview")
}
}
struct LoginView : View {
var body: some View {
Text("LoginView")
}
}
struct FaceLoginView: View {
private var isUnlocked : Bool {
get {
return Bool.random()
}
set {
self.isUnlocked = newValue
}
}
#State var navigateToDashboard = false
#State var navigateToLogin = false
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: DashboardView(), isActive: $navigateToDashboard) { EmptyView().hidden()
}.hidden().frame(height:0)
NavigationLink(destination: LoginView(), isActive: $navigateToLogin) { EmptyView().hidden()
}.hidden().frame(height:0)
Button(action: {
print("face id tapped!")
if self.isUnlocked {
// print("unlocked")
self.navigateToDashboard.toggle()
} else {
// Text("Locked")
self.navigateToLogin.toggle()
}
}) {
HStack {
Image(systemName: "faceid")
.font(.title)
Text("faceid")
.fontWeight(.semibold)
.font(.title)
}
.frame(minWidth: 0, maxWidth: .infinity)
.padding()
// .foregroundColor(.white)
.background(LinearGradient(gradient: Gradient(colors: [Color("DarkGreen"), Color("LightGreen")]), startPoint: .leading, endPoint: .trailing))
.cornerRadius(40)
}
}
}
.onAppear(perform: authenticate)
}
func authenticate() {
// let context = LAContext()
var error: NSError?
// if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
// let reason = "Log in to your account by unlocking FaceID."
// context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, authenticationError in
// DispatchQueue.main.async {
// if success {
// // authenticated successfully
// self.isUnlocked = true
// } else {
// // there was a problem
// self.isUnlocked = false
// print(error?.localizedDescription ?? "Failed to authenticate")
// }
//
// }
// }
// } else {
// // no biometrics
// print(error?.localizedDescription ?? "Can't evaluate policy")
//
// }
}
}
struct ContentView: View {
var body: some View {
FaceLoginView()
}
}
I'm working on a Bluetooth Application.It has onboarding and dashboard.On the Onboarding there is pairing and instructions on how to use the module, and the dashboard controls the peripheral device.So I need to unpair using an alert and navigate it to a different page called Onboarding.How can I navigate to a different view using an alert.
Code Block
import SwiftUI
import BLE
struct Dashboard: View {
#EnvironmentObject var BLE: BLE
#State private var showUnpairAlert: Bool = false
#State private var hasConnected: Bool = false
let defaults = UserDefaults.standard
let defaultDeviceinformation = "01FFFFFFFFFF"
struct Keys {
static let deviceInformation = "deviceInformation"
}
var body: some View {
VStack(alignment: .center, spacing: 0) {
// MARK: - Menu Bar
HStack(alignment: .center, spacing: 10) {
VStack(alignment: .center, spacing: 4) {
Text(self.hasConnected ? "PodId \(checkForDeviceInformation())":"Pod is not connected")
.font(.footnote)
.foregroundColor(.white)
Button(action: {
print("Unpair tapped!")
self.showUnpairAlert = true
}) {
HStack {
Text("Unpair")
.fontWeight(.bold)
.font(.body)
}
.frame(minWidth: 85, minHeight: 35)
.foregroundColor(.white)
.background(Color(red: 0.8784313725490196, green: 0.34509803921568627, blue: 0.36470588235294116))
.cornerRadius(30)
}
}
}
}
.alert(isPresented: $showUnpairAlert) {
Alert(title: Text("Unpair from \(checkForDeviceInformation())"), message: Text("Do you want to unpair the current pod?"), primaryButton: .destructive(Text("Unpair")) {
self.unpairAndSetDefaultDeviceInformation()
}, secondaryButton: .cancel())
}
}
func checkForDeviceInformation() -> String {
let deviceInformation = defaults.value(forKey: Keys.deviceInformation) as? String ?? ""
print("Device Info \(deviceInformation)")
return deviceInformation
}
func unpairAndSetDefaultDeviceInformation() {
defaults.set(defaultDeviceinformation, forKey: Keys.deviceInformation)
print("Pod unpaired and view changed to Onboarding")
}
}
Thank you !!!!
I simplified your code snapshot for demo, but think the idea would be clear
struct TestNavigationFromAlert: View {
#State private var showUnpairAlert: Bool = false
#State private var activateLink: Bool = false
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: Text("Your Onboarding page"), isActive: $activateLink,
label: { EmptyView() })
// DEMO BUTTON - REMOVE IT
Button(action: { self.showUnpairAlert = true }) { Text("Alert") }
// YOUR CODE IS HERE
}
.alert(isPresented: $showUnpairAlert) {
Alert(title: Text("Unpair from \(checkForDeviceInformation())"), message: Text("Do you want to unpair the current pod?"), primaryButton: .destructive(Text("Unpair")) {
self.unpairAndSetDefaultDeviceInformation()
}, secondaryButton: .cancel())
}
}
}
func checkForDeviceInformation() -> String {
// YOUR CODE IS HERE
return "Stub information"
}
func unpairAndSetDefaultDeviceInformation() {
// YOUR CODE IS HERE
DispatchQueue.main.async {
self.activateLink = true
}
}
}