0

I been struggling to update my tableview through another class I made. I then found this stackoverflow solution: How to access and refresh a UITableView from another class in Swift

But when I follow it step by step and implement all the codes, I get the following errors:

My line:

weak var delegate: UpdateDelegate?

Gets the warning

'weak' may only be applied to class and class-bound protocol types, not 'UpdateDelegate'

And my line:

self.delegate.didUpdate(self)

Gets warning:

Instance member 'delegate' cannot be used on type 'APIgetter'

Could this be because the code is old and I'm using swift 4? else I cannot see why this should be failing. I hope you can help me :)

Update:

My Protocol:

protocol UpdateDelegate: AnyObject {
    func didUpdate(sender: APIgetter)
}

Snippet from my ViewController containing the tableview:

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UpdateDelegate {

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        APIgetter.addDataFromSQL()
        let updates = APIgetter()
        updates.delegate = self
    }

    //update func
    func didUpdate(sender: APIgetter) {
        DispatchQueue.main.async {
            self.tableView.reloadData()
        }
    }

My APIgetter class in APIgetter.swift:

class APIgetter {
weak var delegate: UpdateDelegate?

class func addDataFromSQL (){

//Code to fetch data from API

//Code that comes after DispatchQueue.global & DispatchQueue.main and my result being executed
//result
self.delegate.didUpdate(self)
Jonas Borneland
  • 383
  • 1
  • 6
  • 19

1 Answers1

0

just update your protocol definition.

protocol UpdateDelegate: class {
   // protocol body
}

or

protocol UpdateDelegate: AnyObject {
   // protocol body
}

This is needed (as of Swift 4 I think) because classes are reference types and you can only use a weak reference on reference types. Not value types like structs.

UPDATE: You cannot access a property/instance member from a static function the way that you currently are. Remove the class keyword from the function and it should work.

If you want/need to use a single instance of this class throughout your application you can use a static property to make it a Singleton

class APIgetter {
    static let shared: APIgetter = APIgetter()
}

Then you would be able to access it like this:

APIgetter.shared.addDataFromSQL()

You could also update the delegate in the same way before calling your function.

APIgetter.shared.delegate = self

I think in this case though I would use a Singleton without the delegate. Just use a completion handler in your function. Setting and changing the delegate on a shared instance could have some side effects if not managed carefully.

Scriptable
  • 19,402
  • 5
  • 56
  • 72
  • Fantastic, thanks! But I'm still getting the "Instance member 'delegate' cannot be used on type 'APIgetter'" error – Jonas Borneland Feb 19 '18 at 20:59
  • can you post some more code, its difficult to help without knowing how you defined your classes/protocols. What is APIgetter? – Scriptable Feb 19 '18 at 21:02
  • @dafo for that error see [here](https://stackoverflow.com/a/40735415/5175709). Basically the delegate is an **instance** variable. However your `addDataFromSQL` has nothing to do with instances because you defined it to be a **class** function. If you remove the `class` from the `func` then it should work... – mfaani Feb 19 '18 at 21:11
  • ah yeah, like honey said. the function you are accessing is a static/class function and can't access instance members like that. Thanks Honey – Scriptable Feb 19 '18 at 21:16