-1

I'm trying to either show or not show my "NoPostsView" depending on my firebase database.

That's my function for finding out if there are posts:

func checkIfPostsExists(YES: @escaping () -> Void, NO: @escaping () -> Void)
{
     REF_POSTS.observeSingleEvent(of: .value, with:
     {
         (snapshot) in
         if snapshot.exists()
         {
             YES()
         }
         else
         {
             NO()
         }
     })
}

And that's how I use it:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
    checkIfPostsExists(YES:
    {
        if self.posts.count <= 0
        {
            return 7 // ERROR IS IN THIS LINE
        }
        else if self.posts.count != 0
        {
            self.noPostsView.isHidden = true
        }
    })
    {
        self.noPostsView.isHidden = false
    }
    return posts.count
}

The error I'm getting is:

Unexpected non-void return value in void function

I'm pretty sure it's caused due to me returning 7 in that function but I can't seem to get my head around fixing the error.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Marie.K
  • 37
  • 8
  • 1
    the closures are defined as `@escaping () -> Void` which means it takes no params and returns nothing. If checkIfPostsExists function does anything like going to the network or reading from a database this wont work anyway, it will always return posts.count – Scriptable Nov 01 '18 at 15:23
  • Thank you. But how should I do this then? – Marie.K Nov 01 '18 at 15:24
  • explain it fully first, what exactly does `checkIfPostsExists` do? – Scriptable Nov 01 '18 at 15:25
  • I have the function in my question. All it does is that it accesses the database and checks if a given child exists – Marie.K Nov 01 '18 at 15:26
  • I can't fully understand why you used closure to do this thing. If you want to check if something exists, then make the tableView behave based on this, you can use just reload data based on a condition – Andrew21111 Nov 01 '18 at 15:31
  • I can't explain to you why I used this but it, unfortunately, is necessary. So is there a way to do this? Really appreciate you guys helping me btw :D – Marie.K Nov 01 '18 at 15:34

1 Answers1

0

You should be able to do something like this...

// uses a completion with a boolean value to show whether has posts or not
private func hasPosts(completion: (Bool) -> Void) {
    // check posts and then at some point return a boolean
    completion(true) 
}

// check if has posts and either show tableView or noPostsView
override func viewDidLoad() {
   super.viewDidLoad() 

   hasPosts() { hasPosts in 
      if hasPosts {
          tableView.dataSource = self
          // maybe other logic
      }
      noResultsView.isHidden = hasPosts
      tableView.isHidden = !hasPosts
   }
} 
Scriptable
  • 19,402
  • 5
  • 56
  • 72
  • Thank you but that way I still can't return something – Marie.K Nov 01 '18 at 15:39
  • You *cannot* just return from an async function. async functions take time so your function returns before they finish. So you use a completion handler to 'do some work when the task has finished'. Using the example above, when you load the VC you check to see if you have posts or not and then either load the `tableView` or the `noPostsView`. The way you are doing it, `return posts.count` returns before the db has been accessed – Scriptable Nov 01 '18 at 15:46
  • But I'd like to still show the tableView even if there aren't any posts. Is that possible? – Marie.K Nov 01 '18 at 15:52
  • yes of course, just change the logic, you can review this other answer for more info on 'returning from async function': https://stackoverflow.com/questions/25203556/returning-data-from-async-call-in-swift-function – Scriptable Nov 01 '18 at 15:54
  • Or is it may be possible to change the number of rows a tableView has outside of the `numberOfRowsInSection ` function – Marie.K Nov 01 '18 at 15:54
  • You said: "Just change the logic" But that is the problem I don't know how to do so – Marie.K Nov 01 '18 at 15:56
  • Thank you but I already use completionHandlers in my `checkIfPostsExists` function and it still doesn't work. If I'm understanding something wrong please correct me or edit your answer and show me an example. :D – Marie.K Nov 01 '18 at 16:03
  • I was running out of time earlier. the way i have done it in my answer is to get the data and store it in an array on the VC, so when the VC first loads, the tableview will be empty and will fetch from the db and then fill the db if there are posts. you cannot use the closure in the way you are because you are trying to fetch from the db each time it asks for the row count, which is not only inefficient and wasting resources, its also not needed. fetch the records and then use the data to fill the table. the table will fill before the user even notices anything – Scriptable Nov 01 '18 at 21:32
  • and your closures specify that they return nothing and you are trying to return something – Scriptable Nov 01 '18 at 21:32
  • Wow, I can't believe I didn't think of that. Thank you so much!!! You've saved me a lot of time and work :D I really greatly appreciate that, thank you! c: – Marie.K Nov 01 '18 at 21:53
  • Your welcome :) I tried to explain that earlier but I was tight on time. Good luck with the project – Scriptable Nov 01 '18 at 22:20