iOS Design Patterns | Singleton

133 views Asked by At

I am fetching data from server in a method for eg - fetchData().

I want to write logic in such a way that if fetchData() called twice(one after another) from different classes, both classes should be notified once network call is completed. My fetchData() method is block based.

Basically, I want to achieve following- If n/w call is in progress, then another call to fetchDAta() should not initiate n/w call to get same data.

For Example

fetchData() method is used to display data on two view controller Eg A and B.

If user is on controller A, then **fetchData()** call will be initiated and if before its completion user moved to controller B which also calls fetchData() to show data. Then again network call or other operation will happen.

If we know that data is same, is there any way we can pass same data to controller B once first call to that method finishes without initiating the n/w call again?

how to call completion handler for both controllers A and B?

2

There are 2 answers

0
Shehata Gamal On

1- Since there is a one - many notifications , then the best is using NSNotificationCenter to send data is ready messages to all listeners , regarding the data itself you may send it when posting the notification using object or userInfo of the Notification center or share it in a singleton

2- With NotificationCenter no need for that , the one who needs the data should register as an observer

1
janusfidel On

Assuming your fetchData is in the singleton class, one approach would be using delegates in your singleton class to directly notify them with the changes. Add Class A and Class B as delegate.

protocol FetchDataProtocol {
    func didfinishDownloadingData()    
}


class SingletonClass {
    private var observers: [FetchDataProtocol] = []

    func add(observer: FetchDataProtocol) {
        if observers.index(where: { $0 === observer }) == nil {
           observers.append(observer)
        }
    }

    func remove(observer: FetchDataProtocol) {
        //find the object from observers then remove
    }

    private func notifyAll() {
         observers.forEach{ observer in 
            observer.didfinishDownloadingData()
         }
    }

   public function fetchData(){
      //When finished
      self.notifyAll()
   }
}

Add your classes as observers to fetchData changes.

// Do the same for ClassB
ClassA: FetchDataProtocol {
   init() {
     SingletonClass.shared.add(self)
  }

  func didfinishDownloadingData() {
       //notified here
  }

  deinit() {
     SingletonClass.shared.remove(self)
  }
}