I've got a set of UITextFields which are enabled or disabled based on an if function (basically only allows 2 to be filled in, then the others are disabled).
I've got 2 methods to fade the background of the UItextFieldFade in and Fade out.
I want the animation to run every time the enabled property of the UITextField changes but don't really know how to track the actual change.
Any help would be great.
Thanks
Add an observer to the text field:
[_textField addObserver: self forKeyPath: #"enabled" options: NSKeyValueObservingOptionNew context:NULL];
You should implement this method:
- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *) context;
Where you handle the value change of the "enabled" property.
Documentation: Key value observing.
Related
I have an observer on a UITextView to detect if its content size is changing:
[_textView addObserver:self forKeyPath:#"contentSize" options:NSKeyValueObservingOptionNew context:NULL];
This code always worked to call the following function, where I do resizing of the UITextView:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
However, in iOS 9, this function is never getting called. What changed in iOS 9 and how do I fix this?
If you do a search for UIKit and KVO Compliance you will see that everyone says you can't rely on it. See this question and this question.
I don't know what changed, but I think you should just subclass UITextView and overload setContentSize: if you want to know when it changes.
I really need your help here. I have a UITextView in a UiCollectionViewCell. The problem i am facing here is when i select the cell to edit it , neither the textview methods nor the collectionview methods are called. For ex. neither the didSelectItemAtIndexPath nor the textViewDidBeginEditing methods are invoked.
As a result, I am not able to capture the edits made by the user the cell and save it .
Any inputs would be highly appreciated.
Thanks
I had faced similar problem in custom cell what i did was I had added following code to capture the events
[textField addObserver:self forKeyPath:#"contentSize" options:(NSKeyValueObservingOptionNew) context:NULL];
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
UITextView *tv = object;
//Your code using tv
}
I have code that does different logic based on which camera is used such as:
if(aPickerInstance.cameraDevice == UIImagePickerControllerCameraDeviceFront){
// Front camera logic
}else{
// Rear camera logic
}
My issue is that when the switch occurs, front-to-rear or vice versa, I have found no way to tell when the "cameraDevice" property value has changed in order to reevaluate my states. (basically rerun logic blocks to set everything right for the newly selected camera).
When you create your picker, add an observer:
[_picker addObserver:self forKeyPath:#"cameraDevice" options:NSKeyValueObservingOptionNew context:nil];
Then add the handler:
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
NSLog(#"Keypath %# change %#", keyPath, change);
}
change[#"new"] will give you a new value for cameraDevice. You can also just use this to detect a change and trigger your own cameraDevice state check.
I have a container view that holds a view controller. I need to set a non-UI property in this view controller before awakeFromNib is called. However, the prepareForSegue method for the embed segue isn't called until after awakeFromNib happens.
Is there any way to pass this information to the contained view controller before awakeFromNib?
I have a similar issue in one of my apps.
Basically, I have a ViewController that has a property for the data model, but I am never sure when in my lifecycle the data model is actually set. My solution was to use Key-Value Observing to receive a callback when it's set.
Somewhere before the value can be set:
[self addObserver:self forKeyPath:#"propertyName" options: 0 context: nil];
Callback:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:#"propertyName"]) {
//do something
}
}
remember to unregister (I do it in my dealloc)
[self removeObserver:self forKeyPath:#"propertyName"];
I have a view controller with a view that changes (for example), and I would like to observe the frame of any view that self.view is set to.
Is there any difference between:
[self.view addObserver:self forKeyPath:#"frame" options:0 context:nil];
and
[self addObserver:self forKeyPath:#"view.frame" options:0 context:nil];
For the second one, if the view changes will messages still be recieved when the new view's frame changes, or will it only send messages if the frame of the view that was set when the observer was added?
Is there any way to observe changes to the frame property even if the view of the view controller changes after adding the observer?
Use the second path. #"view.frame" will notify you about the frame changes even when the "view" itself is changed. Cocoa will add observers for every object in the keyPath "chain" for you automatically (which means every item in the keyPath must be KVO-compatible).
You asked if there is a difference between the two, The answer is yes, there is a difference between them:
The first one
says "me as a view", I add an observer named self (aka) viewControllerObject, if you invoked this in viewController.m whenever my property named "frame" is changed.
The Second one
Says "me as ViewController" I'm adding myselfAsAnObserver whenever theKeyPath named "view.frame" is changed.
Since every observer should implement
-(void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
For this case you won't notice much difference because you added a viewController as an observer in either of the method above, but it will make a difference when you are dealing with different objects. But the rule is simple, each added observer should implement the
-(void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
One more thing:
Its a good idea to create a context for observation
e.g
//In MyViewController.m
//..
static int observingViewFrameContext
// In ...
[self addObserver:self
forKeyPath:#"view.frame"
options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
context:&observingViewFrameContext];
// .. don' forget to remove an observer ! too