NSWindow not resizing to fit NSView - SOMETIMES? - objective-c

I'm having trouble resizing an NSWindow to fit an NSView. It must be a logic error as it works but not for one action.
I have one NSWindow which is empty, and 3 NSViews with components and are different sizes.
With the following code I resize the NSWindow to fit the NSView and display it:
[_window setContentSize:_mainView.frame.size];
[_window setContentView:_mainView];
This code works fine.
However in one NSView I have a Back button, and while this displays the correct NSView in the NSWindow, it does not re-size it back. As an example the initial window is a certain size, I click to switch to another view and it resizes correctly, I press the back button, the NSView is displayed but the window stays the same size?
Can anyone explain to me why when I switch back to the original NSView, it doesn't resize the NSWindow?
Thanks in advance everyone. This is the complete code I have:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[_window setContentSize:_mainView.frame.size];
[_window setContentView:_mainView];
}
- (IBAction)switchSubtractionView:(id)sender {
[_window setContentSize:_subtractionView.frame.size];
[_window setContentView:_subtractionView];
}
- (IBAction)switchAdditionView:(id)sender {
[_window setContentSize:_additionView.frame.size];
[_window setContentView:_additionView];
}
// -----------------------------------------------------------------------
// THE FOLLOWING METHOD DISPLAYS THE NEW VIEW CORRECTLY BUT DOESN'T RESIZE
// -----------------------------------------------------------------------
- (IBAction)switchMainMenu:(id)sender {
[_window setContentSize:_mainView.frame.size];
[_window setContentView:_mainView];
}
Thanks in advance everyone.
EDIT: it seems to me that when getting VIEW.frame.size, if this is repeatedly used, it loses its values? This seems very strange behaviour to me?

A window's content view must always be sized to fill the window's content area. Therefore, when you set the window's content size, you effectively change the size of the current content view. This happens just before you switch the content view, so you are changing the size of the old view.
Try setting the content view to a new, disposable NSView before changing the content size, and then setting the new content view.

Related

Auto-resizing window

I'd like to embed a Tabbar or a TabViewController using a container into a ViewController of a Window for a macOS App. The two ViewControllers of the Tabbar / TabVC should have different heights, a tall one and a small/flat one.
The point is, that I'd like to automatically resize the whole window height when the Tabbar / TabVC changes its ViewController. This way the window is always as small as possible and doesn't show any unused and empty space.
This is my current storyboard, which (of course) doesn't resize the windows:
Does anybody have a hint, how to automatically resize the window according to the size of the selected ViewController in the Tabbar or TabVC?
Try setting the preferredContentSize in viewWillAppear like:
- (void) viewWillAppear
{
[super viewWillAppear];
self.preferredContentSize = CGSizeMake(self.view.fittingSize.width, 194);
}
You can also use self.preferredContentSize = self.view.fittingSize; if that works for you.
But I'm not sure if this will animate the change for you.

Custom UIActivity ViewController Background Image Transparency Doesn't Work

