Post

Replies

Boosts

Views

Activity

Constraining Beacon with CLBeaconIdentityCondition
In reference to this webpage, I'm turning my iPad to an iBeacon device. class BeaconViewModel: NSObject, ObservableObject, CBPeripheralManagerDelegate { private var peripheralManager: CBPeripheralManager? private var beaconRegion: CLBeaconRegion? private var beaconIdentityConstraint: CLBeaconIdentityConstraint? //private var beaconCondition: CLBeaconIdentityCondition? override init() { super.init() if let uuid = UUID(uuidString: "abc") { beaconIdentityConstraint = CLBeaconIdentityConstraint(uuid: uuid, major: 123, minor: 456) beaconRegion = CLBeaconRegion(beaconIdentityConstraint: beaconIdentityConstraint!, identifier: "com.example.myDeviceRegion") peripheralManager = CBPeripheralManager(delegate: self, queue: nil, options: nil) } } func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) { switch peripheral.state { case .poweredOn: startAdvertise() case .poweredOff: peripheralManager?.stopAdvertising() default: break } } func startAdvertise() { guard let beaconRegion = beaconRegion else { return } let peripheralData = beaconRegion.peripheralData(withMeasuredPower: nil) peripheralManager?.startAdvertising(((peripheralData as NSDictionary) as! [String: Any])) } func stopAdvertise() { peripheralManager?.stopAdvertising() } } In Line 10, I'm using CLBeaconidentityConstraint to constrain the beacon. Xcode says that this class is deprecated and suggests that we use CLBeaconIdentityCondition. But if I try to use it, Xcode says Cannot find type 'CLBeaconIdentityCondition' in scope I've just updated Xcode to 16.4. I still get the same error. So how do we use CLBeaconIdentityCondition to constrain the beacon? My macOS version is Sequoia 15.5. Thanks.
2
0
176
Jun ’25
Value of type 'UIView?' has no member 'isEnabled'
I have the following lines of code in practicing Combine. import UIKit import Combine class ViewController: UIViewController { // MARK: - Variables var cancellable: AnyCancellable? @Published var segmentNumber: Int = 0 // MARK: - IBOutlet @IBOutlet weak var actionButton: UIButton! // MARK: - IBAction @IBAction func segmentChanged(_ sender: UISegmentedControl) { segmentNumber = sender.selectedSegmentIndex } // MARK: - Life cycle override func viewDidLoad() { super.viewDidLoad() cancellable = $segmentNumber.receive(on: DispatchQueue.main) .assign(to: \.isEnabled, on: actionButton) } } I get an error at .assign that says Value of type 'UIView?' has no member 'isEnabled' What am I doing wrong? Thank you.
3
0
2.5k
Aug ’21
Toggling Values on EnvironmentValue (EditMode)
I have the following lines of code for showing a list of friends. import SwiftUI struct ContentView: View { @State var users = ["Susan", "Kate", "Natalie", "Kimberly", "Taylor", "Sarah", "Nancy", "Katherine", "Nicole", "Linda", "Jane", "Mary", "Olivia", "Barbara"] @State var editMode = EditMode.inactive var body: some View { NavigationView { List { ForEach(users, id: \.self) { user in Text(user) } } .navigationBarTitle("Friends") .environment(\.editMode, $editMode) .navigationBarItems(leading: Button("Edit", action: { if self.editMode == .active { self.editMode = .inactive } else { self.editMode = .active } })) } } } If you see the code at the bottom, I have four lines just in order to change the value of editMode. Does SwiftUI have something like showDetails.toggle() where showDetails is a Boolean variable? Muchos thankos.
3
0
562
Sep ’21
Combine with UITableView
Hello, I'm trying to work out a simple example to fill table view data with Combine. The following is what I have. import Foundation struct MyModel: Decodable { let id: String let type: String } import UIKit import Combine class APIClient: NSObject { var cancellable: AnyCancellable? let sharedSession = URLSession.shared func fetchData(urlStr: String, completion: @escaping ([MyModel]?) -> Void) { guard let url = URL(string: urlStr) else { return } let publisher = sharedSession.dataTaskPublisher(for: url) cancellable = publisher.sink(receiveCompletion: { (completion) in switch completion { case .failure(let error): print(error) case .finished: print("Success") } }, receiveValue: { (result) in let decoder = JSONDecoder() do { let post = try decoder.decode([MyModel].self, from: result.data) completion(post) } catch let error as NSError { print("\(error)") completion(nil) } }) } } import Foundation class ViewModel: NSObject { @IBOutlet var apiClient: APIClient! var dataModels = [MyModel]() func getGitData(completion: @escaping () -> Void) { let urlStr = "https://api.github.com/repos/ReactiveX/RxSwift/events" apiClient.fetchData(urlStr: urlStr) { (models) in if let myModels = models { self.dataModels = myModels.map { $0 } } completion() } } } import UIKit import Combine class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { // MARK: - Variables var cancellable: AnyCancellable? @IBOutlet var viewModel: ViewModel! @Published var models = [MyModel]() // MARK: - IBOutlet @IBOutlet weak var tableView: UITableView! // MARK: - Life cycle override func viewDidLoad() { super.viewDidLoad() viewModel.getGitData { self.models = self.viewModel.dataModels } cancellable = $models.sink(receiveValue: { (result) in DispatchQueue.main.async { [weak self] in guard let strongSelf = self else { return } strongSelf.tableView.reloadData() } }) } // MARK: - TableView func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return models.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell") let dataModel = models[indexPath.row] cell?.textLabel?.text = dataModel.id cell?.detailTextLabel?.text = dataModel.type return cell! } } I'm not quite comfortable with the lines of code under my view controller (ViewController) in using Combine. How can I make them better? Muchos thankos.
3
0
3.7k
Oct ’22
Keeping Track of Text Changes over Two Text Fields
I'm still a beginner in using Combine. I practice it on and off. Anyway, I have a view model to see changes in two text fields in my view controller as follows. // ViewModel // import Foundation import Combine class LoginViewModel { var cancellable = [AnyCancellable]() init(username: String, password: String) { myUsername = username myPassword = password } @Published var myUsername: String? @Published var myPassword: String? func validateUser() { print("\(myUsername)") print("\(myPassword)") } } And my view controller goes as follows. // ViewController // import UIKit import Combine class HomeViewController: UIViewController { // MARK: - Variables var cancellable: AnyCancellable? // MARK: - IBOutlet @IBOutlet var usernameTextField: UITextField! @IBOutlet var passwordTextField: UITextField! // MARK: - Life cycle override func viewDidLoad() { super.viewDidLoad() cancellable = NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: usernameTextField) .sink(receiveValue: { result in if let textField = result.object as? UITextField { if let text = textField.text { let loginViewModel = LoginViewModel(username: text, password: "") loginViewModel.validateUser() } } }) } } So I use NSNotification as a publisher to see text changes over one of the text fields. And I cannot see text changes over two of them at the same time. Is there a better approach in seeing text changes over two text fields at the same time using Combine? Muchos thankos.
3
0
2.2k
Oct ’21
Using URLSession in Combine
I'm trying to figure out how to use URLSession with the Combine framework. I have a class that is to fetch data as follows. import UIKit import Combine class APIClient: NSObject { var cancellables = [AnyCancellable]() @Published var models = [MyModel]() func fetchData(urlStr: String) -> AnyPublisher<[MyModel], Never> { guard let url = URL(string: urlStr) else { let subject = CurrentValueSubject<[MyModel], Never>([]) return subject.eraseToAnyPublisher() } let subject = CurrentValueSubject<[MyModel], Never>(models) URLSession.shared.dataTaskPublisher(for: url) .map { $0.data } .decode(type: [MyModel].self, decoder: JSONDecoder()) .replaceError(with: []) .sink { posts in print("api client: \(posts.count)") self.models = posts } .store(in: &cancellables) return subject.eraseToAnyPublisher() } } I then have a view model class that is to deliver data for my view controller as follows. import Foundation import Combine class ViewModel: NSObject { @IBOutlet var apiClient: APIClient! var cancellables = Set<AnyCancellable>() @Published var dataModels = [MyModel]() func getGitData() -> AnyPublisher<[MyModel], Never> { let urlStr = "https://api.github.com/repos/ReactiveX/RxSwift/events" let subject = CurrentValueSubject<[MyModel], Never>(dataModels) apiClient.fetchData(urlStr: urlStr) .sink { result in print("view model: \(result.count)") self.dataModels = result }.store(in: &cancellables) return subject.eraseToAnyPublisher() } } My view controller has an IBOutlet of ViewModel. import UIKit import Combine class ViewController: UIViewController { // MARK: - Variables var cancellables = [AnyCancellable]() @IBOutlet var viewModel: ViewModel! // MARK: - IBOutlet @IBOutlet weak var tableView: UITableView! // MARK: - Life cycle override func viewDidLoad() { super.viewDidLoad() viewModel.getGitData() .sink { posts in print("view controller: \(posts.count)") } .store(in: &cancellables) } } If I run it, it seems that ViewModel returns 0 without waiting for APIClient to return data. And the view controller doesn't wait, either. What am I doing wrong? Can I do it without using the completion handler? In case you need to know what MyModel is, it's a simple struct. struct MyModel: Decodable { let id: String let type: String } Muchos thanks
3
0
1.7k
Nov ’21
Publishers.CombineLatest in SwiftUI
I've been using Combine with UIKit and Cocoa. The following is a simple example. import UIKit import Combine class ViewController: UIViewController { // MARK: - Variables private var cancellableSet: Set<AnyCancellable> = [] @Published var loginText: String = "" @Published var passwordText: String = "" // MARK: - IBOutlet @IBOutlet weak var loginField: UITextField! @IBOutlet weak var passwordField: UITextField! // MARK: - Life cycle override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: loginField) .sink { result in if let textField = result.object as? UITextField { if let text = textField.text { self.loginText = text } } } .store(in: &cancellableSet) NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: passwordField) .sink { result in if let textField = result.object as? UITextField { if let text = textField.text { self.passwordText = text } } } .store(in: &cancellableSet) Publishers.CombineLatest($loginText, $passwordText) .sink { (result0, result1) in if result0.count > 3 && result1.count > 3 { print("You are good") } else { print("No way!!!") } } .store(in: &cancellableSet) } } Now, I want to use Combine with SwiftUI. The following is SwiftUI equivalent, so far. import SwiftUI import Combine struct ContentView: View { @State var anycancellables = Set<AnyCancellable>() @State var userText: String = "" @State var passText: String = "" @State var canSave: Bool = false var body: some View { ZStack { VStack { Color.white }.onTapGesture { UIApplication.shared.endEditing() } VStack { TextField("Username", text: $userText) { }.onChange(of: userText) { newValue in } SecureField("Password", text: $passText) { }.onChange(of: passText) { newValue in } Spacer() .frame(height: 20.0) Button("Save") { print("Saved...") } .foregroundColor(canSave ? Color.black : Color.gray) .font(.system(size: 32.0)) .disabled(!canSave) }.padding(.horizontal, 20.0) } } } So where does Combine fit into the code? I want to enable the Save button if text counts of loginText and passwordText are both greater than 3, which is done at the top with UIKit. Muchos thankos.
3
0
2.2k
Jan ’22
Using Subclassed UIViewController
I'm trying to subclass UIViewController. And I've written the following. import UIKit class BaseViewController: UIViewController { let titleText: String init(titleText: String) { self.titleText = titleText super.init(nibName: nil, bundle: nil) } required init?(coder aDecoder: NSCoder) { self.titleText = "" super.init(coder: aDecoder) setup() } override func viewDidLoad() { super.viewDidLoad() } // MARK: - Setup func setup() { print("GGG: \(titleText)") let navBar = navigationController!.navigationBar navBar.barTintColor = UIColor.yellow let atext = NSMutableAttributedString(string: titleText) atext.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.black, range: NSMakeRange(0, atext.length)) atext.addAttribute(NSAttributedString.Key.strokeColor, value: UIColor.gray, range: NSMakeRange(0, atext.length)) atext.addAttribute(NSAttributedString.Key.strokeWidth, value: NSNumber.init(value: -1.0), range: NSMakeRange(0, atext.length)) let titleLabel: UILabel = UILabel(frame: CGRect(origin: CGPoint(x: 15.0, y: 0), size: CGSize(width: 320.0 - 120.0, height: 44.0))) titleLabel.attributedText = atext titleLabel.textAlignment = NSTextAlignment.center titleLabel.font = UIFont(name: "Helvetica", size: 24.0) self.navigationItem.titleView = titleLabel } } And I subclass it with a view controller named HomeViewController as follows. import UIKit class HomeViewController: BaseViewController { override init(titleText: String) { super.init(titleText: "Jim") } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override func viewDidLoad() { super.viewDidLoad() } } But the setup method in BaseViewController never gets the titleText variable ("Jim") from HomeViewController. What am I doing wrong? Thanks.
Topic: UI Frameworks SubTopic: UIKit Tags:
3
0
667
Feb ’22
Telling a View to show a Dialog from Another
I was quite active in writing code in SwiftUI several months ago. I've forgotten how to use an ObservedObject object to channel a variable between two Views. Anyway, I need to show a dialog over ContentView when I tap a button that is shown over another (RightView). The following is my code. // ContentView.swift // import SwiftUI class ObserveMonster: ObservableObject { @Published var showDialog = false } struct ContentView: View { @ObservedObject var observeManiac: ObserveMonster var body: some View { GeometryReader { geo in ZStack { HStack(spacing: 0.0) { LeftView() .frame(width: geo.size.width / 2.0, height: geo.size.height, alignment: .leading) RightView() .frame(width: geo.size.width / 2.0, height: geo.size.height, alignment: .trailing) } ShowDialogView(isShowing: observeManiac.showDialog) { } .frame(width: 500, height: 600, alignment: .center) .cornerRadius(10.0) } } } } struct ShowDialogView<Content: View>: View { let isShowing: Bool @ViewBuilder let content: () -> Content var body: some View { Group { if isShowing { Color.blue } } .animation(.default, value: isShowing) } } // RightView.swift // import SwiftUI struct RightView: View { @StateObject var observeManiac = ObserveMonster() var body: some View { ZStack { Color.red Button { observeManiac.showDialog.toggle() } label: { Text("Tap me") .font(.largeTitle) } } } } When I tap the button, the dialog (ShowDialogView) is no show. Does anybody now what I'm doing wrong? Thanks a million.
3
0
567
Mar ’22
Deleting a View Instance with the Tap of a Button
I have a simple project where I have a UUID string followed by a tap button as shown below. If one taps the Add me, the app will list a new instance of a View (KeywordRow). The following is what I have. import SwiftUI struct ContentView: View { @ObservedObject var monster: Monster var body: some View { VStack { Button { monster.items.append(Keyword()) } label: { Text("Add me!") }.padding(.vertical, 10.0) ForEach($monster.items) { item in KeywordRow(id: item.id) } } } } // MARK: - ObservableObject class Monster: ObservableObject { @Published var items = [Keyword]() } // MARK: - Keyword struct Keyword: Identifiable { var id = UUID() } struct KeywordRow: View { @Binding var id: UUID var body: some View { VStack { HStack { Text("ID: \(id)") Button { /* ------ Delete ------ */ } label: { Text("Delete") } } } } } My question is how I can let the app delete the corresponding instance when I tap the Delete button? I have an ObservedObject variable, which I haven't used. Thanks.
3
0
1.4k
Apr ’22
TextField Binding
I have an array of a model with just a single string with which I want to create instances of TextField. And I get an error for the TextField string binding. I know that is wrong. But how can fix it so that I can use textModel.name as a Binding? import SwiftUI struct ContentView: View { @State var textModels = [TextModel]() var body: some View { HStack { ForEach(textModels.indices, id: \.self) { index in let textModel = textModels[index] TextField("", text: textModel.name) // <----- Cannot convert value of type 'String' to expected argument type 'Binding<String>' } }.background(Color.green) .onAppear { textModels.append(TextModel(name: "Jim Thorton")) textModels.append(TextModel(name: "Susan Murphy")) textModels.append(TextModel(name: "Tom O'Donnell")) textModels.append(TextModel(name: "Nancy Smith")) } } } struct TextModel: Hashable { let name: String } Thanks.
3
0
1.1k
Apr ’22
AVCaptureSession startRunning crash
I have revisited AVCaptureSession in UIKit to capture a snapshot with the FaceTime camera. And my sample app will crash when AVCaptureSession starts running. Does anyone know how to fix it? The console says the following purple warning. -[AVCaptureSession startRunning] should be called from background thread. Calling it on the main thread can lead to UI unresponsiveness import UIKit import AVFoundation class CaptureViewController: UIViewController, AVCapturePhotoCaptureDelegate { var captureSession: AVCaptureSession! var cameraDevices: AVCaptureDevice! var imagePhotoOutput: AVCapturePhotoOutput! enum CameraCase { case front case back } // MARK: - IBAction @IBAction func selectTapped(_ sender: UIButton) { snapPicture() } // MARK: - Life cycle override func viewDidLoad() { super.viewDidLoad() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) prepareCamera(cameraCase: .front) } // MARK: - Camera func prepareCamera(cameraCase: CameraCase) { /* removing existing layers */ if let sublayers = self.view.layer.sublayers { for sublayer in sublayers { if sublayer.isKind(of: AVCaptureVideoPreviewLayer.self) { sublayer.removeFromSuperlayer() } } } /* creating a capture session */ captureSession = AVCaptureSession() if cameraCase == .front { guard let device = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .back).devices.first else { return } let videoInput = try? AVCaptureDeviceInput(device: device) if captureSession.canAddInput(videoInput!) { captureSession.addInput(videoInput!) imagePhotoOutput = AVCapturePhotoOutput() // setting output destination captureSession.addOutput(imagePhotoOutput) // adding photo output to session } } else { guard let device = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .front).devices.first else { return } let videoInput = try? AVCaptureDeviceInput(device: device) if captureSession.canAddInput(videoInput!) { captureSession.addInput(videoInput!) imagePhotoOutput = AVCapturePhotoOutput() // setting output destination captureSession.addOutput(imagePhotoOutput) // adding photo output to session } } /* creating a capture layer */ let captureVideoLayer: AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer.init(session: captureSession) captureVideoLayer.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height) captureVideoLayer.videoGravity = AVLayerVideoGravity.resizeAspect /* adding video capture layer to the view layer */ self.view.layer.addSublayer(captureVideoLayer) /* starting capture session */ captureSession.startRunning() //<<<<<<<<<<<<<<<<<<<<<<<<<<< The console shows a purple warning here. } }
3
0
12k
Dec ’22
Switching Locale with Picker
I'm trying to change the locale of an app with Picker as follows. import SwiftUI @main struct LocaleSwitchCrazyMamaApp: App { var body: some Scene { WindowGroup { let lanSetting = LanguageSetting() ContentView() .environmentObject(lanSetting) .environment(\.locale, lanSetting.locale) } } } class LanguageSetting: ObservableObject { @Published var locale = Locale(identifier: "en") } import SwiftUI struct ContentView: View { @State private var segmentSelection = 0 @EnvironmentObject var languageSetting: LanguageSetting var body: some View { VStack { Text(NSLocalizedString("Hello", comment: "")) .padding(.vertical, 20) Picker("Language", selection: $segmentSelection) { Text("English").tag(0) Text("Japanese").tag(1) Text("French").tag(2) } .frame(width: 200) .pickerStyle(.segmented) .onChange(of: segmentSelection) {newValue in if newValue == 0 { languageSetting.locale = Locale(identifier: "en") } else if newValue == 1 { languageSetting.locale = Locale(identifier: "ja") } else { languageSetting.locale = Locale(identifier: "fr") } } } .padding() } } In addition, I have three locale versions like the following "Hello" = "Hello"; // en.lproj "Hello" = "Bonjour"; //fr.lproj "Hello" = "こんにちは"; // ja.lproj As long as I run the app on a simulator, the language of the Hello text won't change when tap any of the segments. What am I doing wrong? Muchos thankos
3
0
1k
Oct ’23
SwiftUI #Preview with Callback Closure
I have created a simple calendar framework of my own. The screenshot below shows what it looks like. The following lines show a concise version of my calendar framework. The deal is such that the app will return a date when I tap a date button with the callBack closure. import SwiftUI struct ContentView: View { @State private var navigateToAddDate = false @State private var days: [Day] = [] @State var callBack: ((Date) -> Void) private let cols = [ GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible()) ] var body: some View { NavigationStack { VStack { LazyVGrid(columns: cols) { ForEach(days, id: \.self) { day in Button(action: { selectedDay = day navigateToAddDate.toggle() }, label: { Image(systemName: "\(day.num).circle.fill") .resizable() .aspectRatio(contentMode: .fit) .foregroundColor(day.show ? dateTextForecolor(day: day) : .clear) }) .disabled(day.isInvalid) } } } } } } struct ContentView_Previews: PreviewProvider { static var callBack: (Date) -> Void = { _ in } static var previews: some View { ContentView(callBack: callBack) } } struct Day: Hashable { let date: Date let text: String let num: Int let dayOfWeek: Int let show: Bool let isInvalid: Bool } Well, PreviewProvider works. Now, I want to use #Preview that comes with iPhone 15. #Preview { var callBack: (Date) -> Void = { _ in } ContentView(callBack: callBack) } And I get a warning and an error. The warning is the following Result of 'ContentView' initializer is unused , which seems to stem from the said warning. How can I make the Preview guy work? Thanks.
3
0
1.7k
Nov ’23
Can SwiftUI View Receive a Call When Window Will Close?
I have an NSStatusBar application. This is my first in SwiftUI. And I need to know when the window is closed so that I can disable some of menu commands. I can use NSWindowDelegate with AppDelegate as follows. import SwiftUI @main struct SomeApp: App { @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate @StateObject private var menuViewModel = MenuViewModel() var body: some Scene { WindowGroup { ContentView() .environmentObject(menuViewModel) } } } class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate { private var menuViewModel = MenuViewModel() func applicationDidFinishLaunching(_ notification: Notification) { if let window = NSApplication.shared.windows.first { window.setIsVisible(false) window.delegate = self } } func windowWillClose(_ notification: Notification) { menuViewModel.windowClosed = true } } When the window will close, MenuViewModel (ObservableObject) will receive a call, which I want my ContentView to receive. But, so far, it won't. import SwiftUI struct ContentView: View { var body: some View { ZStack { ... ... } .onReceive(statusBarViewModel.$windowClosed) { result in // never called... } } } Can a SwiftUI View receive a call somehow when its window closes? Muchos thankos.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
3
1
557
Jun ’25