CocoaMQTT init, Can't seem to connect to MQTT Broker - swift

Please excuse how much of a newbie I am. I started on swift at the beginning of last week...
I am trying to make an app that uses BLE and or MQTT to talk to a raspberry pi through a broker. the BLE side is ok but the MQTT (for when out of BLE range) I'm having trouble with.
This is in a swift file of a couple of classes:
import Foundation
import CocoaMQTT
class MQTTManager{
static let shared = MQTTManager()
private var mqttClient: CocoaMQTT
init() {
let clientID = "swift-Trial-13579"
let host = "IP.Goes.Here"
let port = UInt16(1883)
self.mqttClient = CocoaMQTT(clientID: clientID, host: host, port: port)
self.mqttClient.username = "User"
self.mqttClient.password = "Pass"
self.mqttClient.keepAlive = 60
self.mqttClient.connect()
sendMessage(topic: "app/init", message: "init called")
print("MQTT Init Called")
}
func sendMessage(topic:String, message:String){
self.mqttClient.publish(topic, withString: message)
print("publish MQTT called with message: \(message) and a topic of: \(topic)")
}
}
class useProperties: ObservableObject{
#Published var useMQTT = false
#Published var recallMQTTScene = false
#Published var MQTTScene = 0
init(){
}
}
I then have 3 views, ContentView
import SwiftUI
import CocoaMQTT
struct ContentView: View {
#State public var Connection:Bool = false
#State public var SceneMessqe: String = ""
let MQTTHandle = MQTTManager()
// the main view actually is here
var body: some View{
// SceneButton(function: { self.MQTTPub})
VStack{
HStack {
Text("MultiControl POC")
.font(.title)
//.padding()
}
Spacer()
mainSwitch()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.environmentObject(BLEManager())
}
}
mainSwitch
import SwiftUI
import CocoaMQTT
struct mainSwitch: View {
#State public var Connection:Bool = false
#State private var selection: String? = nil
#StateObject var bleManager = BLEManager() // gets from environment.
public var properties = useProperties()
#State private var selectDeviceShown = false
#State var isPresenting = false
public var MQTTHandle = MQTTManager()
var body: some View {
VStack (spacing: 0){
NavigationView{
HStack {
Spacer()
NavigationLink(destination: sheetView(), isActive: $isPresenting) { EmptyView() }// added for nav but not working
Menu("Menu") {
Button("BLE Setup", action: {
self.isPresenting = true // added to trigger nav not workinh
print("Setup button pressed")
//selectDeviceShown = true
})
Button("Reconnect", action: {
bleManager.myCentral.connect(bleManager.wrappedControllers[bleManager.currentSceneSwitchControllerUUID]!.wrappedPerh)
})
Button(action: {
MQTTManager.init()
Connection.toggle()
properties.useMQTT = true
print("connect/disconnect pressed useMQTT = \(properties.useMQTT)")
}, label: {
Text(Connection ? "MQTT Disconnect":"MQTT Connect")
})
Button("Cancel", action: {
print("oops")
})
}
.foregroundColor(Connection ? .green : .red)
.padding(38)
.overlay(
RoundedRectangle(cornerRadius: 15)
.stroke(lineWidth: 2)
.foregroundColor(Connection ? .green : .red)
)
Spacer()
Spacer()
}
.fixedSize(horizontal: false, vertical: true)
.frame(maxHeight: 10)
.padding()
}
HStack{
Spacer()
VStack{
Spacer()
SceneButton(sceneName: "Scene 1", sceneNumber: 1)
Spacer()
SceneButton(sceneName: "Scene 3" , sceneNumber: 3)
Spacer()
SceneButton(sceneName: "Scene 5", sceneNumber: 5)
Spacer()
}
Spacer()
VStack{
Spacer()
SceneButton(sceneName: "Scene 2", sceneNumber: 2)
Spacer()
SceneButton(sceneName: "Scene 4", sceneNumber: 4)
Spacer()
SceneButton(sceneName: "Off", sceneNumber: 6)
Spacer()
}
Spacer()
}
Spacer()
}
.environmentObject(useProperties())
.environmentObject(BLEManager())
}
}
struct mainSwitch_Previews: PreviewProvider {
static var previews: some View {
Group {
mainSwitch()
.environmentObject(BLEManager())
.environmentObject(useProperties())
}
}
}
and finally sceneButton
import SwiftUI
import CocoaMQTT
struct SceneButton: View {
var sceneName: String
var sceneNumber: Int
let properties = useProperties()
#State private var isDisabled: Bool = true
#State private var isDuringGesture: Bool = false
#StateObject private var bleManager = BLEManager()
let btnClr:Color = Color.orange
let btnClrOutr:Color = Color.red
let btnPressedClr:Color = Color.gray
let MQTTHandle = MQTTManager()
var body: some View {
if (properties.useMQTT){
Button(sceneName) {
bleManager.writeToCharacteristicButtonPress(peripheral: bleManager.currentSceneSwitchControllerUUID, sceneToGoToo: (sceneNumber).description, setButtonPressed: true) // Note the number is the same number as the button.
bleManager.writeToCharacteristicButtonPress(peripheral: bleManager.currentSceneSwitchControllerUUID, sceneToGoToo: (sceneNumber).description, setButtonPressed: false)
print("BLE Button" + sceneName)
print("\(properties.useMQTT)")
}
.foregroundColor(.white)
.frame(minWidth: 100)
.padding()
.background(Color(red: 1, green: 0.1, blue: 0.1))
.cornerRadius(10)
.padding(10)
.font(.title2)
.font(.system(size: 20))
}else{
Button(sceneName) {
print("\(properties.useMQTT)")
MQTTHandle.sendMessage(topic: "apptest/scene", message: "\(sceneNumber)")
}
.frame(minWidth: 100)
.padding()
.background(Color(red: 0.40, green: 0.60, blue: 0))
.cornerRadius(10)
.padding(10)
}
}
}
struct SceneButton_Previews: PreviewProvider {
static var previews: some View {
SceneButton(sceneName: "Scene X", sceneNumber: 42) //, publishSceneMQTT: sceneHandle
.environmentObject(BLEManager())
.environmentObject(useProperties())
}
}
Currently when the app loads it calls the MQTT init many times, and then doesn't connect reliably, occasionally, maybe 1 in 10 times it connects to send a single message then I can't send more.
Ideally it would only connect when I press the connect button in the menu in mainSwitch. However each button (SceneButton) should publish something slightly different.
Firstly, is it an issue that it keeps calling init at start?
Secondly, is there something visible that I am doing wrong to mean its not reliably connecting?
thirdly, (least important) in sceneButton the button should change whether using BLE or MQTT, this variable, useMQTT is set in the mainSwitch file. but doesn't change in sceneButton, what have I done wrong?

You use everywhere (!) different instances of MQTTManager, because create it via init, instead you should use everywhere MQTTManager.shared, like
struct ContentView: View {
#State public var Connection:Bool = false
#State public var SceneMessqe: String = ""
// let MQTTHandle = MQTTManager() // << not this !!
let MQTTHandle = MQTTManager.shared // << this one !!
so review all your code and fix as above.

Related

SwiftUI - How to add a screen to a section of segmental control

I have coded a currency converter page, however I want to add this converter to a section on a segmented control. How can I add this page to one section in a segmented control so one section of the control is currency conversion and then when I click on the other section it will take me to another page?
import SwiftUI
struct ContentView: View {
#State var input = "100"
#State var base = "USD"
#State var currencyList = [String]()
#FocusState private var inputIsFocused: Bool
func makeRequest (showAll: Bool, currencies: [String] = ["USD", "GBP", "EUR"]) {
apiRequest(url:
"https:api.exchangerate.host/latest?base=\(base)&amount=\(input)") { currency in
var tempList = [String]()
for currency in currency.rates {
if showAll {
tempList.append("\(currency.key) \(String(format: "%.2f", currency.value))")
} else if currencies.contains(currency.key) {
tempList.append("\(currency.key) \(String(format: "%.2f", currency.value))")
}
tempList.sort()
}
currencyList.self = tempList
print(tempList)
}
}
var body: some View {
VStack {
HStack {
Text("Currencies")
.font(.system(size: 30))
.bold()
Image(systemName: "yensign.square")
.font(.system(size: 30))
.foregroundColor(.black)
}
List {
ForEach(currencyList, id: \.self) { currency in
Text(currency)
}
}
VStack {
Rectangle()
.frame(height: 8.0)
.foregroundColor(.black)
.opacity(0.90)
TextField("Enter an Amount", text: $input)
.padding()
.background(Color.gray.opacity(0.10))
.cornerRadius(20.0)
.padding()
.keyboardType(.decimalPad)
.focused($inputIsFocused)
TextField("Enter a Currency", text: $base)
.padding()
.background(Color.gray.opacity(0.10))
.cornerRadius(20.0)
.padding()
.focused($inputIsFocused)
Button("Convert") {
makeRequest(showAll: true, currencies: ["DKK", "SEK" ,"NOK"])
inputIsFocused = false
}.padding()
}
}.onAppear {
makeRequest(showAll: true)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View{
ContentView()
}
}
`
I built the segmented control separate to the converter, however one was built with SwiftUi and the other was built using storyboard, so How can I combine the two?

Getting Values from own PickerView

I'm new to Swift and I'm currently developing my own Timer Application for practice purposes. (I do it without storyboard)
Now I have the Problem that i made a View called "TimePickerView" (Code below), where I created my own Picker. Then I use that TimePickerView in another part of my Application with other Views (in a View). In that View I want to pick my time but I don't know how i can get the Values of the Picker (The Picker works by the way)
This is my TimePickerView
import SwiftUI
struct TimePickerView: View {
#State private var selectedTimeIndexSecond = 0
#State private var selectedTimeIndexMinutes = 0
#State private var seconds : [Int] = Array(0...59)
#State private var minutes : [Int] = Array(0...59)
var body: some View {
VStack{
Text("Select Your Time")
HStack{
//minutes-Picker
Picker("select time", selection: $selectedTimeIndexMinutes, content: {
ForEach(0..<minutes.count, content: {
index in
Text("\(minutes[index]) min").tag(index)
})
})
.padding()
.frame(width: 120)
.clipped()
//seconds-Picker
Picker("select time", selection: $selectedTimeIndexSecond, content: {
ForEach(0..<seconds.count, content: {
index in
Text("\(seconds[index]) sec").tag(index)
})
})
.padding()
.frame(width: 120)
.clipped()
Spacer()
}
Text("You picked the time")
.multilineTextAlignment(.center)
.font(.title2)
.padding()
Text("\(minutes[selectedTimeIndexMinutes]) min : \(seconds[selectedTimeIndexSecond]) sec")
.font(.title)
.bold()
.padding(.top, -14.0)
}
}
func getValues() -> (Int, Int) {
return (self.minutes[selectedTimeIndexMinutes] ,self.seconds[selectedTimeIndexSecond])
}
}
and that is the View I want to use my Picker, but I don't know how I get those values from the Picker:
struct SetTimerView: View {
#State var timepicker = TimePickerView()
var body: some View {
NavigationView{
VStack{
//Select the time
timepicker
//Timer variables (This doesn't work)
var timerTime = timepicker.getValues()
var minutes = timerTime.0
var seconds = timerTime.1
Spacer()
let valid : Bool = isValid(timerTime: minutes+seconds)
//Confirm the time
NavigationLink(
destination:
getRightView(
validBool: valid,
timerTime: minutes*60 + seconds),
label: {
ConfirmButtonView(buttonText: "Confirm")
});
Spacer()
}
}
}
func isValid(timerTime : Int) -> Bool {
if (timerTime == 0) {
return false
} else {
return true
}
}
#ViewBuilder func getRightView(validBool : Bool, timerTime : Int) -> some View{
if (validBool == true) {
TimerView(userTime: CGFloat(timerTime), name: "David", isActive: true)
} else {
UnvalidTimeView()
}
}
}
I think main problem is misunderstanding conceptions between data and views.
At first you need a model witch will override your data (create it in separate swift file):
import Foundation
class Time: ObservableObject {
#Published var selectedTimeIndexMinutes: Int = 0
#Published var selectedTimeIndexSecond: Int = 0
}
Pay attention on ObservableObject so that swiftUI can easily detect changes to it that trigger any active views to redraw.
Next I try to change the value of the model in the view
import SwiftUI
struct TimePickerView: View {
#EnvironmentObject var timeData: Time
#State private var seconds : [Int] = Array(0...59)
#State private var minutes : [Int] = Array(0...59)
var body: some View {
VStack{
Text("Select Your Time")
HStack{
//minutes-Picker
Picker("select time", selection: $timeData.selectedTimeIndexMinutes, content: {
ForEach(0..<minutes.count, content: {
index in
Text("\(minutes[index]) min").tag(index)
})
})
.padding()
.frame(width: 120)
.clipped()
//seconds-Picker
Picker("select time", selection: $timeData.selectedTimeIndexSecond, content: {
ForEach(0..<seconds.count, content: {
index in
Text("\(seconds[index]) sec").tag(index)
})
})
.padding()
.frame(width: 120)
.clipped()
Spacer()
}
Text("You picked the time")
.multilineTextAlignment(.center)
.font(.title2)
.padding()
Text("\(timeData.selectedTimeIndexMinutes) min : \(timeData.selectedTimeIndexSecond) sec")
.font(.title)
.bold()
.padding(.top, -14.0)
}
}
}
struct TimePickerView_Previews: PreviewProvider {
static var previews: some View {
TimePickerView()
.environmentObject(Time())
}
}
Like you can see I don't using #Blinding, instead of it I connecting our Model with a View
On the next view I can see changes, I created a new one because your example have view that don't indicated here...
import SwiftUI
struct ReuseDataFromPicker: View {
#EnvironmentObject var timeData: Time
var body: some View {
VStack{
Text("You selected")
Text("\(timeData.selectedTimeIndexMinutes) min and \(timeData.selectedTimeIndexSecond) sec")
}
}
}
struct ReuseDataFromPicker_Previews: PreviewProvider {
static var previews: some View {
ReuseDataFromPicker()
.environmentObject(Time())
}
}
And collect all in a Content View
struct ContentView: View {
var body: some View {
TabView {
TimePickerView()
.tabItem {Label("Set Timer", systemImage: "clock.arrow.2.circlepath")}
ReuseDataFromPicker()
.tabItem {Label("Show Timer", systemImage: "hourglass")}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.environmentObject(Time())
}
}
Like that you can easily change or reuse your data on any other views

Swift UI button action function

I completely new on Swift, so excuse possible lack of precision. I am trying to build a login form that authenticates with a REST API.
Here is what I have so far following this tutorial.
My next step is understanding where to put all of the logic for submitting the form. I would like to extract it from the inline manner it is taking.
Can I pass a function to the action parameter? I tried finding some sort of extract feature on Xcode but couldn't get it to work (they are greyed).
import SwiftUI
let lightGreyColor = Color(red: 239.0/255.0, green: 243.0/255.0, blue: 244.0/255.0, opacity: 1.0)
let storedUsername = "john"
let storedPassword = "1234"
struct ContentView: View {
#State var username: String = ""
#State var password: String = ""
#State var authenticationDidFail: Bool = false
#State var authenticationDidSucceed: Bool = false
var body: some View {
ZStack {
VStack {
Image("logo")
EmailField(username: $username)
PasswordField(password: $password)
if authenticationDidFail {
Text("Information not correct. Try again.")
.offset(y: -10)
.foregroundColor(.red)
}
Button(action: {
if self.password == storedPassword {
print(password)
self.authenticationDidSucceed = true
self.authenticationDidFail = false
} else {
self.authenticationDidFail = true
}
}) {
LoginButtonContent()
}
}
if authenticationDidSucceed {
Text("Login succeeded!")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct LoginButtonContent: View {
var body: some View {
Text("LOGIN")
.font(.headline)
.foregroundColor(.white)
.padding()
.frame(width: 220, height: 60)
.background(Color.green)
.cornerRadius(15.0)
}
}
struct PasswordField: View {
#Binding var password: String
var body: some View {
SecureField("Password", text: $password)
.padding()
.background(lightGreyColor)
.cornerRadius(5.0)
.padding(.bottom, 20)
}
}
struct EmailField: View {
#Binding var username: String
var body: some View {
TextField("Username", text: $username)
.padding()
.cornerRadius(5.0)
.padding(.bottom, 20)
}
}
You can use an Object of your Model inside your Button's action, there you can execute your REST call and return a result to set a value to authenticationDidSucceed, so that the UI is updated.
If the used class conforms to the ObservableObject protocol you can even use its published variables to automatically update the UI.

Why My second view cannot jump back to the root view properly

My App currently has two pages, first page has a circle plus button which could lead us to a second page. Basically, I have a save button which after clicking it, we could get back to the rood page. I followed this link for going back to root view. I tried the most up voted code, his code works perfectly. I reduced his code to two scene (basically the same scenario as mine), which also works perfectly. But then I don't know why my own code, pasted below, doesn't work. Basically my way of handling going back to root view is the same as the one in the link.
//
// ContentView.swift
// refridgerator_app
//
// Created by Mingtao Sun on 12/22/20.
//
import SwiftUI
import UIKit
#if canImport(UIKit)
extension View {
func hideKeyboard() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
}
#endif
struct ContentView: View {
#EnvironmentObject private var fridge : Fridge
private var dbStartWith=0;
#State var pushed: Bool = false
#State private var selection = 1;
#State private var addFood = false;
var body: some View {
TabView(selection: $selection) {
NavigationView {
List(fridge.container!){
food in NavigationLink(destination: FoodView()) {
Text("HI")
}
}.navigationBarTitle(Text("Fridge Items"), displayMode: .inline)
.navigationBarItems(trailing:
NavigationLink(destination: AddFoodView(pushed: self.$pushed),isActive: self.$pushed) {
Image(systemName: "plus.circle").resizable().frame(width: 22, height: 22)
}.isDetailLink(false) )
}
.tabItem {
Image(systemName: "house.fill")
Text("Home")
}
.tag(1)
Text("random tab")
.font(.system(size: 30, weight: .bold, design: .rounded))
.tabItem {
Image(systemName: "bookmark.circle.fill")
Text("profile")
}
.tag(0)
}.environmentObject(fridge)
}
}
struct FoodView: View{
var body: some View{
NavigationView{
Text("food destination view ");
}
}
}
struct AddFoodView: View{
#Binding var pushed : Bool
#EnvironmentObject private var fridgeView : Fridge
#State private var name = ""
#State private var count : Int = 1
#State private var category : String = "肉类";
#State var showCategory = false
#State var showCount = false
var someNumberProxy: Binding<String> {
Binding<String>(
get: { String(format: "%d", Int(self.count)) },
set: {
if let value = NumberFormatter().number(from: $0) {
self.count = value.intValue;
}
}
)
}
var body: some View{
ZStack{
NavigationView{
VStack{
Button (action: {
self.pushed = false ;
//let tempFood=Food(id: fridgeView.index!,name: name, count: count, category: category);
//fridgeView.addFood(food: tempFood);
} ){
Text("save").foregroundColor(Color.blue).font(.system(size: 18,design: .default)) }
}.navigationBarTitle("Three")
}
ZStack{
if self.showCount{
Rectangle().fill(Color.gray)
.opacity(0.5)
VStack(){
Spacer(minLength: 0);
HStack{
Spacer()
Button(action: {
self.showCount=false;
}, label: {
Text("Done")
}).frame(alignment: .trailing).offset(x:-15,y:15)
}
Picker(selection: $count,label: EmptyView()) {
ForEach(1..<100){ number in
Text("\(number)").tag("\(number)")
}
}.labelsHidden()
} .frame(minWidth: 300, idealWidth: 300, maxWidth: 300, minHeight: 250, idealHeight: 100, maxHeight: 250, alignment: .top).fixedSize(horizontal: true, vertical: true)
.background(RoundedRectangle(cornerRadius: 27).fill(Color.white.opacity(1)))
.overlay(RoundedRectangle(cornerRadius: 27).stroke(Color.black, lineWidth: 1))
.offset(x:10,y:-10)
Spacer()
}
if self.showCategory{
let categoryArr = ["肉类","蔬菜类","饮料类","调味品类"]
ZStack{
Rectangle().fill(Color.gray)
.opacity(0.5)
VStack(){
Spacer(minLength: 0);
HStack{
Spacer()
Button(action: {
self.showCategory=false;
}, label: {
Text("Done")
}).frame(alignment: .trailing).offset(x:-15,y:15)
}
Picker(selection: $category,label: EmptyView()) {
ForEach(0..<categoryArr.count){ number in
Text(categoryArr[number]).tag(categoryArr[number])
}
}.labelsHidden()
} .frame(minWidth: 300, idealWidth: 300, maxWidth: 300, minHeight: 250, idealHeight: 100, maxHeight: 250, alignment: .top).fixedSize(horizontal: true, vertical: true)
.background(RoundedRectangle(cornerRadius: 27).fill(Color.white.opacity(1)))
.overlay(RoundedRectangle(cornerRadius: 27).stroke(Color.black, lineWidth: 1))
Spacer()
}.offset(x:10,y:20)
}
}
}.animation(.easeInOut)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
If you read my code carefully, there are some variables are missing referencing. That's because I pasted part of the code that relates to my issue.
Food Class
//
// Food.swift
// refridgerator_app
//
// Created by Mingtao Sun on 12/23/20.
//
import Foundation
class Food: Identifiable {
init(id:Int, name: String, count: Int, category: String){
self.id=id;
self.name=name;
self.count=count;
self.category=category;
}
var id: Int
var name: String
var count: Int
var category: String
}
Fridge class
//
// Fridge.swift
// refridgerator_app
//
// Created by Mingtao Sun on 12/27/20.
//
import Foundation
class Fridge: ObservableObject{
init(){
db=DBhelper();
let result = setIndex(database: db!);
self.index = result.1;
self.container=result.0;
}
var db:DBhelper?
var index : Int?
#Published var container : [Food]?;
func setIndex(database: DBhelper) -> ([Food],Int){
let foodList : [Food] = database.read();
var index=0;
for food in foodList{
index = max(food.id,index);
}
return (foodList,(index+1));
}
func updateindex(index: inout Int){
index=index+1;
}
func testExist(){
if let data = db {
print("hi")
}
else{
print("doesnt exist")
}
}
func addFood(food:Food){
self.db!.insert(id: self.index!, name: food.name, count:food.count, category: food.category);
self.container!.append(food);
}
}
Because you implemented a new NaviagtionView in AddFoodView. Simply remove this and it should work. Look at the link you provided. There is no NavigationView in the child.
Correct me if Im wrong but the core code parts here that produce this issue are as follows:
Here you start:
struct ContentView: View {
#State var pushed: Bool = false
// Deleted other vars
var body: some View {
TabView(selection: $selection) {
NavigationView {
List(fridge.container!){
food in NavigationLink(destination: FoodView()) {
Text("HI")
}
}.navigationBarTitle(Text("Fridge Items"), displayMode: .inline)
.navigationBarItems(trailing:
// Here you navigate to the child view
NavigationLink(destination: AddFoodView(pushed: self.$pushed),isActive: self.$pushed) {
Image(systemName: "plus.circle").resizable().frame(width: 22, height: 22)
}.isDetailLink(false) )
}
Here you land and want to go back to root:
struct AddFoodView: View{
#Binding var pushed : Bool
// Deleted the other vars for better view
var body: some View{
ZStack{
NavigationView{ // <-- remove this
VStack{
Button (action: {
// here you'd like to go back
self.pushed = false;
} ){
Text("save").foregroundColor(Color.blue).font(.system(size: 18,design: .default)) }
}.navigationBarTitle("Three")
}
For the future:
I have the feeling you might have troubles with the navigation in general.
Actually it is really simple:
You implement one NavigationView at the "root" / start of your navigation.
From there on you only use NavigationLinks to go further down to child pages. No NavigationView needed anymore.

My view moves up when I implemented the navigation link in swiftui

Mockup of the Application
Problem:
My application successfully navigates from one view to another without any complexities.When I use the navigationLink to navigate from View 4 to View 2 (refer mockup). The view 2 movesup. I tried debugging but I found no solution.
I have designed a mockup of what I am trying to acheive.
Code Block for View 4:
import SwiftUI
import BLE
struct View4: View {
#EnvironmentObject var BLE: BLE
#State private var showUnpairAlert: Bool = false
#State private var hasConnected: Bool = false
#State private var activateLink: Bool = false
let defaults = UserDefaults.standard
let defaultDeviceinformation = "01FFFFFFFFFF"
struct Keys {
static let deviceInformation = "deviceInformation"
}
var body: some View {
VStack(alignment: .center, spacing: 0) {
NavigationLink(destination: View2(), isActive: $activateLink,label: { EmptyView() })
// 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")
DispatchQueue.main.async {
self.activateLink = true
}
}
}
Thank you !!!!