Landscape mode without a ViewController - objective-c

I have a project based on a window-template, so it doesn't have a viewController. Now I'm trying to make this work in landscape only, and I have set the "supported device orientations" to "Landscape (right home button)" only, just the way I want it. The app actually launches in Landscape mode, but when I want to show an image which is btw a landscape-fullscreen one, iOS draws it in Portrait mode, cutting off what doesn't fit. Well I know the option of implementing a ViewController and editing the "shouldAutorotate..." method, but I want to do it without.
I have one solution in my mind, but I'm not sure whether it#s such a great idea: Rotate the whole coordinate-system on app-startup manually using "CGTransform..."

Down that path lies madness. Just because the template doesn't include a built-in UIViewController doesn't mean you can't add one yourself.
Add one, and save yourself a bazillion headaches.
From a more technical standpoint, a lot a UIKit expects the window to have a UIViewController, and not having one means you can lose out on a whole lot of behavior that you would otherwise get for free.

Related

Using an AVPlayerLayer as the backing layer for an NSView

I'm trying to create a view hierarchy similar to what you'd expect in a media playback viewer like the QuickTime Player:
+ Host View
+ Video Controls (NSView layer-backed)
+ Video View (NSView layer-hosted)
+ AVPlayerLayer
Since layer-hosted views cannot contain subviews, the video controls view is a sibling of the video view and simply ordered-front so that it's on top of the video view.
This current view hierarchy appears to be working fine for me, but I remain a bit confused over whether it's officially "supported" because of the overlapping, sibling views (the video controls view always overlaps the video view).
This Stack Overflow question: Is there a proper way to handle overlapping NSView siblings? offers conflicting information regarding overlapping sibling views.
I would assume the more 'correct' way to handle this is for the video controls to be a subview of the video view, which is only possible of I change the video view from being a layer-hosted view to a layer-backed view.
By default a layer-backed view uses a basic CALayer as its backing store, but NSView exposes makeBackingLayer to allow you to return a custom layer such as an AVPlayerLayer.
By doing that, and moving the controls view to be a subview of this layer-backed video view, things also appear to work properly but now there's an AVPlayer object that is directly modifying the contents of the AVPlayerLayer. That seems to be contrary to the requirement that in a layer-backed view, you should never modify the contents of the layer without going through the NSView using something like drawRect or updateLayer.
This seems to leave me with two choices, neither of which appears 'correct' based on my interpretation of the document:
Option 1:
Layer-hosted view for the AVPlayerLayer
Overlapping sibling view for the controls view.
Option 2:
Layer-back view with an AVPlayerLayer via makeBackingLayer
AVPlayer that directly modifies the contents of the AVPlayerLayer
Controls view as a subview of the video view
I'm inclined to think that option #2 is the more correct way and that in this scenario, it's OK for the AVPlayer to directly modify the contents of the AVPlayerLayer even though it's in a layer-backed view, but I'm not certain and would be curious if others have any thoughts or experiences with a setup like this.
Apple has some old (ancient in computer terms, 2007!) code that doesn't even compile in Xcode 6 without some tweaks. It shows some controls that are overlaying a QuickTime movie layer. Download it here: https://developer.apple.com/library/mac/samplecode/CoreAnimationQuickTimeLayer/Introduction/Intro.html .
It's hard to say that just because they provided source code that it's considered a best practice, but I would suggest you just build it the way you think is best. This is not one of those areas so heavily developed on that a best practice is likely to exist. For me personally it makes the most sense to use overlapping sibling views as to ensure that you don't mess with the video rendering. Whether that's the right way or not is probably somewhat subjective. You can maybe access one of the old quicktime developers mailing lists or even ask on the Apple developer forums. At the end of the day though you should probably just stick with the method that makes the most sense to you since you're likely to be the one to maintain or build upon it in the future.

Cocoa: Update views outside NSWindow's content view during live window resizing?

