Firebase Observe() Clarification - swift

If you for instance do
DataBase.database().refrence().observe(.valueChanged....
//code here
)
more then one time in the same spot, does this create a stack of observers? I want to make sure I only have 1 observer per spot. Does calling this method multiple times create more then one observer?

If you attach multiple observers to the same location in the database, the SDK is smart enough to internally only register with the server to receive updates to that location once. It doesn't duplicate the amount of data sent to the app. All your observers at that location will still receive the updates, so you will need to unregister each to stop receiving updates.

Related

Is there a standard / built-in way to handle race conditions with CKFetchRecordZoneChangesOperation?

I'm building my first CloudKit application, and am using CKFetchRecordZoneChangesOperation on startup to get any new records changed while the current device was offline.
I am also calling CKFetchRecordZoneChangesOperation when I receive a subscription notification of changes.
It is possible the subscription notification could come in before the startup call finishes. I am currently using a lock to prevent the 2nd call from starting until the recordZoneFetchCompletionBlock handler is called, signalling that the first one is done. This works, but it also smells a bit hacky.

StartUpdatingLocation Vs significant-change location service

I am having issue regarding significant-change location service.
Apple documentation says "Whether you use the standard location service or the significant-change location service to get location events, the way you receive those events is the same."
but in case of "significant-change location service" I am not able to get any callbacks which
I get in case of "standard location service" Please let me know if anybody has any inputs?
startUpdatingLocation updates the location when it is called first time and then when the distance filter value exceeds.
But the startMonitoringSignificantLocationChanges when a significant change in position occurs.
Please check CLLocationManager for the details.
startUpdatingLocation
Starts the generation of updates that report the user’s current
location.
- (void)startUpdatingLocation Discussion
This method returns immediately. Calling this method causes the
location manager to obtain an initial location fix (which may take
several seconds) and notify your delegate by calling its
locationManager:didUpdateLocations: method. (In iOS 5 and earlier, the
location manager calls the
locationManager:didUpdateToLocation:fromLocation: method instead.)
After that, the receiver generates update events primarily when the
value in the distanceFilter property is exceeded. Updates may be
delivered in other situations though. For example, the receiver may
send another notification if the hardware gathers a more accurate
location reading.
Calling this method several times in succession does not automatically
result in new events being generated. Calling stopUpdatingLocation in
between, however, does cause a new initial event to be sent the next
time you call this method.
If you start this service and your application is suspended, the
system stops the delivery of events until your application starts
running again (either in the foreground or background). If your
application is terminated, the delivery of new location events stops
altogether. Therefore, if your application needs to receive location
events while in the background, it must include the UIBackgroundModes
key (with the location value) in its Info.plist file.
In addition to your delegate object implementing the
locationManager:didUpdateLocations: method, it should also implement
the locationManager:didFailWithError: method to respond to potential
errors.
startMonitoringSignificantLocationChanges
Starts the generation of updates based on significant location
changes.
- (void)startMonitoringSignificantLocationChanges Discussion
This method initiates the delivery of location events asynchronously,
returning shortly after you call it. Location events are delivered to
your delegate’s locationManager:didUpdateLocations: method. The first
event to be delivered is usually the most recently cached location
event (if any) but may be a newer event in some circumstances.
Obtaining a current location fix may take several additional seconds,
so be sure to check the timestamps on the location events in your
delegate method.
After returning a current location fix, the receiver generates update
events only when a significant change in the user’s location is
detected. For example, it might generate a new event when the device
becomes associated with a different cell tower. It does not rely on
the value in the distanceFilter property to generate events. Calling
this method several times in succession does not automatically result
in new events being generated. Calling
stopMonitoringSignificantLocationChanges in between, however, does
cause a new initial event to be sent the next time you call this
method.
If you start this service and your application is subsequently
terminated, the system automatically relaunches the application into
the background if a new event arrives. In such a case, the options
dictionary passed to the locationManager:didUpdateLocations: method of
your application delegate contains the key
UIApplicationLaunchOptionsLocationKey to indicate that your
application was launched because of a location event. Upon relaunch,
you must still configure a location manager object and call this
method to continue receiving location events. When you restart
location services, the current event is delivered to your delegate
immediately. In addition, the location property of your location
manager object is populated with the most recent location object even
before you start location services.
In addition to your delegate object implementing the
locationManager:didUpdateLocations: method, it should also implement
the locationManager:didFailWithError: method to respond to potential
errors.
Note: Apps can expect a notification as soon as the device moves 500
meters or more from its previous notification. It should not expect
notifications more frequently than once every five minutes. If the
device is able to retrieve data from the network, the location manager
is much more likely to deliver notifications in a timely manner.

