Please ignore StringTool. its just a helper tool to ensure that if it's a nil, it will return "". In the child view i did it like this
init(temp: Binding<Temp?>) {
_temp = temp
}
in the parent view it looks like this
ChiildView(temp: $temp)
when i dismiss the child view, i want to set the property cityUrlId in the parent view which is @State
Post
Replies
Boosts
Views
Activity
Baaah.. managed to solve it
addInfo("Sample", action: () {
})
Image(uiImage: UIImage(named: "AppIcon") ?? UIImage()) works fine
This does not seem to be data about the value being stored but rather the number of keys being stored where the total must not exceed its limit.
Here is my code but it's not a workign sample code. just wish to have this checked out if in theory my assumptions are correct or not
struct ContentView: View {
@State var dark = PrefTool.instance.getBoolean(Keyword.DARK_MODE)
@State var show = false
@StateObject var navigationManager = SidebarNavigationManager()
@StateObject var appData = AppData()
@StateObject var toolbarData = ToolbarData()
var body: some View {
NavigationStack(path: $appData.path) {
ZStack(alignment: .leading) {
VStack(spacing: 0) {
HStack {
Button(action: {
withAnimation(.default) {
show.toggle()
}
}) {
Image(systemName: "line.3.horizontal")
}
Text("Home")
Spacer()
ToolbarView()
OverflowMenu()
.padding([.leading], Default.instance.PADDING_BETWEEN_MENU_ITEM)
}
.padding()
.foregroundColor(.primary)
.overlay(Rectangle().stroke(Color.primary.opacity(0.1), lineWidth: 1).shadow(radius: 3).edgesIgnoringSafeArea(.top))
MainContent(navigationManager: navigationManager)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
HStack {
SideMenuView(show: $show, navigationManager: navigationManager)
.preferredColorScheme(dark ? .dark : .light)
.offset(x: self.show ? 0 : -UIScreen.main.bounds.width / 1.2)
Spacer(minLength: 0)
Rectangle().stroke(.clear).frame(width: show ? UIScreen.main.bounds.width - (UIScreen.main.bounds.width / 1.2) : 0)
.contentShape(Rectangle())
.onTapGesture {
if (show) {
withAnimation(.default) {
show.toggle()
}
}
}
}
.background(Color.primary.opacity(self.show ? (self.dark ? 0.05 : 0.2) : 0))
}
.navigationBarHidden(true)
}
.navigationViewStyle(.stack)
.environmentObject(appData)
.environmentObject(toolbarData)
}
}
and ToolbarView and ToolbarData
struct ToolbarView: View {
@EnvironmentObject var toolbarData: ToolbarData
var body: some View {
HStack {
if let item = toolbarData.toolbarItem, item.visible {
Button {
item.action()
} label: {
if let iconLink = item.iconLink {
NavigationLink(destination: iconLink) {
Image(systemName: item.icon)
}
}
else {
Image(systemName: item.icon)
}
}
.disabled(item.disabled)
.opacity(item.opacity)
.padding([.leading, .trailing], Default.instance.PADDING_BETWEEN_MENU_ITEM)
}
}
}
}
final class ToolbarData: ObservableObject {
@Published var toolbarItem: ToolbarItemProperties?
func disableToolbarItem(_ toolbarItem: ToolbarItemProperties?, _ disabled: Bool) {
if let toolbarItem {
objectWillChange.send()
toolbarItem.disabled = disabled
}
}
func disableToolbarItem(_ toolbarItem: ToolbarItemProperties?, _ disabled: Bool, _ deadline: DispatchTime) {
if let toolbarItem {
DispatchQueue.main.asyncAfter(deadline: deadline) {
self.objectWillChange.send()
toolbarItem.disabled = disabled
}
}
}
func resetMenuItems() {
toolbarItem = nil
}
}
in a custom view e.g. MainContent in the code above. i do something from a button click like this
toolbarData.disableToolbarItem(toolbarData.toolbarItem, true, .now())
The thing is, only the ToolbarView() should be rebuilt. somehow, the whole ContentView() gets rebuilt instead. This should not behave like this right? Since only the ToolbarData is updated. Thoughts?
@babyj hi. tried it and it works. but i only used this section here
// This line is the key part
// Must be before the variable change
appData.objectWillChange.send()
I ran that code after every property change e.g.
appData.toolbarItem1?.disabled = true
appData.toolbarItem1?.objectWillChange.send()
but when i placed that before as you mentioned, it worked. and i do not understand why they have it behave that way if send() is called before a property change.
ps tollbarItem1 is also an ObservableObject in the appData class.
Please ignore. Seems the problem lies in the DailyCityReportView.
@ptit-xav it didnt work.
i have another class that contains the ToolbarItemProperties
final class AppData: ObservableObject {
@Published var toolbarItem1: ToolbarItemProperties?
}
it works if i do it like this
let item = ToolbarItemProperties()
item.disabled = true
appData.toolbarItem1 = item
but if i directly change the value of the property like this, nothing happens. it does not re-render. any idea why?
appData.toolbarItem1?.disabled = true
although if i do it like this (after setting a value to the disabled property, it works
appData.toolbarItem1 = appData.toolbarItem1
I still think even if a property of an ObservableObject is changed, it should refresh the view. not when the whole object is a set a value.
Baaaah. I luckily found the solution I was looking for a few minutes after posting this.
so we use .aspectRatio(ratio, contentMode: .fit)
I got it to work. by adding a condition in the MyView's body
if isShowing {
VStack(spacing: 0) {
Group {
row("#ff0000", "color1")
........
}
And this code in the button action
withAnimation {
isShowingLegend.toggle()
}
I do not understand why it works though. any inputs are appreciated. thank you.
Use state binding in the child view.
Guess the solution is to use state and binding (in the child view)
Well. I now got it to work... unexpectedly. Xcode still needs improvement. Devs do not have to keep on clearing builds, or deingtegrating pods to reset them.
i got to install the lib in pods
then just manually created a sapmle objective c library so that xxcode will prompt to create a header file
then import the bridging header file into your project's bridging header file
yep. this was never mentioned in any of the posts i came across with.
Seems i missed some code. here's the right one
struct SatelliteVideoView: View {
@State private var player: AVPlayer?
init() {
if let url = URL(string: "https://swiftanytime-content.s3.ap-south-1.amazonaws.com/SwiftUI-Beginner/Video-Player/iMacAdvertisement.mp4") {
player = AVPlayer(url: url)
}
}
var body: some View {
if player != nil {
VideoPlayer(player: player!)
}
}
}
@Claude31 it seems the problem is with the instantation of AVPlayer inside init(). honeslty, i have no clue why it behaves this way. If i specify the url when the variable is declared, it works. I followed the sample here
https://www.swiftanytime.com/videoplayer-in-swiftui/
and it works if it is coded like this
@State var player = AVPlayer(url: URL(string: "https://swiftanytime-content.s3.ap-south-1.amazonaws.com/SwiftUI-Beginner/Video-Player/iMacAdvertisement.mp4")!)
but, if it is done like this, it does not work
init() {
if let url = URL(string: "https://swiftanytime-content.s3.ap-south-1.amazonaws.com/SwiftUI-Beginner/Video-Player/iMacAdvertisement.mp4") {
player = AVPlayer(url: url)
}
}
Thoughts?