Topbar cannot rotate in landscape view with storyboard - objective-c

I have just converted from .nib files to storyboard, but suddenly the view wont rotate topbar in landscape view. All the settings are "inferred" in my view, and i have not really made any changes since the conversion.
Is this a common problem when upgrading? I have not found any specific info.
And furthermore i do not force any view rotations in my code.
If any more info is needed i can supply anything!
Thanks in advance.
ViewController:
- (void) viewDidLoad {
[super viewDidLoad];
self.view.autoresizingMask = UIViewAutoresizingNone;
self.view.autoresizesSubviews = UIViewAutoresizingNone;
}

I've taken a look at your code and you seem to be missing a method that allows your view controller to rotate freely.
Subclass UIViewController e.g. like this:
// .h file
#interface OrientationAwareViewController : UIViewController
#end
// m.file
#implementation OrientationAwareViewController
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return YES;
}
#end
Then set OrientationAwareViewController in the storyboard as your main view controller's class name. That said, I have no idea how this worked for you when using nibs :) Documentation says clearly:
By default, this method returns YES for the UIInterfaceOrientationPortrait orientation only. If your view controller supports additional orientations, override this method and return YES for all orientations it supports.

Related

NSScrollView how to start from top left corner

How to set scrollView document view to be pinned to top left corner? If scrollView is big enough/bigger than its content, everything is drawn from bottom to up and it not looks right. I have to override isFlipped of scrollView?
I was searching internet and overriding isFlipped to return trueis not everything. I don't want to make my documentView flipped because then I have to make changes in that class to make everything looks like I want.
I created simple NSView class as an container for elements that i want to have inside my scrollView and everything looks perfect. I hope this will help someone!
#interface FlippedView : NSView
#end
and implementation:
#implementation FlippedView
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
// Drawing code here.
}
- (BOOL) isFlipped
{
return YES;
}
#end
Swift 4 Method to invert axises :
from https://stackoverflow.com/a/40381180/5464805 thank's to Ben Leggiero :
import Cocoa
class FlippedView: NSView {
override var isFlipped: Bool { return true }
}
Then in the storyboard, set this class to the NSView below the NSClipView and it do the trick.
However it won't appear in StoryBoard so you'll have to build and run

NSTextView not properly resizing with auto layout

I have a simple layout, which consists of NSView and its subview NSTextView. NSTextView is programmatically filled with some text that spawns multiple lines. I tie everything together using auto-layout (all done programmatically). However, when everything is displayed NSTextView is cut off, only one line is showing.
After searching the web, the best answer I could find was:
Using Autolayout with expanding NSTextViews
However, this only works if I manually change the text in NSTextView after everything is displayed (which is not really my use case). The views are readjusted and the whole NSTextView is displayed.
I am trying to figure out when NSViewController is done with laying out subviews so that I could call invalidateIntrinsicContentSize on the NSTextView. The equivalent of viewDidLayoutSubviews in UIViewController.
Nothing I tried worked so far. I attempted calling invalidateIntrinsicContentSize for NSTextView:
At the end of loadView
After I filled NSTextView with my text
Is there a better way to achieve this?
After further research, found the answer:
Create custom NSView subclass that contains NSTextView
In NSView subclass override layout method that calls invalidateIntrinsicContentSize
Also check out this link that explains subtleties of auto layout and intrinsic content size (among many other things):
http://www.objc.io/issue-3/advanced-auto-layout-toolbox.html
Sample code:
#interface MyView : NSView
#property MyTextView *textView;
#end
#implementation MyView
// init & create content & set constraints
-(void) layout {
[super layout];
[self.textView invalidateIntrinsicContentSize];
}
#end
Implementation of MyTextView:
#implementation MyTextView
- (NSSize) intrinsicContentSize {
NSTextContainer* textContainer = [self textContainer];
NSLayoutManager* layoutManager = [self layoutManager];
[layoutManager ensureLayoutForTextContainer: textContainer];
return [layoutManager usedRectForTextContainer: textContainer].size;
}
- (void) didChangeText {
[super didChangeText];
[self invalidateIntrinsicContentSize];
}
#end

Device Orientation in iOS 6.0 UINavigationController

