KVO nsmutablearray remove object notification - objective-c

i have a singleton class with a nsmutablearray
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
NSLog(#"Received notification: keyPath:%# ofObject:%# change:%#",
keyPath, object, change);
//[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
//array accessors
- (void)insertNewObject:(id)object
{
[self willChangeValueForKey:#"heldJoins"];
[heldJoins addObject:object];
[self didChangeValueForKey:#"heldJoins"];
}
- (void)removeObject:(id)object
{
[self willChangeValueForKey:#"heldJoins"];
[heldJoins removeObject:object];
[self didChangeValueForKey:#"heldJoins"];
}
i "observe" the changes made to this array from another class
my rootviewcontroller
[CCV addObserver:self forKeyPath:#"heldJoins" options:NSKeyValueChangeOldKey||NSKeyValueChangeNewKey context:NULL];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
NSLog(#"Received notification: keyPath:%# ofObject:%# change:%#",keyPath, object, [change allKeys]);
}
this works and i am notified when there is an object removed or added
however i cannot figure out (and maybe its not possible) how to see the object that was removed or added (mainly need the object when its removed not added though)
i know the NSDictionary variable Change should have my object but all it has is one key "kind" which always equals 1 since there is always 1 change made to the array.
the nsmutablearray is filled with numbers 500,100,300
so when one of those numbers is removed i would like to know which number was removed in my observer class
how can i do that?
answer code:
[CCV addObserver:self forKeyPath:#"heldJoins" options: NSKeyValueObservingOptionOld ||NSKeyValueChangeNewKey context:NULL];
NSLog(#"Received notification: keyPath:%# ofObject:%# change:%#",keyPath, object, [change valueForKey:#"new"]);

It sounds like you didn't specify NSKeyValueObservingOptionOld when you added the observer.

Related

Observer not working

I am trying to make an observer to notify me whenever my laptop it automatically changes its wifi connection.
I have a "NetworkProperties" class where I store my connection properties:
#interface NetworkProperties : NSObject
{
#public
CWInterface *wfi;
#private
CWWiFiClient *wfc;
NSString *SSID;
NSString *BSSID;
NSString *phyMode;
NSString *hwAddr;
NSString *securityType;
}
#end
and a "GUIHandle" class where I try to handle my GUI. I also have the following functions to enable/disable the scaning:
#interface GUIHandle : NSObject
{
NetworkProperties *NP;
}
-(IBAction)startScan:(id)sender;
-(IBAction)stopScan:(id)sender;
#end
-(IBAction)startScan:(id)sender
{
done = 0;
NP = [[NetworkProperties alloc] init];
[NP scanNetworkProperties];
[NP->wfi addObserver:self forKeyPath:#"bssid" options:NSKeyValueObservingOptionNew context:nil];
}
-(IBAction)stopScan:(id)sender
{
[NP->wfi removeObserver:self forKeyPath:#"bssid"];
}
- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
NSLog(#"We are here!\n");
if ([keyPath isEqual:#"bssid"]) {
NSLog(#"Value changed!\n");
}
}
However I do not get any notification if the "bssid" of my connection is changing. What am I doing wrong?

How do I detect property changes with RCT_EXPORT_VIEW_PROPERTY in Objective C?

RCT_EXPORT_MODULE()
- (UIView *)view
{
return [[RNNativeListview alloc] initWithBridge:self.bridge];
}
RCT_EXPORT_VIEW_PROPERTY(rowHeight, float)
RCT_EXPORT_VIEW_PROPERTY(numRows, NSInteger)
I want to reload my UITableView whenever js updates numRows. How do I listen for this?
I don't think that KVO is a good solution.
You can just override setter for numRows property:
- (void)setNumRows:(NSInteger)numRows {
_numRows = numRows;
[self.tableView reloadData];
}
Or you can use RCT_CUSTOM_VIEW_PROPERTY:
RCT_CUSTOM_VIEW_PROPERTY(numRows, NSInteger, RNNativeListview) {
view.numRows = [RCTConvert NSInteger:json];
[view.tableView reloadData];
}
I solved it using an observer.
- (instancetype)initWithBridge:(RCTBridge *)bridge {
[self addObserver:self forKeyPath:#"self.numRows" options:NSKeyValueObservingOptionNew context:nil];
return self;
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
[self.tableView reloadData];
}

How to check Key Value Observing in ObjectiveC for dictionary of arrays?

I have the following code:
#property (strong, nonatomic) NSMutableDictionary *todoSessionDict;
#synthesize todoSessionDict;
[self addObserver:self forKeyPath:#"todoSessionDict" options:NSKeyValueObservingOptionNew context:NULL];
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
}
------------------------
NSMutableArray *unCompletedTodosArr = [NSMutableArray array];
NSMutableArray *completedTodosArr = [NSMutableArray array];
[self.todoSessionDict setObject:unCompletedTodosArr forKey:#"unCompletedTodosArr"];
[self.todoSessionDict setObject:completedTodosArr forKey:#"completedTodosArr"];
Any idea how to check if the #"unCompletedTodosArr" and #"completedTodosArr" values are changed in the self.todoSessionDict using KVO ?
At first, It should be:
[self addObserver:self forKeyPath:#"todoSessionDict.unCompletedTodosArr" options:0 context:nil];
[self addObserver:self forKeyPath:#"todoSessionDict.completedTodosArr" options:0 context:nil];
And for both, the methods:
#pragma mark - KVO
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
// Here your actions depends on the key path...
}
-(void)didChangeValueForKey:(NSString *)key
{
}

how to put condition in selected method annotation mapkit?

I have one method that add selected method for any annotation in my map but I don't want this method working for my annotation location (user location annotation) and I don't know how do it?
this is my code that add select method to any annotation and I want that this method don't working for my user location annotation.
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
NSString *action = (__bridge NSString *)context;
if ([action isEqualToString:ANNOTATION_SELECTED_DESELECTED]) {
BOOL annotationSelected = [[change valueForKey:#"new"] boolValue];
if (annotationSelected) {
NSLog(#"Annotation was selected, do whatever required");
}else {
NSLog(#"Annotation was deselected, do what you must");
}
}
}
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
for (MKAnnotationView *anAnnotationView in views) {
if (!Change) {
[anAnnotationView setCanShowCallout:NO]; //this method is for show popover annotation
[anAnnotationView addObserver:self forKeyPath:#"selected" options:NSKeyValueObservingOptionNew context:(__bridge void *)(ANNOTATION_SELECTED_DESELECTED)];
NSLog(#"%#",anAnnotationView);
}
}
}

AVPlayer Skips the Beginning of a Video

I'm having an issue with AVPlayer skipping the first 0.5 seconds of a video I'm playing when I attempt to play it immediately after pre-rolling.
First, I create the player:
self.videoPlayer = [[AVPlayer alloc] init];
Then, I add the player item to the player and add an observer to check and see when the item is ready:
[self.videoPlayer addObserver:self forKeyPath:#"currentItem" options:0 context:kBLCurrentPlayerItemStatusContext];
[self.videoPlayer replaceCurrentItemWithPlayerItem:self.currentVideoPlayerItem];
When the player item is observed, I will check to see if the player is ready to play. If it's not ready to play, I will add an observer to make sure it's ready to play:
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
...
} else if (context == kBLCurrentPlayerItemStatusContext) {
[self.videoPlayer removeObserver:self forKeyPath:#"currentItem" context:&kBLCurrentPlayerItemStatusContext];
if ([self.videoPlayer status]==AVPlayerStatusReadyToPlay) {
[self prerollVideoPlayer];
} else {
[self.videoPlayer addObserver:self forKeyPath:#"status" options:0 context:&kBLVideoPlayerStatusContext];
}
}
...
When the player status is observed as ready to play, I then preroll the player:
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
...
if (context == kBLVideoPlayerStatusContext) {
if ([self.videoPlayer status] == AVPlayerStatusReadyToPlay) {
[self.videoPlayer removeObserver:self forKeyPath:#"status" context:&kBLVideoPlayerStatusContext];
[self prerollVideoPlayer];
}
}
...
After the pre-roll is complete, I play the player:
-(void)prerollVideoPlayer{
[self.videoPlayer prerollAtRate:1.0 completionHandler:^(BOOL finished){
if (finished) {
[self.videoPlayer play];
}
}];
}
When the player plays in this way, it skips the first ~0.5 seconds of the video. If I don't have the player play immediately when it's finished pre-rolling, and I call the play method later it plays fine. I've checked to make sure all the observers are correctly observed and they occur in the order I've noted above. Is there another observer I need to add or a notification I should check for to avoid this skipping behavior?