Post not yet marked as solved
I've been going through SwiftData documentation, as I'm trying to learn how to work with SwiftData, especially how to use it to cache web responses. "Maintaining a local copy of server data" sample seems to be perfect source for me then, but I find it a little bit confusing, or lacking. There's this function:
/// Loads new earthquakes and deletes outdated ones.
@MainActor
static func refresh(modelContext: ModelContext) async {
do {
// Fetch the latest set of quakes from the server.
logger.debug("Refreshing the data store...")
let featureCollection = try await fetchFeatures()
logger.debug("Loaded feature collection:\n\(featureCollection)")
// Add the content to the data store.
for feature in featureCollection.features {
let quake = Quake(from: feature)
// Ignore anything with a magnitude of zero or less.
if quake.magnitude > 0 {
logger.debug("Inserting \(quake)")
modelContext.insert(quake)
}
}
logger.debug("Refresh complete.")
} catch let error {
logger.error("\(error.localizedDescription)")
}
}
It says specifically that it "deletes outdated ones", but where does the actual deletion happens? All I can see is call to modelContext.insert(quake) which will update existing entries or create new ones if they don't exist yet, if I'm understanding things right. But quakes that were already in the database, and are not present in the response, don't seem to be deleted anywhere in this function. Or am I missing something?
I want to automatically load different views depending on OS (OSX or iOS). Is there a way that I can do this without the user having to click on a link? This is my code so far.
struct ContentView: View {
#if os(iOS)
var myOS = "iOS"
#elseif os(OSX)
var myOS = "OSX"
#else
var myOS = "Something Else"
#endif
var body: some View {
NavigationStack {
VStack {
Text("PLEASE WAIT....")
.font(.system(size: 24))
.fontWeight(.bold)
}
.padding()
if (myOS == "OSX"){
// Goto Screen for iMac
}
else{
// go to screen for iOS
}
}
}
}
If I use "NavigationLink", my understanding is that the user would need to click on a link. Is there some way to do this without user interaction?
Post not yet marked as solved
I am trying to develop an app that runs on iMacs, iPhones and iPads. so how, using SwiftUI, do I check what device I am running on?
Post not yet marked as solved
I am trying to load and view several locations onto a map from a JSOPN file in my SwiftUI project, but I continually encounter the error "no exact matches in call to initializer" in my ContentView.swift file.
What I Am Trying to Do:
I am working on a SwiftUI project where I need to display several locations on a map. These locations are stored in a JSON file, which I have successfully loaded into Swift. My goal is to display these locations as annotations on a Map view.
JSON File Contents:
coordinates: latitude and longitude
name: name of the location
uuid: unique identifier for each location
Code and Screenshots:
Here are the relevant parts of my code and the error I keep encountering:
import SwiftUI
import MapKit
struct ContentView: View {
@State private var mapPosition = MapCameraPosition.region(
MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194),
span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
)
)
@State private var features: [Feature] = []
var body: some View {
NavigationView {
Map(position: $mapPosition, interactionModes: .all, showsUserLocation: true) {
ForEach(features) { feature in
Marker(coordinate: feature.coordinate) {
FeatureAnnotation(feature: feature)
}
}
}
.onAppear {
POILoader.loadPOIs { result in
switch result {
case .success(let features):
self.features = features
case .failure(let error):
print("Error loading POIs: \(error.localizedDescription)")
}
}
}
.navigationBarTitle("POI Map", displayMode: .inline)
}
}
}
struct FeatureAnnotation: View {
let feature: Feature
var body: some View {
VStack {
Circle()
.strokeBorder(Color.red, lineWidth: 2)
.background(Circle().foregroundColor(.red))
.frame(width: 20, height: 20)
Text(feature.name)
}
}
}
I have not had any luck searching for solutions to my problems using the error messages that keep arising. Does anyone have any advice for how to move forward?
Environment: Mac OS Sonoma v14.4.1 Xcode 15.3
I'm new to iOS Swift development environment and trying to create a simple app to just return the current location address. I'm testing it with simulator iPhone 15 but the app is not returning any result. Please advise. Here is my code.
import SwiftUI
import CoreLocation
struct CurrentLocationView: View {
@StateObject private var locationManager = LocationManager()
var body: some View {
VStack {
Text("Your Address:")
.font(.title2)
Text(locationManager.address ?? "Locating...")
.multilineTextAlignment(.center)
.padding()
}
.onAppear {
locationManager.requestAuthorization()
}
}
}
class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {
private let locationManager = CLLocationManager()
@Published var address: String?
override init() {
super.init()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
}
func requestAuthorization() {
switch locationManager.authorizationStatus {
case .notDetermined:
locationManager.requestWhenInUseAuthorization()
case .authorizedWhenInUse, .authorizedAlways:
locationManager.startUpdatingLocation()
case .denied, .restricted:
// Handle denied or restricted authorization
print("Location services denied")
default:
break
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.first else { return }
let geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(location) { [weak self] placemarks, error in
guard let self = self, let placemark = placemarks?.first else { return }
// Extract address components
if let thoroughfare = placemark.thoroughfare, let locality = placemark.locality {
let address = "\(thoroughfare), \(locality)"
self.address = address
} else {
self.address = "Unable to determine address"
}
}
}
}
#Preview {
CurrentLocationView()
}
Post not yet marked as solved
#Preview, @available(iOS 17, *), PreviewProvider
Preview is not working.
I've tried this and that, but I can't.
Please help me.
Post not yet marked as solved
Hi, I am developing a drawing app using SafariView and is using apple pencil double tap handler for crucial features.
In IOS 17.5 I lost functionality of it when interacting with SafariView, my friend confirmed that it worked with IOS 17.4 and I can confirm it also worked with IOS 17.1. However, I cannot downgrade my system nor can my uses. THIS IS A FATAL MALFUNCTION FOR MY APP.
Detailedly, as I tested, the double tap handlers cannot be activated when my last tapped component is SafariView, so it never works when interacting with my web app. But I can enable this by clicking outside the SafariView or some non-SafariView component on top of it, just anything other than the Safari view, even webkit view can work but it is not usable for me. My aim is to keep listening to double tapping while interacting with SafariView in full screen, so I cannot let the user tap elsewhere to just activate double tap, there is no other walk around for me, unless there is a way to enable 120fps animation in WebKit view, which is only available in safari feature flags as I know.
I would like to hear a solution in this situation or a promise of a fix, this is devastating to my users' experience.
code to reproduce:
import SwiftUI
import WebKit
import SafariServices
struct SafariView: UIViewControllerRepresentable {
let url: URL
func makeUIViewController(context: Context) -> SFSafariViewController {
return SFSafariViewController(url: url)
}
func updateUIViewController(_ uiViewController: SFSafariViewController, context: Context) {
// No update code needed for this example
}
}
struct WKWebViewWrapper: UIViewRepresentable {
let url: URL
func makeUIView(context: Context) -> WKWebView {
let webView = WKWebView()
let request = URLRequest(url: url)
webView.load(request)
return webView
}
func updateUIView(_ uiView: WKWebView, context: Context) {
// No update code needed for this example
}
}
struct ContentView: View {
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
.onPencilDoubleTap { value in
print("tap1")
}
Text("Hello, world!")
.padding()
SafariView(url: URL(string: "https://www.example.com")!)
.onPencilDoubleTap { value in print("tap2")}
.frame(width:300)
WKWebViewWrapper(url: URL(string: "https://www.example.com")!).onPencilDoubleTap { value in
print("tap3")
}
.frame(width:300)
}
}
}
#Preview {
ContentView()
}
I already filed feedback FB13777941 for this, but wanted to ask if anyone has the same problem, since I can't find anything on google or SO.
I created a new package in Xcode (15.3) and added this to it:
import SwiftUI
struct Test: View {
var body: some View {
Text("Hello world")
}
}
#Preview {
Test()
}
The package builds, tests can run. Previews don't work.
This is more or less the error I get from the diagnostics button (formatted for readability):
LoadingError: failed to load library at path ”PATH_TO_DERIVED_DATA/Build/Intermediates.noindex/Previews/macos/PACKAGE_NAME/Products/Debug/PackageFrameworks/PACKAGE_NAME_63097C4A372B9C87_PackageProduct.framework/PACKAGE_NAME_63097C4A372B9C87_PackageProduct”: Optional(dlopen(PATH_TO_DERIVED_DATA/Build/Intermediates.noindex/Previews/macos/PACKAGE_NAME/Products/Debug/PackageFrameworks/PACKAGE_NAME_63097C4A372B9C87_PackageProduct.framework/PACKAGE_NAME_63097C4A372B9C87_PackageProduct, 0x0000):
tried:
'PATH_TO_DERIVED_DATA/Build/Intermediates.noindex/Previews/macos/PACKAGE_NAME/Products/Debug/PACKAGE_NAME_63097C4A372B9C87_PackageProduct.framework/PACKAGE_NAME_63097C4A372B9C87_PackageProduct' (no such file),
'PATH_TO_DERIVED_DATA/Build/Intermediates.noindex/Previews/macos/PACKAGE_NAME/Products/Debug/PackageFrameworks/PACKAGE_NAME_63097C4A372B9C87_PackageProduct.framework/PACKAGE_NAME_63097C4A372B9C87_PackageProduct' (mach-o file, but is an incompatible architecture (have 'arm64', need 'arm64e')),
'/System/Volumes/Preboot/Cryptexes/OSPATH_TO_DERIVED_DATA/Build/Intermediates.noindex/Previews/macos/PACKAGE_NAME/Products/Debug/PackageFrameworks/PACKAGE_NAME_63097C4A372B9C87_PackageProduct.framework/PACKAGE_NAME_63097C4A372B9C87_PackageProduct' (no such file),
'PATH_TO_DERIVED_DATA/Build/Intermediates.noindex/Previews/macos/PACKAGE_NAME/Products/Debug/PackageFrameworks/PACKAGE_NAME_63097C4A372B9C87_PackageProduct.framework/PACKAGE_NAME_63097C4A372B9C87_PackageProduct' (mach-o file, but is an incompatible architecture (have 'arm64', need 'arm64e')),
'PATH_TO_DERIVED_DATA/Build/Intermediates.noindex/Previews/macos/PACKAGE_NAME/Products/Debug/PACKAGE_NAME_63097C4A372B9C87_PackageProduct.framework/Versions/A/PACKAGE_NAME_63097C4A372B9C87_PackageProduct' (no such file),
'PATH_TO_DERIVED_DATA/Build/Intermediates.noindex/Previews/macos/PACKAGE_NAME/Products/Debug/PackageFrameworks/PACKAGE_NAME_63097C4A372B9C87_PackageProduct.framework/Versions/A/PACKAGE_NAME_63097C4A372B9C87_PackageProduct' (mach-o file, but is an incompatible architecture (have 'arm64', need 'arm64e')),
'/System/Volumes/Preboot/Cryptexes/OSPATH_TO_DERIVED_DATA/Build/Intermediates.noindex/Previews/macos/PACKAGE_NAME/Products/Debug/PackageFrameworks/PACKAGE_NAME_63097C4A372B9C87_PackageProduct.framework/Versions/A/PACKAGE_NAME_63097C4A372B9C87_PackageProduct' (no such file),
'PATH_TO_DERIVED_DATA/Build/Intermediates.noindex/Previews/macos/PACKAGE_NAME/Products/Debug/PackageFrameworks/PACKAGE_NAME_63097C4A372B9C87_PackageProduct.framework/Versions/A/PACKAGE_NAME_63097C4A372B9C87_PackageProduct' (mach-o file, but is an incompatible architecture (have 'arm64', need 'arm64e')))
I don't remember ever having this problem. The arm64 vs arm64e makes no sense to me - why would Xcode get that wrong... and only for previews?
I've tried restarting, deleting derived data, the usual rain dances.
Any ideas?
Post not yet marked as solved
Hello everyone. I am developing an application with SwiftUI. I am having trouble with NavigationStack(path: ).
1st problem:
After the application runs, after clicking on the first list item, there is a flicker in the title section. I think it is the .navigationDestination that causes this problem, because when I change the navigationLink to Button in the “ActiveRegQueryView” screen, this problem disappears.
2nd Problem:
When you click on a list item, sometimes it stays pressed (grayed out) and does not take you to the screen (Video 1). If you try to click on an item more than once, navigatinLink passes more than one value to path and opens more than one page (I noticed this with path.count) (Video 2).
I don't have this problem if you edit the back button on the screen it takes you to (ActiveRegDetailView). (vm.path.removeLast())
The reason I use path is to close multiple screens and return to the start screen.
Video 1:
Video 2:
Main View:
import SwiftUI
struct ActiveRegView: View {
@Environment(NavigationViewModel.self) private var navViewModel
@AppStorage("sortOption") private var sortOrder: sorting = .byBrand
@State private var searchText = ""
var body: some View {
@Bindable var navViewModel = navViewModel
NavigationStack(path: $navViewModel.path) { // <- if i don't use path everything is OK
List {
ActiveRegQueryView(searchText: searchText, sortOrder: sortOrder) // <- Dynamic Query View
}
.navigationDestination(for: Registration.self, destination: {
ActiveRegDetailView(reg: $0)
.toolbar(.hidden, for: .tabBar)
})
}
}
}
Dynamic Query View:
import SwiftData
import SwiftUI
struct ActiveRegQueryView: View {
@Query private var regs: [Registration]
@Environment(NavigationViewModel.self) var vm
init(searchText: String, sortOrder: sorting) {
var order: SortDescriptor<Registration>
switch sortOrder {
case .byBrand:
order = SortDescriptor(\.brand)
case .byDateDescending:
order = SortDescriptor(\.entryRegistration.entryDate, order: .reverse)
case .byDateAscending:
order = SortDescriptor(\.entryRegistration.entryDate)
}
_regs = Query(filter: #Predicate {
if !searchText.isEmpty {
if $0.activeRegistration && ($0.brand.localizedStandardContains(searchText) || $0.model.localizedStandardContains(searchText) || $0.plate.localizedStandardContains(searchText)) {
return true
} else {
return false
}
} else {
return $0.activeRegistration
}
}, sort: [order])
}
var body: some View {
ForEach(regs) { reg in
NavigationLink(value: reg) {
ListRowView(reg: reg)
}
// Button {
// vm.path.append(reg)
// } label: {
// ListRowView(reg: reg)
// }
// .buttonStyle(.plain)
}
}
}
I look forward to your ideas for solutions. Thank you for your time.
Post not yet marked as solved
Hello,
I have a view have three textfields and a button.
I wrote following code to move between textfields using return key.
func textFieldShouldReturn(_ textField: UITextField) -> Bool
{
if textField == self.A {
self.B.becomeFirstResponder()
}else if textField == self.B {
self.C.becomeFirstResponder()
}
return true
}
when I use return key between A->B, above code works properly. but when i use return key between B->C, above code doesn't work. I couldn't figure out what's wrong with this.
if anyone pick me my mistake and suggest solution for it, I'd very appreciate.
Thanks,
c00012
Post not yet marked as solved
No matter what I have tried, I can't get my test "What would you like to do?" to appear at the top of the screen. What have I missed? Is something g to do with the ZStack?
import SwiftUI
import SwiftData
struct ContentView: View {
@Environment(\.modelContext) private var context
@Query private var readings: [Readings]
@State private var readingTimeStamp: Date = Date()
var body: some View {
ZStack {
Image("IPhone baqckgound 3")
.resizable()
.aspectRatio(contentMode: .fill)
.padding(.top, 40)
VStack {
Text("What would you like to do?")
.font(.title)
.fontWeight(.bold)
}
.padding()
Spacer()
}
}
}
Map(initialPosition: .camera(mapCamera)) {
Marker("Here", coordinate: location)
}
.frame(height: 300)
.clipShape(RoundedRectangle(cornerSize: CGSize(width: 10, height: 10)))
.onMapCameraChange(frequency: .continuous) { cameraContext in
locationManager.location = cameraContext.camera.centerCoordinate
}
.onReceive(locationManager.$location, perform: { location in
if let location {
mapCamera.centerCoordinate = location
}
})
class LocationDataManager: NSObject, CLLocationManagerDelegate, ObservableObject {
enum LoadingState {
case loading
case notLoading
case finished
}
static let shared = LocationDataManager()
private let locationManager = CLLocationManager()
@Published var location: CLLocationCoordinate2D? = nil
@Published var loading: LoadingState = .notLoading
override init() {
super.init()
locationManager.delegate = self
}
func resetLocation() {
loading = .notLoading
location = nil
}
func getLocation() {
locationManager.requestLocation()
loading = .loading
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
location = locations.first?.coordinate
if location != nil {
loading = .finished
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: any Error) {
print("Failed to retrieve location: \(error.localizedDescription)")
loading = .notLoading
}
}
So the when the LocationButton is selected, the location is found and the marker is set correctly. You can also move the camera around to adjust the marker position, which works correctly. However, if you press the LocationButton again, it updates the marker position but it won't move the MapCamera to the new location. I can see the marker move. mapCamera.centerCoordinate = location should be doing it, but it's not. Anyone know how to fix this?
Post not yet marked as solved
iPad mini device with iPadOS 17.4.1.
I get this failure on iPad mini device exclusively. I have universal app and I doesn't get this error neither on iPhone or any simulator or macOS. I tried to reset the iPad, still getting the error.
The error happens when I send the app to background from the particular app screen.
Here is the error:
error: Store failed to load.
<NSPersistentStoreDescription: 0x3004b4bd0> (type: SQLite, url: file:///dev/null) with error = Error Domain=NSCocoaErrorDomain Code=134060
"A Core Data error occurred."
UserInfo={NSLocalizedFailureReason=The configuration named 'default' does not contain any entities.} with userInfo {
NSLocalizedFailureReason = "The configuration named 'default' does not contain any entities.";
}
What error says is that it loaded the store from file:///dev/null, which is wrong. Basically it looses the model container which is added via modelContaner modificator to the root view.
The error get caused particularly by the @Environment(\.modelContext) private var modelContext call in the view on which the failure occurs. This view is deep in the view hierarchy, and it get's created in the navigationDestination block.
I fixed the error by supplying modelContainer one more time right on the view:
.navigationDestination(for: File.self) { file in
FileEditor(file: file)
.modelContainer(FolderService.modelContainer)
}
I wonder, why can it loose the model container which is supplied on the root view?
Post not yet marked as solved
hello
I am trying to detect the orientation of text in images. (each image has a label with a number but sometimes the the label is not in the right orientation and I would like two detect these cases and add a prefix to the image files)
this code is working well but when the text is upside down it considers that the text is well oriented
is it a way to distinguish the difference ?
thanks for your help !
import SwiftUI
import Vision
struct ContentView: View {
@State private var totalImages = 0
@State private var processedImages = 0
@State private var rotatedImages = 0
@State private var remainingImages = 0
var body: some View {
VStack {
Button(action: chooseDirectory) {
Text("Choisir le répertoire des images")
.padding()
}
Text("TOTAL: \(totalImages)")
Text("TRAITEES: \(processedImages)")
Text("ROTATION: \(rotatedImages)")
Text("RESTANT: \(remainingImages)")
}
.padding()
}
func chooseDirectory() {
let openPanel = NSOpenPanel()
openPanel.canChooseDirectories = true
openPanel.canChooseFiles = false
openPanel.allowsMultipleSelection = false
openPanel.begin { response in
if response == .OK, let url = openPanel.url {
processImages(in: url)
}
}
}
func processImages(in directory: URL) {
DispatchQueue.global(qos: .userInitiated).async {
do {
let fileManager = FileManager.default
let urls = try fileManager.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil)
let imageUrls = urls.filter { $0.pathExtension.lowercased() == "jpg" || $0.pathExtension.lowercased() == "png" }
DispatchQueue.main.async {
self.totalImages = imageUrls.count
self.processedImages = 0
self.rotatedImages = 0
self.remainingImages = self.totalImages
}
for url in imageUrls {
self.processImage(at: url)
}
} catch {
print("Error reading contents of directory: \(error.localizedDescription)")
}
}
}
func processImage(at url: URL) {
guard let image = NSImage(contentsOf: url), let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil) else {
return
}
let request = VNRecognizeTextRequest { (request, error) in
if let error = error {
print("Error recognizing text: \(error.localizedDescription)")
return
}
if let results = request.results as? [VNRecognizedTextObservation], !results.isEmpty {
let orientationCorrect = self.isTextOrientationCorrect(results)
if !orientationCorrect {
self.renameFile(at: url)
DispatchQueue.main.async {
self.rotatedImages += 1
}
}
}
DispatchQueue.main.async {
self.processedImages += 1
self.remainingImages = self.totalImages - self.processedImages
}
}
let handler = VNImageRequestHandler(cgImage: cgImage, options: [:])
do {
try handler.perform([request])
} catch {
print("Error performing text recognition request: \(error.localizedDescription)")
}
}
func isTextOrientationCorrect(_ observations: [VNRecognizedTextObservation]) -> Bool {
// Placeholder for the logic to check text orientation
// This should be implemented based on your specific needs
for observation in observations {
if let recognizedText = observation.topCandidates(1).first {
let boundingBox = observation.boundingBox
let angle = atan2(boundingBox.height, boundingBox.width)
if abs(angle) > .pi / 4 {
return false
}
}
}
return true
}
func renameFile(at url: URL) {
let fileManager = FileManager.default
let directory = url.deletingLastPathComponent()
let newName = "ROTATION_" + url.lastPathComponent
let newURL = directory.appendingPathComponent(newName)
do {
try fileManager.moveItem(at: url, to: newURL)
} catch {
print("Error renaming file: \(error.localizedDescription)")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Post not yet marked as solved
I have an app which uses SwiftUI and Mac Catalyst. When running on a Mac I want to provide a preferences menu entry with the usual keyboard shortcut Command + ,. An implementation via the Settings bundle is out of question since my preferences are too complex for this.
Here is a reduced example of my implementation:
import SwiftUI
@main
struct PreferencesMenuTestApp: App {
@UIApplicationDelegateAdaptor private var appDelegate: AppDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
class AppDelegate: UIResponder, UIApplicationDelegate {
override func buildMenu(with builder: UIMenuBuilder) {
let preferencesCommand = UIKeyCommand(title: "Preferences…",
action: #selector(showPreferences),
input: ",",
modifierFlags: .command)
// let preferencesCommand = UIAction(title: "Preferences…") { action in
// debugPrint("show preferences")
// }
let menu = UIMenu(title: "Preferences…",
options: .displayInline,
children: [preferencesCommand])
builder.insertSibling(menu, afterMenu: .about)
}
@objc
func showPreferences() {
debugPrint("show preferences")
}
}
The problem is that the menu entry is disabled. Obviously the provided selector is not recognised. When I mark the AppDelegate with @main, then the menu entry is enabled. Of course then the app's window is empty.
When I switch to the UIAction implementation (the out commented code) it works fine. But since one cannot provide a keyboard shortcut for UIActions this is not a good solution.
What am I missing? How would one implement a preferences menu entry that actually works?
Post not yet marked as solved
I recently encountered a difficult-to-diagnose bug in an app that I'm working on, and I thought I would share it with the Apple Developer community.
The app that I'm working on is an iOS app that uses Core Location's Visit Monitoring API, and it is essential that the app is able to process incoming visits while running in the background. However, after real-world testing, I discovered several crash reports which were difficult to understand, as SwiftUI symbols are not symbolicated on debug builds.
Eventually I discovered that the app was crashing when calling an @EnvironmentObject property of the root ContentView from that view's body when the app was launched directly into the background from not running at all.
After creating a small test app to isolate the problem, I discovered that any environment object declared in the App struct and referenced from the root ContentView causes the crash, with the exception message: "Fatal error: No ObservableObject of type ArbitraryEnvObject found. A View.environmentObject(_:) for ArbitraryEnvObject may be missing as an ancestor of this view."
It seems that when a SwiftUI app is launched in the background, the ContentView's body is executed, but the environment is not initialized. I searched through as much documentation as I could, but could not find any information about how this should be handled, so I think it's a bug in SwiftUI. I have filed a Feedback Assistant bug report.
The current workaround is to convert my ObservableObject into an object that conforms to the new @Observable protocol, add it to the scene as an Environment Value with the .environment(_:) modifier rather than the .environmentObject(_:) modifier, and declare the @Environment property on the view as optional. The object will still be missing when the app is launched in the background, but the optional property can be handled safely to prevent a crash.
Attached to this post is a sample project that demonstrates the issue and the workaround.
And finally, I'd like to hear from anyone who knows more about the expected behavior of background launches of SwiftUI apps, and whether or not there's something I should be doing completely differently.
I'm not able to directly attach a zip archive to this post, so here's an iCloud link to the sample project: BackgroundEnvObjCrash.zip
Post not yet marked as solved
Hello, can someone please explain to me how does SwiftUI TabView works "under the hood" , I don't understand why do all views in TabView get reinitialized each time I switch between tabs.
Xcode Version 15.3, iOS 16+
Below is the code snippet :
struct ScreenOne: View {
init() {
print("ScreenOne init called !")
}
var body: some View {
Text("This is screen one!")
}
}
struct ScreenTwo: View {
init() {
print("ScreenTwo init called !")
}
var body: some View {
Text("This is screen two !")
}
}
struct TabViewTest: View {
@State var selectedIndex: Int = 1
var body: some View {
TabView(selection: $selectedIndex) {
ScreenOne()
.tag(1)
.tabItem {
Text("Item 1")
}
ScreenTwo()
.tag(2)
.tabItem {
Text("Item 2")
}
}
// .onChange(of: selectedIndex) { oldValue, newValue in
//
// }
// NOTE: When code above is uncommented
// Screen one & Screen two initializers get called
// each time switch to different tab occurs
}
}
Snippet output with the commented out code :
App loads
Both print statements get called -> "ScreenOne init called ! & "ScreenTwo init called !
Switch between taps
Nothing happens
Snippet output with the uncommented code :
App loads
Both print statements get called -> ScreenOne init called ! & ScreenTwo init called !
Switch between taps
Both print statements get called -> ScreenOne init called ! & ScreenTwo init called !
@eskimo heeelp :)
Thanks in advance !
Post not yet marked as solved
I am little confused about when to use State / StateObject / ObservedObject.
What I have researched and what I understand:
@State --> for value types
@StateObject --> for reference types
@ObservedObject --> child objects who needs reference to above two (the parent object should have @State/@StateObject and the object should conform to Observable)
I am clear about Environment object.
Post not yet marked as solved
Gents, dev(il)s,
I am looking for a piece of code or principal explanation to realise following:
I have a array of struct Item{}
Each item has child [Item]
in the content view I would like to have a hierarchical displayed tree of my Items and for each Item line I would like to have a button to remove it or add a child item for a selected one
I tired List entity, navigation and have no real success. Is anybody there to give me a small guide?
Thank you
M
Post not yet marked as solved
Hello developers !
I've created a List or a ForEach from a binding where there are TextFields or TextEditors inside.
When I go to fill in the text, the keyboard dismisses after one char is typed in !
My need is to be able to add textfields as much as required.
Please have a look to this code
import SwiftUI
struct ContentView: View {
@State private var messages = ["Hello 1","Hello 2","Hello 3"]
var body: some View {
VStack(alignment: .leading) {
List($messages, id: \.self) { $msg in
TextEditor(text: $msg)
}
ForEach($messages, id: \.self) { $msg in
VStack{
TextEditor(text: $msg)
}
.contextMenu{
Button(role: .destructive, action: {
messages = messages.filter {$0 != msg}
}, label:{
Text("Delete entry")
})
}
}
Button(action: {
messages.append("-")
}
, label: {
Text("Add a row")
})
}
.background(.black)
.padding()
}
}
#Preview {
ContentView()
}
I'm using iOS 17.4 and Xcode 15.3
Thanks !