I have a UINavigationController in UITabbarcontroller. I want to rotate only one view cotnroller inside UINavigationController.
Here is the code snippet I am using.
-(NSUInteger)supportedInterfaceOrientations
{
if (CURRENTDEVICE == IPHONE)
return [self.navigationController supportedInterfaceOrientations] | UIInterfaceOrientationMaskAllButUpsideDown;
else
return UIInterfaceOrientationMaskAll;
}
-(BOOL)shouldAutorotate {
return YES;
}
I have a category on UINavigationController as well:
#import "UINavigationController+autorotate.h"
#implementation UINavigationController (autorotate)
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
#end
I am not sure how to implement it.
you can hard code it with cgrect. here is a link to another question that might help you. there is a nice example of hard coding two different views for rotation in there, but i don't recomend it personally. anyhow i thought that might point you to the right direction.
https://stackoverflow.com/questions/12867792/ios-rotation-causing-views-to-displace-shift-forcing-me-to-use-non-sensical-har
there is a set of codes in that question that might get you started. you also have an option in starboard( if you are using storyboard) to set rotations in IB which is much easier.
hope this helps
adrian
In your category in the supportedInterfaceOrientations implementation, you could check for the topViewController. You can use kindOfClass: method to work out which class it is... Then return a different orientation from the default of your navigation.
You could also subclass UINavigationController, and do this check the same way. Subclassing the navigation controller isn't recommended until, iOS 6, the documentation still states this but Apple engineers have told me that with the new rotation logic, you can subclass the UINavigationController.

Why am I seeing a black screen? Did I not alloc something?

In xcode, this is one of the views I have created:
If I run the program in the simulator, I can see this view fine. However, if I create a UIViewController class and hook it up with this view (I confirmed this view is a UIViewController), this is what I get in the simulator:
Why do I get this blank screen? How can I get the screen that looks like the first image?
Edit: code
#import "EnterLevelViewController.h"
#interface EnterLevelViewController ()
#end
#implementation EnterLevelViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)loadView
{
// Implement loadView to create a view hierarchy programmatically, without using a nib.
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
It appears from your code that you have uncommented the -(void)loadView method from the view controller, which is provided in the template. When you do this, the controller will try to construct the view programmatically, instead of using the nib (storyboard). Remove the empty method completely and see if that helps.
just drag from the tabBarController to the new ViewController in the storyboard and when you let go, press the selection for relationship ViewController.
Here is a quick example of how to set it up with three tabs, one with your view:
https://github.com/HubertK/TabBar_Example
The storyboard that was part of your project at the outset already included a view controller and its associated view. You can see it in the storyboard image that you posted -- it's the icon at the bottom with the light gray background. That view controller was set up as the root view controller, and the code that came as part of the project template loaded that view controller and its view. That's what you were seeing in the simulator. When you added another view controller, you must have configured it as the root controller instead. Since it doesn't have a view connected to it (or if it does, the view is empty), you no longer see anything.

Cocoa-Touch internals: How does the view know its controller?

If you add a subview to a view or add a view to a window, how does iOS know which controller this view belongs too?
Easy example:
Have a UIView without UIViewController and add it to the window [window addSubView:myView] --> it will not rotate.
Now use a UIViewController, have it implement shouldAutoRotateToInterfaceOrientation: and add the controller's view to the window: [window addSubView:myController.view] --> magically, the view will adjust to interface orientation.
But look at the code: in both cases a UIView was added. How can iOS possibly be aware that in the second case a UIViewController was involved?
I'm interested in how this is done internally. My best guess is that UIViewController.view is a setter which adds the controller to an internal array of controllers or assigns itself to some internal variable which holds the currently active controller.
Simple. Look in UIView.h. It's right there. Each UIView has a pointer back to a UIViewController (which is apparently referred to as the "viewDelegate").
Dave DeLong is correct (and gets +1) as it is clearly defined UIView.h as #package so anything in UIKit can access it.
Here is an example of accessing that variable for educational purposes only (obviously you will not do this in a real application).
SomeAppDelegate.m
#synthesize navigationController=_navigationController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
// Add the navigation controller's view to the window and display.
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
//DO NOT TRY THIS AT HOME
UIView *mynavview = self.navigationController.view;
//Guaranteed _viewDelegate atleast in iOS 4.3
Ivar ivar = class_getInstanceVariable([UIView class], "_viewDelegate");
UIViewController *controller = object_getIvar(mynavview, ivar);
NSLog(#"controller = self.navigationController? %#", controller == self.navigationController ? #"Yes" : #"No");
return YES;
}
UIViewController has a private class method (called controllerForView:, I believe) which is used to find the view's controller. Internally, there is probably a table used to connect the two together, and this method simply finds the proper location in that table and returns its value. When the result is nil, the default implementation will be used (don't rotate).
If you want to be sure about the name of the method, set a breakpoint in -[UIView becomeFirstResponder], tap on a text field, and step through the code until it shows up in the call stack. I suggest using becomeFirstResponder because it is easier to control than most things which get the view controller.