I wanted to experiment a little using UINavigationController with SwiftUI App Lifecycle
I created a Custom Navigation Controller named JDNavigationController. It does not do much other than having the @Observable macro
public struct NavigationControllerStack<Content: View>: UIViewControllerRepresentable {
private let initialView: () -> Content
@State private var controller = JDNavigationController()
public init(content: @escaping () -> Content) {
self.initialView = content
}
public func makeUIViewController(context: Context) -> JDNavigationController {
let viewController = self.initialView()
.environment(self.controller)
.viewController
self.controller.viewControllers = [
viewController
]
return controller
}
public func updateUIViewController(_ uiViewController: JDNavigationController, context: Context) {
}
public typealias UIViewControllerType = JDNavigationController
}
when I check, the functionality of the navigation controller works as expected, however, I can't for the life of me to change the background color of the status bar.
#Preview {
NavigationControllerStack {
ZStack {
Color.purple
.ignoresSafeArea(.all)
VStack {
Text("somethign")
}
}
}
}
I have tried
Using the appearance functions
Creating a Custom View Controller, and in that view controller I tried using a Hosting Controller by adding the hosting controller as a child and
setting hostingController.view.insetsLayoutMarginsFromSafeArea = false
using the toolbar modifiers from SwiftUI View
none seems to work.
I opened the View Debugger it looks like the white portion comes from the UIHosting Controller but I am not sure what I can do to fix it
Post
Replies
Boosts
Views
Activity
ViewA has ModelA
ViewA loads into the memory. ModelA is queried and shown in the list.
ModelA has an array of ModelB which is faulted for the memory.
When you select an item in the list in ViewA ViewB is loaded and ModelB information is displayed.
When you pop back to ViewA, ModelB is still in the memory since it is contained within the array of ModelA.
how could i make this memory efficient by releasing ModelB from the memory.
should I refetch everything? or is there another method?
I have two models a Person and a Possession
the Person model has a one to many relationship to the Possession model.
meaning each possession can only have one person but a person can have multiple possessions.
I have set my model like the following
Person:
@Model
class Person {
@Attribute(.unique)
let personID: String
@Relationship(.cascade, inverse: \Possession.person)
var possetions: [Possession]?
init(id: String, possessions: [Possession]) {
self.personID = id
self.possetions = possessions
}
}
Possession:
@Model
class Possession {
@Attribute(.unique)
let id: String
let name: String?
var person: Person?
init(id: String, name: String, person: Person) {
self.id = id
self.name = name
self.person = person
}
}
If i set a breakpoint i see that all the posessions are loaded into the memory this is something i do not want to happen.
In Core Data we get a relationship fault however, i am not seeing the same behavior in SwiftData.
here's how my view is implemented
struct ContentView: View {
@Environment(\.modelContext) private var modelContext
@EnvironmentObject private var navigationStore: NavigationStore
@Query() private var people: [Person]
var body: some View {
List {
ForEach(people) { person in
NavigationLink(value: person) {
VStack {
Text(person.personID)
}
}
.swipeActions {
Button("Delete") {
modelContext.delete(person)
}
}
}
}
.toolbar(content: {
Button("Add") {
let newPErson = Person(id: UUID().uuidString, possessions: [])
modelContext.insert(newPErson)
do {
try modelContext.save()
} catch {
assertionFailure("\(error)")
}
}
})
.navigationDestination(for: Person.self) { person in
Text("hello")
}
}
}
at the launch i do not want posessions to be loaded into the memory. I want them loaded when they are being used.
I am trying to get the user to pick an image from their gallery. After doing some research I was able to accomplish this task by using a UIViewControllerRepresentable. However, after I opened up the memory debugger it shows that I have a memory leak
I created a basic example to which would make the code a lot simpler to read and still address the same issue without copy-pasting my entire code. the code below also shows a memory leak
// code for the views
import SwiftUI
import UIKit
struct ContentView: View {
var body: some View {
NavigationView {
NavigationLink(
destination: ImagePickerView(),
label: {
Text("Navigate")
})
}
}
}
struct ImagePickerView: View {
@State var image = UIImage()
@State var showController: Bool = false
@State var didChoose : Bool = false
var body: some View {
Button(action: {
showController = true
}, label: {
Text("pick image")
})
.sheet(isPresented: $showController, content: {
ImagePicker(image: $image, didChoose: $didChoose)
})
}
}
struct ImagePicker : UIViewControllerRepresentable {
@Binding var image: UIImage
@Binding var didChoose: Bool
@Environment(\.presentationMode) var presentation
func makeUIViewController(context: UIViewControllerRepresentableContextImagePicker) - UIViewController {
let controller = UIImagePickerController()
controller.delegate = context.coordinator
return controller
}
func updateUIViewController(_ uiViewController: ImagePicker.UIViewControllerType, context: UIViewControllerRepresentableContextImagePicker) {
}
func makeCoordinator() - Coordinator {
return Coordinator(self)
}
class Coordinator : NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let parent : ImagePicker
init(_ parent: ImagePicker) {
self.parent = parent
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let pickedImage = info[.originalImage] as? UIImage else {
print("could not unwrap the image")
return
}
print(pickedImage)
self.parent.image = pickedImage
self.parent.didChoose = true
self.parent.presentation.wrappedValue.dismiss()
}
}
}
I suspect the cause to be the in the coordinator class however, failed to identify the reason behind it. is it involved with the parent?
here's how it supposed to work
I have a login screen where the user logs in entering their username and password. (the UI is built programmatically)
the login screen inherits from UIViewController after the user clicks the sign-in I make a request to get their information from firebase. and then if the login is successful I create a variable such as
let student = Student()
assign the information I grabbed from firebase to the created object student.
and then I do something like
let nextController = theTabBarControllerClass()
nextController.student = student
navigationController.pushViewController(nextController, animated: true)
my expectation here is that the value should pass to the tabbarviewcontroller.
My plan was to get the data to the tab bar view controller and when I have an array of view controllers say
HomeFeedViewController
ProfileViewController
SearchUserViewController
HistoryViewController
AddFriendViewController
i could create a student variable for each one of these view controller objects and pass the data from the tab bar view controller.
However, when I try to pass the object from loginViewcontroller to the tabbarviewcontroller, the properties are always nil.
here are some things I've gathered
From what I know this has nothing to do with the student object I created. I created a dummy string variable and tried to pass it, however, it was still nil.
I suspect that the problem lies within the fact that I am not too familiar with tabbarviewcontrollers since this is the first time I am working on them.