I'm running into a problem with a detached UIPopovercontroller and am hoping someone has seen this behavior before.
My app runs in Landscape mode and offers a number of popover elements using the presentPopoverFromRect call. Some are launched from within the top view while others are presented from a view buried deep in the display. The popovers seem to work fine if the popover is presented from the upper 2/3rds of the iPad's display however when attempting to launch a popover from the bottom 1/3 of the display the popover is displayed detached from the UIButton. The x coordinate appears to be correct, however the y coordinate of the popover tends to be in the middle or top of the iPad screen.
I've played around with presenting the popover using a fixed position by creating a CGRect object in the lower 1/3 of the display but when the iPad renders the popover it either renders the popover in the upper 2/3rd of the view or the very bottom of the screen (if I force the CGRect value to a large y value).
At this point I'm out of ideas and hoping someone on the forum has seen this or can make suggestions as to what to try.
Thanks for any and all help,
Wes
I was able to fix my issue and thought that I'd share my solution incase someone else has the same problem.
The solution was to add a call to set the popover size BEFORE calling presentPopoverFromRect.
[mySettingsPopoverController setPopoverContentSize:CGSizeMake(320, 320) animated:YES];
[mySettingsPopoverController presentPopoverFromRect:sender.frame inView:self.navigationButtonsView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
Before, I wasn't setting the popover content size prior to presenting the popover. In the viewDidAppear method of the viewcontroller of the popover I was resizing the popover to size to the tableview in the popover. Apparently by not setting the popovercontentsize before presenting the popover you get undefined behavior including the possibility of having the popover detach from the element that it is suppose to be attached to.
Wes
Related
I have an NStableView embedded in an NSSplitview.
The table will display, but when it does, the first three or so rows are not visible until I reize the window and/or split view. Then, it will snap into place and function perfectly fine until I quit.
Has this ever happened to anyone? Is there a simple method I can call on the view or table to get it to redraw?
This is how it displays when the view is first loaded (note: the user can scroll the table up and see the top row highlighted, but never get to it)
after resizing the window, the table view suddenly snaps into place and appears as it should:
You could try a [_yourSplitView display] to force a redraw of the NSSplitView. If I remeber correctly the SplitView will redraw all its subviews.
Try experimenting with where you use this, as result may vary depending on where in the init order you call this.
I actually got this working by calling the subview and then just resetting the position of the splitview divider.
NSView *v = [vc view];
[self.superDisplayView addSubview:v];
[self.SourceListSplitView setPosition:250 ofDividerAtIndex:0];
I' ran into an absolutely weird kind of problem I don't have a clue yet how to fix it, having been working on this without a break (except for eating, sleeping, drinking coffee and smoking) for almost two days now.
What I have:
I've got an UIScrollView inside my view controller, containing a certain number of textfields and a UICollectionView. With a button, I open another view controller for adding new data to the collection view. Back to my first view controller after the new data items have been added, I call invalidateIntrinsicContentsize on my UIScrollView and on my UICollectionView to resize them both to fit their content (I use Autolayout and let both of them hug their content). On both views I've implemented these methods to nicely fit their content, and this part works perfectly fine.
What my problem is:
If I add data to the UICollectionView in the way just described, and if I'm in landscape mode, the problems start: After getting back to my initial view controller and updating the intrinsic content sizes, the content of my UICollectionView is displaced - displaced in such a way, that the scrolling position of the content inside the UIScrollView before switching to the data-adding view now becomes something like a fixed content offset. If I scroll up now, I can reach at maximum that position of the content where it has been - by getting scrolled to - before I switched to the data-adding view controller.
Pictures (everyone loves that):
To illustrate that situation somehow difficult to explain, I appended two pictures. Red is the entire content area of the scroll view, dark green is the content, where both overlap the color is olive. The visible part of the UIScrollView is shown in the highlighted, bordered area.
Before updating the data, content is where it should be:
(source: grubbrother.com)
After updating the data and updating UI, content is displaced by former scroll position / contentOffset:
(source: grubbrother.com)
Please help me with this weird stuff. Unfortunately, I've got a tight deadline and need to move on with the project. Nevertheless I really don't know how to solve this or even what might cause it - I have absolutely no clue.
Despite I couldn't find out yet what causes the problem described in my question, I found a hack around it that at least somehow fixes the symptoms:
As I describe above, the unwanted content displacement that occurs when switching back to the UIViewController containg the buggy UIScrollView is equal to the contentOffset of the UIscrollView before switching to another scene.
Knowing this, I set the contentOffset to zero after my UIViewController disappears.
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[self.scrollView setContentOffset: CGPointZero];
}
When the view reappears, I scroll down to the newly added content at the bottom of the UIScrollView in question:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if (self.appearedFromActorsAdding)
{
[self.scrollView setContentOffset:CGPointMake(0, self.scrollView.contentSize.height - self.scrollView.frame.size.height) animated:YES];
}
}
Hope this helps anyone running into the same problem.
I'm placing a few buttons in a simple rectangular NSview which acts as a custom toolbar. On first render the buttons/views come out as expected, but every time a button is pressed (and sometimes with no mouse interaction at all) artefacts start appearing.
Before
After
I can eliminate the artefacts by calling a [self.toolbarView setNeedsDisplay:YES] in all the action and focus methods but this seems like a hack, is there any clean way to deal with this?
It was a beginner's problem. In the drawRect method
- (void)drawRect:(NSRect)dirtyRect
I was using the param dirtyRect for drawing an outline of my view, assuming it was the view's bounds, where in fact it was only the area around the buttons that became dirty when they were pressed. The 'artefacts' were actually my outline being drawn in the wrong place.
By correctly using the bounds of the view
NSRect drawingRect = [self bounds];
the 'artefacts' no longer appeared.
You just try to set focus ring for a buttons to 'none' in IB.
In my app i have UIView that floats at the top of a UITableView (Visualise:Attached to the bottom of the navigation Bar), under iOS5 i was enabling it to float at the top using these lines of code in scrollViewDidScroll
// get the table and buttonView bounds
CGRect tableBounds = self.tableView.bounds;
CGRect buttonViewFrame = self.buttonView.frame;
// make sure the buttonView at the table's original x and y as the content moves
self.buttonView.frame = CGRectMake(tableBounds.origin.x,tableBounds.origin.y,buttonViewFrame.size.width,buttonViewFrame.size.height);
This however no longer seems to work in iOS6, does anyone know why or how to fix the problem? I'm supporting iOS5 and above.
Having looked through the iOS6 release notes i found this...
Note that you can make a subview of the scroll view appear to float (not scroll) over the other scrolling content by creating constraints between the view and a view outside the scroll view’s subtree, such as the scroll view’s superview.
How would I set this up in code as Im not using AutoLayout in storyboards as I'm still supporting iOS5. It would also be great if anyone can enlighten me as to why the code i was using in iOS5 no longer works in 6.
I have an NSView in IB which sits above the app window. I have a subclass of NSView (AddSource) which I assign to the NSView.
On awakeFromNib I instantiate the view:
//add a new Add Source class
addSourceView = [[AddSource alloc] initWithFrame:NSMakeRect(0.0, 959.0, 307.0, 118.0)];
[[winMain contentView] addSubview:addSourceView];
in addSourceView's drawRect method I am adding a white background to the view:
[[NSColor whiteColor] set];
NSRectFill(rect);
[self setNeedsDisplay:YES];//added this to see if it might solve the problem
In winMain's contentView I have a NSButton that when clicked slides the addSourceView onto the window:
NSRect addSourceViewFrame = [addSourceView frame];
addSourceViewFrame.origin.y = 841.0;
[[addSourceView animator] setFrame:addSourceViewFrame];
But it seems as if the app is painting over the IBOutlets I placed on the NSView in IB. If, in IB, I repoistion the NSView so that it is on screen when the app launches everything works fine, the IBOutlets are there as well as the background color.
I'm not sure why this is happening. I've done this before with no problems. I must be doing something different this time.
Thanks for any help.
*note - on the 3rd screen capture, when I say this is what the app looks like when opened, that's when I hard code the Y position of the NSView. When it is functioning correctly it should open as screen capture 1.
Most likely your buttons and custom view are siblings, i.e. they are both subviews of your window's content view. Since siblings are "Stacked" depending on the order in which they are added, when you add the view in code it is being added on top of the buttons. You should be able to fix it by explicitly specifying where the view should be positioned relative to its new siblings like so:
[[winMain contentView] addSubview:addSourceView positioned:NSWindowBelow relativeTo:nil];
which should place it below any existing subviews of your window's content view. Also, remove the setNeedsDisplay: line in drawRect, that leads to unncessary, possibly infinite, redrawing.
EDIT: OK I see what you're doing.
I would suggest creating a standalove view in the NIB by dragging a "Custom View" object into the left hand side (the vertically-aligned archived objects section) and adding your controls there, that should ensure the controls are actualy subviews of the view, then you can just create a reference to the archived view in code, and add/remove it dynamically as needed.
Honestly though, you should probably be using a sheet for these kinds of modal dialogs. Why reinvent the wheel, and make your app uglier in the process?
You added TWO AddSource views to the window. You added one in IB - this view contains your textFields and buttons that are connected to the IBOutlets and it is positioned outside the window.
Then in -awakeFromNib you create another, blank AddSource view (containing nothing) and animate it into the window.
I can't recommend highly enough the Hillegass as the best introduction to IB and the correct way to build Cocoa Apps.
Also, Assertions can be useful to make sure what you think is happening is actually what is happening.
If you are certain you added a button to your view in IB, assert it is so:-
- (void)awakeFromNib {
NSAssert( myButton, #"did i hook up the outlet?");
}
NSAssert is a macro that has zero overhead in a release build.
Calling [self setNeedsDisplay:YES] from -drawRect just causes the same -drawRect to be called again. This will give you big problems.