I have a standard NSWindow with a toolbar. One of the toolbar's items is a custom view -- specifically, an NSTextField. (More specifically, it's a timer app -- the timer's controls as well as the digital display are all within the toolbar, with other stuff in the window's content area. The NSTextField is the digital display.)
Ordinarily, I just update the timer every second by changing the 'stringValue' property of the NSTextField, which causes it to update itself. But during a live window resize, even though the code that updates the 'stringValue' property is running (which I have verified with NSLog), the NSTextField doesn't draw itself again until the window resizing is done. Meanwhile, the stuff inside the content area is updating itself just fine.
I've tried all the ways I know to tell the NSTextField to draw itself, but it just refuses to happen until the live resize is done. Any ideas? Obviously it must be possible somehow, as the toolbar gets resized along with the rest of the window -- so you'd think it would be possible to force it to redraw one or more of its subviews as it is moving them around. I'm assuming I can hack this together by subclassing something, but my Cocoa-fu is not yet strong enough to figure out the easiest/most proper way to do so.
Thanks in advance...
EDIT: I kind of figured out a solution -- it's not great but it mostly works for now. It's in my comments below.
Just invoke -[NSWindow displayIfNeeded] after marking the view as needing display. I encountered this problem when implementing the Mac driver for Wine (an open-source project for running Windows software on OS X and other Unix-like OSes).
http://source.winehq.org/source/dlls/winemac.drv/cocoa_window.m?v=wine-1.7.11#L1905
(That's LGPL code, so you want to consider before copying it. But you can learn implementation techniques from it without worry.)

Working with storyboards in Xcode, how to handle massive Storyboard in iOS

I have been using the storyboard to make an application and currently there are many segues and several components. This is causing a ton of lag when I try to do anything inside the storyboard. Is there a way to hide components inside the storyboard? thanks.
+1, For the potentially features to improve Xcode. Now, there is no way you can hide those views (Not that I know). But I would suggest you to,
Hide the debug areas you don't need.
Hide the document outline while working with segues.
Why?
I think in this way whenever you are making changes, system does not have to repaint those unwanted views and long document outline. Probably this will be less laggy(I don't think there is a word like this)!
Work around
Divide your segue into different meta segues and then you can call those segues from your main segue. In that way you don't have to put each connection on one file but you condense it!
And here we go the documentation for it! Now you can get the story board by different file and then initiate with the UIViewController easily. Then you can just use old ways to segue between different ViewControllers.
Apple Documentation for UIStoryboard
Demo App.
In order to achieve this, I have made a quick demo application which will help any future visitors.
https://github.com/Krutarth/LargeStoryboardManagement
Visually something like this,
You can split one huge storyboard into multiple small storyboards.
Select the view controllers that you want to move to a smaller storyboard, then
In the top menu, click Editor -> Refactor to Storyboard
Save the new storyboard with the desired name. XCode will auto generate all the required storyboard links from your large storyboard to this newly created small one.

Advantages, problems, examples of adding another UIWindow to an iOS app?

Recently I've been wondering about the fact that that an iOS app only has one UIWindow.
It does not seem to be an issue to create another UIWindow and place it on screen.
My question is kind of vague, but I'm interested in:
What could I potentially achieve with a second UIWindow that cannot be done in other ways?
What can go wrong when using multiple UIWindow instances?
I have seen that people use a 2nd UIWindow to display popover like views on iPhone. Is this a good way of doing it? Why? Why not?
Are there other examples where it is making perfectly sense to have another UIWindow?
It's not that I'm missing something. I have never felt the need to create another UIWindow instance but maybe it would allow doing amazing things I'm not aware of! :-)
I'm hoping that it might help me solve this problem:
I need to add a "cover view" over whatever is currently displayed. It should also work if there are already one or more modal controllers presented. If I add a UIView to the root controller's view, the modal controllers sit on top, so do the popover controllers.
If I present the cover view modally and there is already a modal controller, only part of the screen is covered.
Starting with Rob's answer I played around a bit and would like to write down some notes for others trying to get information on this topic:
It is not a problem at all to add another UIWindow. Just create one and makeKeyAndVisible. Done.
Remove it by making another window visible, then release the one you don't need anymore.
The window that is "key" receives all the keyboard input.
UIWindow covers everything, even modals, popovers, etc. Brilliant!
UIWindow is always portrait implicitly. It does no rotate. You'll have to add a controller as the new window's root controller and let that handle rotation. (Just like the main window)
The window's level determines how "high" it gets displayed. Set it to UIWindowLevelStatusBar to have it cover everything. Set its hidden property to NO.
A 2nd UIWindow can be used to bring views on the screen that float on top of everything. Without creating a dummy controller just to embed that in a UIPopoverController.
It can be especially useful on iPhone where there is no popover controller but where you might want to mimic something like it.
And yes, it solved of course my problem: if the app resigns activation, add a cover window over whatever is currently shown to prevent iOS from taking a screenshot of your app's current content.
A UIWindow can float above other UI elements like the system keyboard.
To address your last paragraph: Make a UIWindow with the same frame as your main window. Set its windowLevel property to UIWindowLevelStatusBar. Set its hidden property to NO.
Here is Apple's Documentation for better understanding UIWindow:
https://developer.apple.com/library/archive/documentation/WindowsViews/Conceptual/WindowAndScreenGuide/WindowScreenRolesinApp/WindowScreenRolesinApp.html
One good though specific reason to use multiple instances of UIWindow is when you need to video record the app screen. You may not want to include certain elements (recording button, recording status, etc.) in the final recorded video, so you can put those elements in a separate UIWindow on top.
In fact, if you are using ReplayKit, you will have to use a separate UIWindow for these excluded UI elements. More info here: https://medium.com/ar-tips-and-tricks/how-to-record-a-screen-capture-with-replaykit-whilst-hiding-the-hud-element-bedcca8e31e

Split NSTabView across multiple NSViewControllers and XIBs

I'm just getting into desktop Cocoa development (I have experience with iOS development). If this question seems basic, forgive me.
That being said, I'm dealing with a large program with lots of calculations and functionality to deal with. There are almost a dozen views, organized with an NSTabView. Rather than dumping everything into one monstrosity of a class and creating a XIB file that brings my system to its knees (Xcode apparently isn't that efficient…who knew? :P). I'd like for each tab to be its own NSViewController with accompanying XIB; as such, I'd like to load each tab's view from the corresponding XIB.
I'm thinking of this in terms of UITabBarController, but this doesn't seem to work (there isn't an NSTabViewController as far as I could find). I'm not sure how to do this (or even if it's possible—but I can't be the only one with this issue?), and I'd appreciate any assistance. Thanks!
Update: I tried assigning the controller's view to the tab's view, but quickly realized that wouldn't get me anywhere. Is it worth creating an NSTabViewController from scratch, or is there a solution out there?
Cocoa development on the desktop has some major differences compared to iOS development. One of them is the use of view controllers - they aren't strictly necessary - and when you use them you can just stick to a generic NSViewController regardless of what kind of view it contains. All of the methods you need to control the tab view are in the NSTabView class - not the controller.
Having said that, putting 12 views in to a tabview sounds like a painful way to interact with a program. Have you thought about a source-detail type setup (think itunes or mail with their sidebars - each entry in the sidebar corresponds to a different view)?
I've ditched the tab bar, and as per sosborn's suggestion, I have used a split view—or rather I've put a table view on the side, and a custom view taking up most of the screen. Then, in my AppDelegate, I have individual controllers as ivars (I need individual controllers because there are a lot of calculations involved, and I don't want to have a monster class handling them all). They'll be lazily loaded, and the view will be assigned to the current controller's view as necessary.