Storing pointers in Core Data

I am storing some objects in core data that have inherent life spans. I was scheduling local notifications on object creation for this lifespan and then handling the object went the notification fired.
The problem is that the objects can end early. But the local notifications don't know this and still fire at their respective time which leads to confusion. Is there a way to store a pointer to the notification in with the object? So if it ends early it can just cancel it.
I would like to stick with notifications as I need the user to know when it is finished, if it finishes normally. And notifications don't depend on the app running.
Basic question can you store pointers to objects in core data. Second question is if local notifications change memory addresses during their lifespan
I know I could just cancel them all and reschedule the ones needed if one ends early but that just seems wasteful and hopefully there's a better way.
UILocalNotification is not serializable (it doesn't implement NSCoding), so you can't store it persistently with Core Data. I suggest you add the Core Data entities' managedObjectID in serializable form (e.g. as an URL) to the notifications' userInfo property. If you need to delete a specific notification, you search your UIApplications' scheduledLocalNotifications array for the local notification with the corresponding managed object ID in its userInfo property and then cancel that one via cancelLocalNotification:.
Heads up - I've been reviewing this topic, and I'm seeing some conflicting information with the answer from #MrMage :
UILocalNotification does conform to NSCoding per the Apple doc
Here's an answer on stackoverflow that describes how to store the local notification in nsdata which should enable you to store the localnotification as a property in an entity: Delete a particular local notification
Not an expert on this topic though, so any feedback would be great.

NSNotificationCenter question

Is there a way to know if an object is already registered as an observer for a particular notification?
In my implementation I have to add and remove the observers on the fly. For some reason, there is a random issue where the listener is receiving twice the same notification. I know I have to review my coding but It will be easier to fix for me if I could know this info.
Thanks.
No. There is no way to query this information. If you need it, you need to keep track of that yourself.
You might want to look into NSNotificationQueue. Here's the overview from Apple. It sounds like this could help you stop receiving duplicate notifications:
NSNotificationQueue objects (or simply
notification queues) act as buffers
for notification centers (instances of
NSNotificationCenter). Whereas a
notification center distributes
notifications when posted,
notifications placed into the queue
can be delayed until the end of the
current pass through the run loop or
until the run loop is idle. Duplicate
notifications can also be coalesced so
that only one notification is sent
although multiple notifications are
posted. A notification queue maintains
notifications (instances of
NSNotification) generally in a first
in first out (FIFO) order. When a
notification rises to the front of the
queue, the queue posts it to the
notification center, which in turn
dispatches the notification to all
objects registered as observers.
Every thread has a default
notification queue, which is
associated with the default
notification center for the task. You
can create your own notification
queues and have multiple queues per
center and thread.

NSNotificationCenter: How long does it take to perform an operation

I want to know how long does it take from posting a notification to getting the notification.
The reason is that I want to find out if the observer pattern is suitable for me. I don't want that another view controller can change the value before the notification has been sent and processed. I'm afraid that another process (thread?) is faster and the value will be overwritten when it shouldn't.
A notification center delivers messages synchronously, which means that the postNotification: method does not return until all objects registered to receive the notification have processed the notification. In other words, you can think of it as taking no time between posting a notification and receiving the notification.
There are a few extra things you'll need to be aware of:
Notifications are received on the same thread in which they are posted. If you move a notification over to the main thread using performSelectorOnMainThread:withObject:waitUntilDone:, you can break the synchronous behavior if waitUntilDone is set to NO. If waitUntilDone is set to YES, the thread passing the notification will block until the main thread has finished performing the specified action.
There is no guarantee of the order in which a notification will be received by its observers. If a single notification has multiple observers, don't rely on those observers receiving the notification in any particular order.
Given the above, and knowing which thread is posting notifications in your application and which thread needs to process them, you should be able to figure out whether the observer pattern will work for you.
you can use enqueueNotification for finer grained control over the processing of the notifications, but in the end I believe you can run into the same issue you have expressed concern about regardless of a NotificationCenter implementation or not