Post

Replies

Boosts

Views

Activity

Can You Debug a Widget on Actual Device?
I'm working on an iOS app with a Widget. I am able to display the Widget on the iPhone 16 Pro Simulator. It doesn't appear on iPad mini 6th gen., though. Anyway, I want to make sure that it works on an actual device. If I try to add the Widget to the Home Screen, I cannot find it in the search list on iPhone XR and iPad 9th gen. If I set the target to that of the widget, Xcode gives me the following error. SendProcessControlEvent:toPid: encountered an error: Error Domain=com.apple.dt.deviceprocesscontrolservice Code=8 "Failed to show Widget 'some bundle ID' error: … I hope that's not a sign of trouble. So how do you debug a Widget on an Actual Device? I've read some topics like this one here. Thanks.
2
0
102
May ’25
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
202
Jun ’25
Projecting a Cube with a Number in ARKit
I'm a novice in RealityKit and ARKit. I'm using ARKit in SwiftUI to show a cube with a number as shown below. import SwiftUI import RealityKit import ARKit struct ContentView : View { var body: some View { return ARViewContainer() } } #Preview { ContentView() } struct ARViewContainer: UIViewRepresentable { typealias UIViewType = ARView func makeUIView(context: UIViewRepresentableContext<ARViewContainer>) -> ARView { let arView = ARView(frame: .zero, cameraMode: .ar, automaticallyConfigureSession: true) arView.enableTapGesture() return arView } func updateUIView(_ uiView: ARView, context: UIViewRepresentableContext<ARViewContainer>) { } } extension ARView { func enableTapGesture() { let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap(recognizer:))) self.addGestureRecognizer(tapGestureRecognizer) } @objc func handleTap(recognizer: UITapGestureRecognizer) { let tapLocation = recognizer.location(in: self) // print("Tap location: \(tapLocation)") guard let rayResult = self.ray(through: tapLocation) else { return } let results = self.raycast(from: tapLocation, allowing: .estimatedPlane, alignment: .any) if let firstResult = results.first { let position = simd_make_float3(firstResult.worldTransform.columns.3) placeObject(at: position) } } func placeObject(at position: SIMD3<Float>) { let mesh = MeshResource.generateBox(size: 0.3) let material = SimpleMaterial(color: UIColor.systemRed, roughness: 0.3, isMetallic: true) let modelEntity = ModelEntity(mesh: mesh, materials: [material]) var unlitMaterial = UnlitMaterial() if let textureResource = generateTextResource(text: "1", textColor: UIColor.white) { unlitMaterial.color = .init(tint: .white, texture: .init(textureResource)) modelEntity.model?.materials = [unlitMaterial] let id = UUID().uuidString modelEntity.name = id modelEntity.transform.scale = [0.3, 0.1, 0.3] modelEntity.generateCollisionShapes(recursive: true) let anchorEntity = AnchorEntity(world: position) anchorEntity.addChild(modelEntity) self.scene.addAnchor(anchorEntity) } } func generateTextResource(text: String, textColor: UIColor) -> TextureResource? { if let image = text.image(withAttributes: [NSAttributedString.Key.foregroundColor: textColor], size: CGSize(width: 18, height: 18)), let cgImage = image.cgImage { let textureResource = try? TextureResource(image: cgImage, options: TextureResource.CreateOptions.init(semantic: nil)) return textureResource } return nil } } I tap the floor and get a cube with '1' as shown below. The background color of the cube is black, I guess. Where does this color come from and how can I change it into, say, red? Thanks.
4
0
164
Jul ’25
Dealing with IAP Purchase Restore
Do you let your users restore their IAP purchases with or without history of purchases? I don't. And it had not been a problem in the past 10 years or so till two days ago when the reviewer rejected my new iOS software submission. He or she said that it was a bug since the Restore button is disabled. I saw the screenshot he or she gave me in which it was obvious that the reviewer had not made a purchase. For me, I cannot think of a reason why one with no history of purchases should be allowed to proceed and restore purchases. I don't even know what the reviewer is trying to restore. So far, the reviewer doesn't buy my explanation or seems to ignore me. What do you think? Do you let them go lucky by accident? By the way, this is a non-consumable IAP product.
4
0
97
Aug ’25
Changing a Status With @EnvironmentObject in Another View
I'm playing with @EnvironmentObject to see how it works in SwiftUI. I have the main view (ContentView) where it says the user has not logged in yet. By letting the user tap a link, I want to make it such that they can log in by tapping a button. class LoginMe: ObservableObject { @Published var loggedIn = false } struct ContentView: View { @StateObject var loginMe = LoginMe() var body: some View { if loginMe.loggedIn { Text("Yes, I'm logged in") } else { NavigationView { VStack { Text("No, not logged in yet") .padding(.vertical) NavigationLink(destination: LoginView()) { Text("Tap to log in") } } .navigationBarTitle("User") } .environmentObject(loginMe) } } } struct LoginView: View { @EnvironmentObject var loginMe: LoginMe var body: some View { /* Toggle(isOn: $loginMe.loggedIn) { Text("Log in") }.padding(.horizontal) */ Button("Login") { loginMe.loggedIn.toggle() } } } So far, when the user taps a button in the LoginView view, the screen goes back to ContentView and the navigation simply disappears. How can I change my code so that the status will change back and forth in in the LoginView view by tapping a button and then so that they can return to ContentView the navigation return button? I think the problem is that I need to use @State var in ContentView and @Binding var in LoginView. Things are kind of confusing. Muchos thankos.
1
0
555
Sep ’21
Updating @State Variable Depending ForEach Row Selection
import SwiftUI struct ContentView: View { @State var numbers = [2021, 9, 30] var body: some View { //let firstLocalYear = 2021 let firstLocalMonth = 9 let firstLocalDay = 24 let firstLastDay = 30 NavigationView { List { Section(header: Text("Current month")) { ForEach(firstLocalDay ..< firstLastDay) { i in HStack { Text("\(firstLocalMonth)-\(i + 1)") Spacer() NavigationLink( destination: TimeView(numbers: $numbers), label: { Text("") }) } } } } } } } struct TimeView: View { @Binding var numbers: [Int] var body: some View { HStack { Text(String(numbers[0])) Text(String(numbers[1])) Text(String(numbers[2])) } } } I have the lines of code above to list some rows of text. For now, numbers is a state variable that is pre-determined. This state variable is passed on to TimeView. Actually, I want to change this array depending on which row the user selects like numbers = [firstLocalYear, firstLocalMonth, i] where i comes from the ForEach thing. How can I change this array? Muchos thankos.
1
0
441
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
Animating Shape
I'm trying to animate a shape. The following is my code. import SwiftUI struct ContentView7: View { @State private var goingLeft = true @State private var goingUp = true var body: some View { ZStack { Color.green.ignoresSafeArea() CustomShape(quadDistance: goingUp ? 0: 60.0, horizontalDeviation: 0.0) .fill(Color.red) .ignoresSafeArea() .animation(.easeInOut(duration: 1.0).repeatForever(), value: goingUp) }.onAppear { goingUp = false } } } struct CustomShape: Shape { var quadDistance: CGFloat var horizontalDeviation: CGFloat func path(in rect: CGRect) -> Path { Path { path in path.move(to: CGPoint(x: -horizontalDeviation, y: 0)) path.addLine(to: CGPoint(x: rect.maxX + horizontalDeviation , y: 0)) path.addLine(to: CGPoint(x: rect.maxX + horizontalDeviation, y: rect.midY)) path.addLine(to: CGPoint(x: -horizontalDeviation, y: rect.midY)) path.move(to: CGPoint(x: -horizontalDeviation, y: rect.midY)) path.addQuadCurve(to: CGPoint(x: rect.maxX + horizontalDeviation, y: rect.midY), control: CGPoint(x: rect.midX, y: rect.midY + quadDistance)) } } } Well, my intension is to move the center of the convex point up and down. But the shape won't animate itself. What am I doing wrong? Muchos thankos.
0
0
315
Feb ’22
Showing a Constructor Dialog View with an ObservedObject Object
I'm trying to show a dialog over ContentView. The dialog view, ShowDialogView, has an ObservedObject object with name and properties. class User: ObservableObject { @Published var name = "" @Published var age: Int = 0 } struct ShowDialogView: View { @Binding var isPresented: Bool @ObservedObject var user: User /* @State var name = "" */ init(isPresented: Binding<Bool>, user: User) { self._isPresented = isPresented self.user = user.searchWord //_name = State(initialValue: "Kimberly") } var body: some View { VStack { ... ... }.onAppear { print("\(user.name)") } } } struct ContentView: View { @State var user = User() @State var showMe = true var body: some View { VStack { ... ... ShowDialogView(isPresented: showMe, user: user) } } } The dialog view will open with no problem. The problem that I have is that the user object doesn't deliver anything beyond default values. If I somehow set the name property to "Kimberly" before the dialog appears, the app will end up showing no value (""). Even if I try setting an initial value to the name property in the constructor, the app will still show an empty value. What am I doing wrong? I'm sorry I cannot give you a lot of details in the code above. Thank you.
1
0
437
Apr ’22
Horizontally-Aligned TextField Wrap?
I have a @State variable with an array of strings with which to create instances of TextField. So far, I have the following lines of code. import SwiftUI struct ContentView: View { @State private var names: [String] = ["Jim Thorton", "Susan Murphy", "Tom O'Donnell", "Nancy Smith"] var body: some View { HStack { ForEach($names, id: \.self) { $name in TextField("", text: $name) .fixedSize() .padding(.horizontal, 20.0) .background(Color.orange.opacity(0.2)) } } } } I wonder if there is a simple way of aligning instances of TextField horizontally such that one that exceeds the screen width will go to the next line like the following picture? Thanks.
2
0
1.7k
Apr ’22
Files Selected with UIDocumentPickerViewController Ending Up in File Provider Storage [SwiftUI]
I often use security-scoped bookmarks when I develop a desktop application in Cocoa. This time, I need to use them in an iOS app, using SwiftUI framework. I don't quite remember the history, but I use UIDocumentPickerViewController through UIViewControllerRepresentable to let the user select a file. And I have a model where I save file name, file path, its bookmark (Data) with NSKeyedArchiver.. And everything goes well when I run the app in a simulator. Yet, FileManager says each file in the model does not exist. One of the path is something like the following. /private/var/mobile/Containers/Shared/AppGroup/749F05F0-12BC-40AC-B5C4-72571145C624/File Provider Storage/Test/somefile.txt Since it doesn't exist, I cannot even resolve it. How can I resolve the bookmark if a file ends up at the File Provider Storage folder? Do I need a special capability that I don't know about or something? Thanks.
1
0
647
Jul ’22
Deleting a Row in the List with Data from Realm
I have created a very simple sample project just to make my point using RealmSwift.. // ContentView.swift // import SwiftUI import RealmSwift struct ContentView: View { @StateObject var viewModel = ViewModel() var body: some View { NavigationView { VStack { Spacer() NavigationLink("Listing all meals") { ListView() .environmentObject(viewModel) } Spacer() } } } } // ListView.swift // import SwiftUI import RealmSwift struct ListView: View { @EnvironmentObject var viewModel: ViewModel @State var meals = [MealDB]() var body: some View { List { ForEach(meals) { meal in HStack { Text("\(meal.title)") .padding(.leading, 6.0) Spacer() Button { viewModel.model.delete(id: meal.id) } label: { Text("Delete") } .padding(.trailing, 6.0) .buttonStyle(.borderless) } .onDrag { return NSItemProvider() } } .onMove(perform: move(from:to:)) } .onAppear { updateData() } } func updateData() { meals.removeAll() // data from Realm database for mealItem in viewModel.mealItems {// <<<<<<<<<< meals.append(mealItem) } meals.sort { (($0).place < (($1).place)) } } } // ViewModel.swift // import Foundation import RealmSwift class ViewModel: ObservableObject { @Published var model = MealStore() var mealItems: Results<MealDB> { model.items } } final class MealStore: ObservableObject { var config: Realm.Configuration init() { config = Realm.Configuration() } var realm: Realm { return try! Realm(configuration: config) } var items: Results<MealDB> { realm.objects(MealDB.self) } } // MealDB.swift // import Foundation import RealmSwift class MealDB: Object, Identifiable { @objc dynamic var id = "" @objc dynamic var title = "" @objc dynamic var order = 0 @objc dynamic var place = 0 override class func primaryKey() -> String? { "id" } } ListView has a list of meals. Each row comes with a button that lets me delete the corresponding row. And the app will crash inside the updateData function. I have found out that the issue is the way how SwiftUI works and hangs on to the old set of data even after I tap the delete button. So a solution is to 'freeze up' the dataset. And the app won't crash when I tap the delete button. for mealItem in viewModel.mealItems.freeze() { ... } Now, my question is... Are there reasons for not freezing up the dataset? If there is no downside, how come MongoDB just doesn't tell us to do it when we use access a dataset in Realm? Thanks.
1
0
800
Sep ’22
Reading a PSSliderSpecifier value in Settings Bundle
I didn't know that Settings Bundle exists till two days ago. Anyway, I've tested it with a simple example. As shown in the screenshot below, I have one group, one text field, one slider and two toggle buttons. I am able to read the values from all of them except the slider. I wonder if it's a bug? I'm using Xcode 14.2. In the following code, the app won't go inside the if clause for the PSSliderSpecifier key. import UIKit class ViewController: UIViewController { // MARK: - Life cyle override func viewDidLoad() { super.viewDidLoad() let defaultValues = [String: AnyObject]() UserDefaults.standard.register(defaults: defaultValues) } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) /* settings */ fetchSettingBundleData() } @objc func fetchSettingBundleData() { let userDefaults = UserDefaults.standard if let settingsURL = Bundle.main.url(forResource: "Root", withExtension: "plist", subdirectory: "Settings.bundle"), let settings = NSDictionary(contentsOf: settingsURL), let preferences = settings["PreferenceSpecifiers"] as? [NSDictionary] { var defaultsToRegister = [String: Any]() for preferenceSpecification in preferences { if let key = preferenceSpecification["Type"] as? String, let value = preferenceSpecification["Title"] { defaultsToRegister[key] = value } } userDefaults.register(defaults: defaultsToRegister) } if let groupName = userDefaults.string(forKey: "PSGroupSpecifier") { print("Group name: \(groupName)") } if let _ = userDefaults.string(forKey: "PSTextFieldSpecifier") { if let text = userDefaults.string(forKey: "name_preference") { print("Textfield \(text)") } } if let _ = userDefaults.string(forKey: "PSToggleSwitchSpecifier") { if let value = userDefaults.string(forKey: "enabled_preference1") { print("Toggle \(value)") // 0 or 1 } } if let _ = userDefaults.string(forKey: "PSToggleSwitchSpecifier") { if let value = userDefaults.string(forKey: "enabled_preference2") { print("Toggle2 \(value)") // 0 or 1 } } if let _ = userDefaults.string(forKey: "PSSliderSpecifier") { print("heck....") // No show if let value = userDefaults.string(forKey: "slider_preference") { print("Slider \(value)") } } } }
1
0
838
Jan ’23
Ending TextList Madness
I am just playing with NSTextList by creating a sample iOS app. The following is my code. import UIKit class ViewController: UIViewController { lazy var textView: UITextView = { let textView = UITextView() textView.text = "" textView.contentInsetAdjustmentBehavior = .automatic textView.backgroundColor = .white textView.font = UIFont.systemFont(ofSize: 20.0) textView.textColor = .black textView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ textView.widthAnchor.constraint(equalToConstant: 600.0), textView.heightAnchor.constraint(equalToConstant: 600.0) ]) return textView }() lazy var button: UIButton = { let button = UIButton() button.setTitle("End list", for: .normal) button.setTitleColor(.white, for: .normal) button.setTitleColor(.lightGray, for: .highlighted) button.backgroundColor = .black button.layer.cornerRadius = 8.0 button.addTarget(self, action: #selector(fixTapped), for: .touchUpInside) button.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ button.widthAnchor.constraint(equalToConstant: 100.0), button.heightAnchor.constraint(equalToConstant: 42.0) ]) return button }() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemBlue view.addSubview(textView) view.addSubview(button) let tapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)) view.addGestureRecognizer(tapGesture) NSLayoutConstraint.activate([ textView.centerXAnchor.constraint(equalTo: view.centerXAnchor), textView.centerYAnchor.constraint(equalTo: view.centerYAnchor) ]) NSLayoutConstraint.activate([ button.centerXAnchor.constraint(equalTo: view.centerXAnchor), button.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20.0) ]) let list = NSTextList(markerFormat: .diamond, options: 0) list.startingItemNumber = 1 let paragraphStyle = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle paragraphStyle.textLists = [list] let attributes = [NSAttributedString.Key.paragraphStyle: paragraphStyle, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 24.0)] let attributedStr = NSMutableAttributedString(string: "\n\n\n\n\n", attributes: attributes) textView.textStorage.setAttributedString(attributedStr) } @objc func fixTapped() { } @objc func dismissKeyboard() { view.endEditing(true) } } When the app launches itself, I get 5 lines of diamond guys as shown in the following screenshot. If I keep pressing the delete key with a connected keyboard, the list will be gone as shown below. But if I press the RETURN key several times, the diamond list will come back as shown below. So how can I end this June TextList madness? In code, I have the dismissKeyboard function if I can end this madness programmatically. Thanks, Señor Tomato Spaghetti Chief Janitor at Southeastern Tomato Spaghetti Trade Association
0
0
687
Jun ’23
Saving Color from UIColorPickerViewController with UserDefaults
I've been trying to save a selected color with UserDefaults from UIColorPickerViewController. But I run into a color space fiasco. Anyway, here come my lines of code. class ViewController: UIViewController, UIColorPickerViewControllerDelegate { @IBOutlet weak var imageView: UIImageView! @IBAction func selectTapped(_ sender: UIButton) { let picker = UIColorPickerViewController() picker.delegate = self picker.selectedColor = .yellow picker.supportsAlpha = false present(picker, animated: true, completion: nil) } override func viewDidLoad() { super.viewDidLoad() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) if let color = UserDefaultsUIColor.shared.readColor(key: "MyColor") { print("Color being read: \(color)") } } func colorPickerViewControllerDidFinish(_ viewController: UIColorPickerViewController) { let color = viewController.selectedColor print("Selected color: \(color)") UserDefaultsUIColor.shared.saveColor(color: viewController.selectedColor, key: "MyColor") } func colorPickerViewControllerDidSelectColor(_ viewController: UIColorPickerViewController) { imageView.backgroundColor = viewController.selectedColor } } class UserDefaultsUIColor { static let shared = UserDefaultsUIColor() func saveColor(color: UIColor, key: String) { let userDefaults = UserDefaults.standard do { let data = try NSKeyedArchiver.archivedData(withRootObject: color, requiringSecureCoding: false) as NSData? userDefaults.set(data, forKey: key) } catch { print("Error UserDefaults: \(error.localizedDescription)") } } func readColor(key: String) -> UIColor? { let userDefaults = UserDefaults.standard if let data = userDefaults.data(forKey: key) { do { if let color = try NSKeyedUnarchiver.unarchivedObject(ofClass: UIColor.self, from: data) { return color } } catch { print("Error UserDefaults") } } return nil } } I first start out with a yellow color (UIColor.yellow). And I select a color whose RGB values are 76, 212, 158, respectively. And the color picker guy returns the following. kCGColorSpaceModelRGB 0.298039 0.831373 0.619608 1 And I get the following in reading the saved color data object. UIExtendedSRGBColorSpace -0.270778 0.84506 0.603229 1 How can I save and read color data objects consistently? I could specify a color space when I save a color. But it doesn't go well. Muchos thankos Señor Tomato de Source
0
0
946
Jun ’23