1

Hi first off I'm very new to swift and programing (coming from design field). I'm trying to update doesNotificationsExist based on posts.count

I'm getting true inside the Api().getPosts {} Where I print the following:

print("Api().getPosts")
print(doesNotificationExist)

but outside (in the loadData() {}) I still get false and not the @Publihed var doesNotificationExist:Bool = false doesn't update.

Please help me out, I would really appreciate some guidance to what I'm doing wrong and what I need to do.

Here is my code:

import SwiftUI
import Combine

public class DataStore: ObservableObject {
    @Published var posts: [Post] = []
    @Published var doesNotificationExist:Bool = false
    
    init() {
        loadData()
        startApiWatch()
    }
    
    func loadData() {
        
        Api().getPosts { [self] (posts) in
            self.posts = posts

            if posts.count >= 1 {
                doesNotificationExist = true
            }
            else {
                doesNotificationExist = false
            }
            
            print("Api().getPosts")
            print(doesNotificationExist)
        }
        print("loadData")
        print(doesNotificationExist)
    }
    
    func startApiWatch() {
        Timer.scheduledTimer(withTimeInterval: 60, repeats: true) {_ in
            self.loadData()
            
        }
    }

View where I'm trying to set an image based on store.doesNotificationsExist

StatusBarController:

import AppKit
import SwiftUI

class StatusBarController {
    private var statusBar: NSStatusBar
    private var statusItem: NSStatusItem
    private var popover: NSPopover
    
    @ObservedObject var store = DataStore()
    
    init(_ popover: NSPopover)
    {
        self.popover = popover
        statusBar = NSStatusBar.init()
        statusItem = statusBar.statusItem(withLength: 28.0)
        
        statusItem.button?.action = #selector(togglePopover(sender:))
        statusItem.button?.target = self
    
        if let statusBarButton = statusItem.button {
            let itemImage = NSImage(named: store.doesNotificationExist ? "StatusItemImageNotification" : "StatusItemImage")
            statusBarButton.image = itemImage
            statusBarButton.image?.size = NSSize(width: 18.0, height: 18.0)
            statusBarButton.image?.isTemplate = true
            statusBarButton.action = #selector(togglePopover(sender:))
            statusBarButton.target = self
        }
        
    }
`Other none relevant code for the question`

 }

Niklas
  • 35
  • 8

1 Answers1

1

It’s a closure and hopefully the @escaping one. @escaping is used to inform callers of a function that takes a closure that the closure might be stored or otherwise outlive the scope of the receiving function. So, your outside print statement will be called first with bool value false, and once timer is completed closure will be called changing your Bool value to true.

Check code below -:

import SwiftUI


public class Model: ObservableObject {
    //@Published var posts: [Post] = []
    @Published var doesNotificationExist:Bool = false
    
    init() {
        loadData()
       // startApiWatch()
    }
    
    func loadData() {
        
        getPost { [weak self] (posts) in
            //self.posts = posts

            if posts >= 1 {
                self?.doesNotificationExist = true
            }
            else {
                self?.doesNotificationExist = false
            }
            
            print("Api().getPosts")
            print(self?.doesNotificationExist)
        }
        print("loadData")
        print(doesNotificationExist)
    }
    
    func getPost(completion:@escaping (Int) -> ()){
        Timer.scheduledTimer(withTimeInterval: 5, repeats: true) {_ in
            completion(5)
            
        }
    }
}

struct Test1:View {
    @ObservedObject var test = Model()
    var body: some View{
        Text("\(test.doesNotificationExist.description)")
    }
}
Tushar Sharma
  • 2,839
  • 1
  • 16
  • 38
  • Thanks @tushar-sharma that seems to fix the issue with. the bool not being set to true. All though I seem to still have a problem. I have Edited my question to contain my other file where I'm trying set an image based on the does.NotificationExist – Niklas Jun 22 '21 at 12:46
  • @NiklasPeterson The updated code you shared is for swift, and not swiftUI. Property wrappers are meant to work with swiftUI views. – Tushar Sharma Jun 22 '21 at 12:50
  • Sorry still very new to programming :D so I can't use the `@ObservedObject var store = DataStore()` or `let itemImage = NSImage(named: store.doesNotificationExist ? "StatusItemImageNotification" : "StatusItemImage")` in normal swift then? – Niklas Jun 22 '21 at 12:54
  • You should look at how to communicate between swift and swiftUI. We can still do it, but not in the direct way as you tried. – Tushar Sharma Jun 22 '21 at 12:57
  • I'll accept the answer since it answered my first question. But I'm still not 100% sure how to solve the second part of the problem if I set the `self.doesNotificationExist = true` then it shows shows the right image but with it still doesn't update based on the suggestion you made before. So the data is passed because if I change it to true it shows right image. It's just don't set the image after the completion(5) – Niklas Jun 22 '21 at 14:01
  • You are making changes within init, it will not be called once completion(5) is called. We are not creating object again – Tushar Sharma Jun 22 '21 at 14:08