- (UIViewController *)activityViewController
I created a custom UIACtivity that returns a view controller that displays a popup. This allows the user to do some editing before performing the actual activity.
With ios below 8, my background with transparency that looks like an overlay works (I can see my game underneath) but after updating to ios8, the background becomes solid color gray. I checked the UIImageView displaying my overlay image with alpha and it is set to clear. Can someone tell me why the background suddenly becomes solid? I couldn't see the view of my game underneath anymore.
Here's my code:
- (IBAction)didPressShareButton:(id)sender
{
...
[_rootViewController presentViewController:[self getActivityViewController] animated:YES completion:nil];
...
}
The _rootViewController is the main view controller of my application.
The [self getActivityViewController] returns an instance of UIActivityViewController which includes my custom UIActivity for instagram
My InstagramUIActivity overrides this function to return a custom viewcontroller (see attached image)
- (UIViewController *)activityViewController
{
dismissalAC = [[InstagramDismissal alloc]init];
presentationAC = [[InstagramPresentation alloc]init];
instagramVC = [[InstagramViewController alloc]initWithInstagramPhoto:_instagramPhoto];
instagramVC.delegate = self;
if ([instagramVC respondsToSelector:#selector(setTransitioningDelegate:)]) {
instagramVC.transitioningDelegate = self;
}
return instagramVC;
}
dismissalAC and presentationAC are just objects that implement the UIViewControllerAnimatedTransitioning protocol so I could have my own transition animation.
When I return my custom view controller, it pops up but along with it is a view with white background. I don't know why.
try
instagramVC.modalPresentationStyle = UIModalPresentationOverFullScreen;
or
instagramVC.modalPresentationStyle = UIModalPresentationOverCurrentContext;
I encountered this problem in my apps too.
Since iOS 8, Apple forbids subclassing nor customizing the subviews of an UIActivityViewController.
If you did so on your app, the app shows an overlay over your view and an empty gray list without any buttons. In this case, you must kill your app to dismiss the UIActivityViewController.
To replace this behavior, I simply creating a view (either programmatically or from storyboard) with the same layout and you can make it appear from bottom of the screen (with an animation). Ask me some example code if needed.

iOS7 - Setting selectedIndex of UITabBarController breaks touch events along right-hand edge of screen?

I've hit a weird problem with UITabBarController on iOS7 and can't seem to find a workaround, so any help would be welcome!
Scenario:
Navigation-based app using landscape orientation on iPad.
App consists of a main view, and a second view which is a UITabBarController.
TabBarController has two tabs.
First view has two buttons - each button performs a segue to the tab bar controller and sets a different tab as selected. (i.e. button1 selects the first tab, and button2 selects the second tab).
Setting the tab is done in prepareForSegue by calling setSelectedIndex on the tab bar controller.
Outcome:
On iOS 7 I am finding that the view shown in the tab bar controller fails to register any touch events along the right-hand edge of the view! So in the storyboard shown above, the UISwitch on the right side of the screen cannot be tapped.
I've even attached a tap gesture recognizer to the views and used it to log the area of the screen that can be touched - it seems to register touch events up to about x=770 points across. The remaining 1/4 of the screen is 'untouchable'!
After the segue, if you manually switch to the other tab and switch back again, the touch events are 'fixed' and the full view responds to touches again.
This doesn't seem to be a problem on iOS 5 / 6.
Any help much appreciated as to:
What is causing this to happen in the first place (iOS7 bug / change?)
How else can I work around this? I've tried calling setSelectedViewController as well as using setSelectedIndex and this seems to be the same.
Thanks in advance.
I ended up raising this with Developer Tech Support, and it looks like a bug. This is the response I got back from Apple:
The container view that the tab bar controller sets up to contain your view controller is not being resized to account for the interface being in landscape orientation. It's dimensions at the time your view controller is displayed are 768 (width) x 1024 (height).
The view hierarchy looks like this when the selected tab's view is displayed:
UIWindow
/* Navigation Controller */
UILayoutContainerView
UINavigationTransitionView
UIViewControllerWrapperView
/* Tab bar controller */
UILayoutContainerView
UITransitionView
UIViewControllerWrapperView <-- Incorrectly sized.
/* MyViewController */
MyViewController.view
The incorrect size of UIViewControllerWrapperView does not cause a display problem because subviews are still displayed even if they are outside their superview's bounds. However, event routing is much more strict. Events on the right quarter of the screen are never routed to your view controller's view because the hit test fails at the wrongly-sized UIViewControllerWrapperView where the event falls outside UIViewControllerWrapperView's bounds.
As a workaround, I subclassed UITabBarController, and added the following in viewWillAppear:
#implementation FixedIOS7TabBarController
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// Fix the frame of the UIViewControllerWrapperView
self.selectedViewController.view.superview.frame = self.view.bounds;
}
#end
Hope that helps someone else....
As explained in this answer,
The container view that the tab bar controller sets up to contain your
view controller is not being resized to account for the interface
being in landscape orientation. Its dimensions at the time your view
controller is displayed are 768 (width) x 1024 (height).
I was encountering this problem when the TabBarController was originally displayed in portrait mode. When the device was rotated into landscape mode, the view was unresponsive on the right hand side.
The solution proposed in that answer did not work for me, because viewWillAppear: is invoked only once. However, viewDidLayoutSubvews is invoked whenever the view changes, including rotations, so my solution was to subclass UITabBarController and perform the workaround in viewDidLayoutSubvews:
#implementation FixedIOS7TabBarController
- (void)viewDidLayoutSubviews
{
// fix for iOS7 bug in UITabBarController
self.selectedViewController.view.superview.frame = self.view.bounds;
}
#end
End up finding a workaround here:
self.view.autoresizesSubviews = YES;
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
Right answer don't worked for me, cause user can change orientation; And it still not touchable in some area when change orientation.
So I create my own solution, I don't sure that is normal solution.
#implementation FixedIOS7TabBarController
- (UIView*)findInSubview:(UIView*)view className:(NSString*)className
{
for(UIView* v in view.subviews){
if([NSStringFromClass(v.class) isEqualToString:className])
return v;
UIView* finded = [self findInSubview:v className:className];
if(finded)
return finded;
}
return nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
UIView* wraperView = [self findInSubview:self.view className:#"UIViewControllerWrapperView"];
wraperView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}
#end
Works perfectly for me!
In the list of view controllers on the left hand side navigate to the views/view controllers affected, drag the view to underneath the first responder so that it is disassociated to the view controller's view.
Then go to the layout tab on the right hand side, select all 4 anchors and both sets of resizing arrows (horizontal + vertical).
Then drag the view back to where it was originally (just below the view controller).

Changing view repositions them at (0,0)

I created a simple window with the purpose of being something like a "Wizard" (I know Apple guidelines basically forbid you to, I tried to convince the customer, but whatever.
It is just a simple view with two Custom Views inside, one in the bottom part which contains a "previous" and "next" button, and a bigger view at the top which takes most of the space.
I called the bottom view "NavigationView" and the top one "ContainerView".
I created an array to hold a series of views the user is supposed to navigate through with the "next" and "previous" buttons.
So, here's my code.
- (IBAction) next:(id)sender{
currentViewIndex++;
[self animatePushView:YES];
}
- (IBAction)previous:(id)sender{
currentViewIndex--;
[self animatePushView:NO];
}
- (void) animatePushView:(BOOL)forward{
NSView *nextView = [viewCollection objectAtIndex:currentViewIndex];
for (NSView *subView in [containerView subviews]) {
[subView removeFromSuperview];
}
[containerView addSubview:nextView];
[nextView setFrame:containerView.bounds];
[containerView setNeedsDisplay:YES];
}
It's pretty straightforward I think. I have an array which contains the next view to be displayed.
What happens is that I find the next view centered in the lower left part of the ContainerView. Why does this happen?
Also, as you may have guessed, I'm a newbie at managing views, even though I've been working on objective-c for quite some time, so if there's some best practice I'm missing I'm open to suggestions.
Thanks!
EDIT:
I forgot to add:
Some of these views have different sizes, and I would like to be able to change the window size according to the view size.
[nextView setFrame:containerView.bounds];
You are assigning container view bounds to the next view frame (doc).
What you probably want is assigning the current view frame to the next view frame, and possibly adjust width and height.
Keep a reference to the current displayed view, something like this (_currentView is an ivar of type NSView *) :
- (IBAction) next:(id)sender{
currentViewIndex++;
[self animatePushView:YES];
}
- (IBAction)previous:(id)sender{
currentViewIndex--;
[self animatePushView:NO];
}
- (void) animatePushView:(BOOL)forward{
NSView *nextView = [viewCollection objectAtIndex:currentViewIndex];
[nextView setFrame:_currentView.frame];
[_currentView removeFromSuperview]; // _currentView is retained in the collection
[containerView addSubview:nextView];
_currentView = nextView;
[containerView setNeedsDisplay:YES];
}
Ok, I figured it out.. Finally..
The problem was that the first view I had to show was already contained in the container view in the .xib file.
I don't really know why, but it probably caused some problem with the retain count of the container view, because it was released on the first click.
Releasing the container view would reposition the view on (0,0) probably because its frame was null, and the view would flash because it wasn't retained correctly.
Removing the view from the .xib file and adding it via code works properly anyway.

UIScrollView not scrolling in xcode 4?

For some reason UIScrollView is not working. It did work before I add the content but after it stop working. I'm stuck can someone help me out!
Here is my code
This is the code for my UIScrollView
#interface EditAccountViewController : UIViewController {
IBOutlet UIScrollView *svScroller;
}
Here is my view Load code
- (void)viewDidLoad
{
[super viewDidLoad];
[svScroller setScrollEnabled:YES];
[svScroller setContentSize:CGSizeMake(320, 930)];
}
Here is my objects view
View
Scroll View
Image View
View
View
Toolbar
It works also with that.
To my understanding "autolayout" set constraint after loading the view so the problem could be that you set your constrains on viewDidLoad and just after that "autolayout" changes that. Try to set this constrains on viewDidAppear.
Get it from: scrollview xcode4.5 autolayout. Thanks.
Always keep in mind that the content view needs to be larger than the UIScrollView instance frame size. If it isn't, it will not enable scrolling.
This applies to UITableView as well. The scrolling for UITableView will not appear unless there are more rows to be displayed than actually are.
I resolved the issue. I just bump the height in [svScroller setContentSize:CGSizeMake(320, 1500)]; and It's working fine.