OS X Yosemite window style mask NSFullSizeContentViewWindowMask cause only clicked button of collection view can call drawRect - osx-yosemite

My environment is OS X Yosemite 10.10.2.
Xcode are 6.1.1 and 6.2 beta4.
I wrote an calendar app for OS X. I used a cocoa bindings framework that I wrote. And I got
a problem. There should be only one focus day button in the collection view. But something
wrong. The app has multiple focuses.
I found a statement cause this problem.
[[[self view] window] setStyleMask:([[self view] window].styleMask | NSFullSizeContentViewWindowMask)];
When app sets the NSFullSizeContentViewWindowMask, only the clicked button of collection
view will call drawRect because of performance. This caused my problem.
- (void)drawRect:(NSRect)dirtyRect
The related post in Apple developer forum:https://devforums.apple.com/message/1097305#1097305

I found a solution. In the "- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;" of button add "[self setNeedsDisplay:YES
];"
The original tutorial of cocoa bindings, observeValueForKeyPath action has [self
setNeedsDisplay :YES]; But I don't remember that why I commented it. When
NSFullSizeContentViewWindowMask not set, the app just got only one focus.

Related

Changing UITextField in UITableViewCell value does not trigger KVO in iOS 7

I have a UITableView that has cells containing text fields. As the user edits each text field, I need to keep track of the cell's text field value (even when the cell is no longer displayed, so simply tracking the text field does not work). So I used Key-Value Observing and set an observer for each text field in my UITableViewController subclass:
[cell addObserver:self forKeyPath:#"textField.text" options:NSKeyValueObservingOptionNew context:nil];
And save new changes to the text field in the class's observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context method.
This works great in iOS 6, but in iOS 7 KVO isn't called when the user changes the text field value. Apparently the setter method called by pressing "done" on the keyboard doesn't call KVO anymore.
Is there a workaround to this? Or a better way of listening for this change? I need to know what cell the text field belongs to, so implementing the text field's method editingDidEnd doesn't work for me.
Thanks in advance.
I'm not sure about whether there is a workaround for this or not but there surely is a better way of listening for the UITextField text value. If you are creating instances of UITextField programmatically, all you need to do is add an event handler for them to notify your class about the text changing events. For example:
[myTextField addTarget:self action:#selector(editingChanged:) forControlEvents:UIControlEventEditingChanged];
- (void)editingChanged:(UITextField *)sender {
NSString *targetText = sender.text;
}

NSControl subclass shouldn't change firstResponder

I implemented a tabbar view as an NSControl subclass.
When I click it, AppKit will try to update the firstResponder of my NSWindow. Because I don't want the tabbar to become firstResponder (acceptsFirstResponder returns NO) the NSWindow itself will become the firstResponder. My responder chain will consist of the window and it's controller and no Action Messages are delivered to the subview below the tabbar (an NSOutlineView). I'd like the NSOutlineView to keep receiving Action Messages and Events when I click the tabbar.
What's the appropriate way to do this? Is there no way to stop an NSView from trying to change the firstResponder when being clicked on?
I thought about setting the toolbar's nextResponder to the NSOutlineView, but manually changing the nextResponder of an NSView is not recommended by Apple.
I ended up manually resetting the firstResponder to the outline view in my tabbar's delegate method implementation.
An other solution I came up with is implementing this in the tabbar to reset firstResponder to the original object, if the tabbar becomes the firstResponder.
- (void)awakeFromNib {
[self.window addObserver:self
forKeyPath:#"firstResponder"
options:NSKeyValueObservingOptionOld
context:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context {
NSResponder *oldResponder = [change objectForKey:NSKeyValueChangeOldKey];
if (self.window.firstResponder == self) {
[self.window makeFirstResponder:oldResponder];
}
}

How can I debug NSObject observers?

Let's say I've got a Player instance, and I want to add an observer to their score so I can update the score display in my iOS application. I believe I should be calling a method that looks like this to add the observer:
[[self.game player] addObserver:self
forKeyPath:#"score"
options:NSKeyValueObservingOptionNew
context:nil];
In the same class, I then have a method defined that should receive this message:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
However, the breakpoint that I have placed in this method never gets hit.
I would like to know how to diagnose this issue. I have verified that player instance is filled, and when the score is updated, the same instance is updated.
If it helps, I have just converted my project to ARC, but this code above is new and has never worked.
Either your key path "score" is not KVO compliant (are you not defining a #property for *score?) or the adding of the observer method is never being called. You can easily diagnose the latter by placing a breakpoint onto the line of code in your first snippet, and verifying that an observer indeed is being registered.

ToolBar in Navigation Based Application

Since my last post I'm moving ahead. My Navigation Based Application has to contain toolbar at the bottom of UIViewController. I googled a couple of hours and found a lot of regarding stuff.... well at least I've found this page:
http://frog.io/blog/ios-toolbars
Implemented and got my toolbar buckled up. There's only problem that no single bar button item is visible. So, I need two advices:
How to make em visible?
Is this approach correct enough? I mean wouldn't it be rejected by Apple?
Adding a UIToolbar to a UINavigationController based application is actually deceptively easy. Per the UINavigationController Class Reference, there is a built-in UIToolbar, which is hidden by default.
To show the toolbar try this in your UIViewController subclass:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[[self navigationController] setToolbarHidden:NO animated:YES];
}
To add items to the toolbar, you simply use the - (void)setToolbarItems:(NSArray *)toolbarItems animated:(BOOL)animated during - (void)viewDidLoad or similar.
You will need to remember to hide the toolbar during - (void)viewDidDisappear:(BOOL)animated unless you want it to hang around as other UIViewControllers are pushed and popped.

UIScrollView UITextView and camera causing disappearing GUI bug

I have an intermittent bug that is confounding me. Any advice on how to track it down or what might be the cause are greatly appreciated.
I have a "DetailView" with a few labels, an Image View and a Text View. In the navbar I also have a camera button to open an Image Picker and take a picture (later added to the image view). Basic stuff.
Sometimes, when taking a picture and then editing the text: the whole view between the navbar and the keyboard goes blank (to my background color). Happens more often the "first time". Repeating the procedure does not give the same problem. Happens almost only on the 3Gs (very rare on the 3G and the original iPhone).
I have two theories.
1 is that it has something to do with the scroll view that is the container for the disappearing GUI elements. The view hierarchy is: ScrollView -> UIView -> labels, texts and image. Is it a bad thing to have the scrollview as the "main" view?
2 is that it has to do with memory. The 3Gs has a better camera and takes bigger pictures... Possibly something happens if the app gets a low memory warning while taking the picture (not uncommon)?
Are any of these two at all feasible? Any other ideas on what to look for?
thanks
Update:
Could two simultaneous animations cause the bug?
On the KeyboardWillShow notification I resize the ScrollView using the UIView beginAnimations ... commitAnimations and right after that (which happens asynchronously I believe) I also tell the scroll view to scrollRectToVisible for the TextView.
like this:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:animationCurve];
CGRect rect = [[self view] frame];
rect.size.height -= keyboardFrame.size.height * (up? 1 : -1);
[[self view] setFrame: rect];
[UIView commitAnimations];
// Scroll the active text field into view.
DetailView *tempScrollView = (DetailView *) [self view];
CGRect textFieldRect = [comments frame];
[tempScrollView scrollRectToVisible:textFieldRect animated:YES];
The 3GS also has twice the RAM of the 3G/original (256MB vs 128), so I doubt it's memory-related. You can override didReceiveMemoryWarning: to check, though.
When exactly does the view go blank? Does it happen spontaneously, or only when you press a certain button, etc. For example, does it only happen when you start editing the text view (i.e. when the keyboard pops up)? If so, check your view autoresizing masks.
Are the views actually gone, or are they just offscreen? Try printing their frames to the console or using the debugger to check where exactly they should be.
When you find the bug, please post your solution- it sounds like a problem I might encounter some day.
I managed to track it down in the Sim.
Here it goes:
Going to the DetailView
Tapping the camera buttom to "open" the UIImagePickerController (camera or Library, does not matter)
Now I simulate a memory warning before closing the Picker
Choose the image to close the Picker
Tap the UITextView
Under these circumstances the view will receive TWO UIKeyboardWillShowNotification are eachother... so my copied example code for resizing the view is run twise... making it 416px - 216px - 216px = -16px in height... not a good thing.
The reason for the double notifications were of-course that the ViewController added itself as an observer in viewDidLoad... which runs again when the view "appears" after the memory warning... but the ViewController never removed itself as an observer.
Doing that fixed the bug for sure:
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
(void)viewDidUnload {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}