Better way to detect if isIpad? - objective-c

I have an universal app that changes the screen layout based on what device the user has.
It seems to work pretty good, but I've had one user call in (and send me screen shots) of his iPhone 4 showing him the iPad view instead of the iPhone view. I haven't been able to duplicate it on any of the phones we have around here, but I'm wondering if there there is a better way to do this since iOS 4.3 has come out.
+(BOOL)isIpad{
return ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad);
}
Alternately, is there just a way to detect screen size? I mostly use this to determine how wide elements in a table should be, but if Apple comes out with iPad 3 with retina display, it would be nice to have the app just adjust everything accordingly.
Also useful if the app is in portrait or landscape. Make it so that it just anchors to the edges like elements in WPF.

When loading XIBs for a universal app this, or what you're already doing, seems to be the only way:
NSString *xibName = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)?#"SomeView~iPad":#"SomeView";
As for screen size this should work:
CGRect screenSize = [[UIScreen mainScreen] bounds];

This is like a bazillion years old, but came across it in google so I figured I'd post a poorly documented but very useful feature. If you add ~ipad to the end of the filename for your iPad specific nib it will automatically load that one instead. Same logic as #2x for loading images. So your iPhone nib would be named myview.xib and your ipad myview~ipad.xib and iOS will correctly load the ipad version wherever needed. Fancy!

UIUserInterfaceIdiomPad is now deprecated. The new way to do it would be using TraitCollections. It can only be called on Views.
-(BOOL) isiPad{
return self.view.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassRegular && self.view.traitCollection.verticalSizeClass == UIUserInterfaceSizeClassRegular;
}
Refer Apple Documentation here

Probably it has a previous version of the app and conflict with the new!
Try to remove old one and reinstall new! It works! I already encountered this issue.

Related

KIF (Keep It Functional) distinguish between iPhone and iPad

I am using KIF for testing the functionality of an app. However, this app has two versions, one is for iPad, and the other one is for iPhone. Is there a global variable or something that indicates if I am running my test in iPad or iPhone? I'd like to use it (e.g. in a conditional) to take advantage and just make a few modifications in the iPhone tests that I have already finished.
You can define macro
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPhone)
That's how we used it.

iOS8 how to understand interface orientation from UIViewControllerTransitionCoordinator?

I'm debugging a project that was working fine in iOS7.1, but does not lay out it's content properly in iOS 8.0. I've narrowed the issue down to this method:
[self orientRootViewControllerForOrientation:rootViewController.interfaceOrientation];
iOS8 no longer returns correct UIInterfaceOrientation from rootViewController.interfaceOrientation, instead it returns "upside down".
Reading the documentation, I'm confronted with a cryptic message:
Use viewWillTransitionToSize:withTransitionCoordinator: to make
interface-based adjustments.
Reading documentation on UIViewControllerTransitionCoordinator, I don't see it having any properties. How can I modify my method that expects an interface orientation to get it's orientation from UIViewControllerTransitionCoordinator?
Basically you are supposed now to layout your content based on the available size, no more on the rotation. Which results in big pains to support older rotation-based code.
The view controller transition coordinator provides a UIViewControllerTransitionCoordinatorContext that has a rotation factor. This could give you the hint you need ?
This blog post mentions this too.
You also have the usual device ([UIDevice currentDevice].orientation) or status bar orientation.
In case you are working on iOS 6 rotation methods, this post has relevant informations too.

Titanium - Reset zoom scale in webview

Is it possible to programmatically reset the zoom/scale that the user has done in a webview? My issue is when the webview is pinch zoomed in landscape and you rotate the phone, the webview is still zoomed in and in my case, portrait mode is now extremely zoomed in.
I've tried webview.repaint() but that seems to do absolutely nothing. I know I can call webiew.reload() but that just uses more bandwidth for my server as well as the users data plan so I want to avoid that.
I'm using Titanium Studio, build: 3.1.3.xxx, 3.1.3 GA Ti SDK and compiling for iOS 7 SDK.
Based on this thread and the fact that there was no way to easily achieve this, I have created a module. It extends the Ti.UI.WebView with two methods, setZoomLevel() and scrollToTop(). It is very basic at the moment, but I'm planning on extending its functionality gradually.
https://github.com/mwfire/titanium-module-extended-webview
Have a look, it's an alternative to modifying the core code.
Did you give a try at setting the scalesPageToFit property of your webview upon orientation change?
http://docs.appcelerator.com/titanium/3.0/#!/api/Titanium.UI.WebView-property-scalesPageToFit
I found the answer which was a bit more than I wanted to do. I had to actually modify the Titanium SDK obj-c files.
I modified 3 files:
TiUIWebView.h
-(void)resetZoomScale; //-- added this line to define the function in the header file
TiUIWebView.m
//-- Added this function that will actually handle the resize
- (void)resetZoomScale
{
[webview.scrollView setZoomScale:1.0]; //-- reset the scroll view back to 1
}
TiUIWebViewProxy.m
//-- Call the resetZoomScale function in TiUIWebView.m file
//-- I believe this also exposes the function to javascript
-(void)resetZoomScale:()args
{
TiThreadPerformOnMainThread(^{[(TiUIWebView*)[self view] resetZoomScale];}, NO);
}
I can now call myWebView.resetZoomScale(); and whatever pinch/zooming has been done on the web view will be reset back none or 1

Create single .xib for Universal app in Interface Builder? (iOS)

Apologies if this is a silly question, but I've done some googling and searched SO and haven't found anyone asking this exact question.
I have been doing iOS development for some time now, but I am completely new to the Interface Builder. What I want to know is this: is there any way to just create ONE .xib file and then use it for both iPhone and iPad in a Universal application?
It seems silly to me to have to create them separately; why do twice the work laying something out more than once in Interface Builder when I could do it once (with minor adjustments for screen size) in code?
Please let me know if I'm missing/misunderstanding something here. Like I said, I'm a complete Interface Builder newbie :)
EDIT: I have submitted non-interface-builder games to the App Store in the past where the iPhone and iPad versions were identical, so I'm not concerned with making the game look/feel different on each device. I intend for them to look exactly the same, aside from some slight positioning changes due to the difference in aspect ratio.
If you know what the resulting view would look like, based on autoresizing, you can indeed use only one .xib. May come in handy if the view is just some sort of a shared component that autoresizes as you want it to. However, if you need the view to look way different on iPad than on iPhone, just use two .xibs. It’s possible then to load the appropriate one as needed, for example in instance initializer, like this controller’s -init:
- (id)init
{
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
{
self = [super initWithNibName:#"YourNibForPad" bundle:nil];
}
else
{
self = [super initWithNibName:#"YourNibForPhone" bundle:nil];
}
if (self) { /* initialize other ivars */ }
return self;
}
The main reason that XIBs are separate files is because Apple feel that UIs designed for iPhones/iPod touches and iPads should be tailored to each respectively. This is echoed in their their iOS App Programming Guide, which says the following:
For views, the main modification is to redesign your view layouts to support the larger screen. Simply scaling existing views may work but often does not yield the best results. Your new interface should make use of the available space and take advantage of new interface elements where appropriate. Doing so is more likely to result in an interface that feels more natural to the user—and not just an iPhone app on a larger screen.
Whilst it can take time to maintain two XIBs for what is effectively one UI, I feel it is more straightforward than using one XIB and then having to connect up most of your UI elements in order to move them around programmatically when that XIB loads. After all, with two XIBs at least you can see what each UI looks like, and then make visual changes easily.
As an aside, don't forget iOS 5's Storyboards (read about them here), which make managing a view/view controller hierarchy much simpler.
Try to name them
MyCell.xib and MyCell ~ ipad.xib
then:
[self.tableView registerNib: #"MyCell" forCellReuseIdentifier: #"MyUniqueIdentifier"];
If your using IB, you need to create 2 separate xib files for iPhone and iPad. You need a separate iPad xib to make your app comply with the Apple iPad UI guidelines.

How do I use a RootViewController when making an app without a ViewController?

I am trying to make a simple app from a tutorial that does not have a viewController at all. All the code is in the AppDelegate. I am on xcode 4.2 and I am getting this error:
Applications are expected to have a root view controller at the end of application launch
I'm not sure how to deal with this. There are some blogs out there with fixes but none of them are working for me and I really would like to understand what is going on here. And, how to fix it.
I do have a view that contains some buttons and labels. But I have no "ViewController". The files contained in my project are: AppDelegate.h, AppDelegate.m, and Window.xib only. There is no ViewController.h, ViewController.m
** edit **
I ended up making the app from a 'view based application' instead and just moving all the logic from the app delegate to the view controller. So, I didn't really solve the problem per se. The app works now though. Thanks for the help
It's not possible to have an iOS app that doesn't have a view controller. You can always create a trivial view controller, i.e.,
[[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds].rootViewController =
[[[UIViewController alloc] init] autorelease];
It sounds like you're looking at an old tutorial. UIWindow got a rooViewController property in iOS4. I believe it became required in iOS5 to help keep controller hierarchies and view hierarchies in sync with the addition of custom container controllers (and to fix a corner case where replacing the "root controller" of a UIWindow could stop orientation changes from propagating). There was a WWDC presentation in 2011 that explained this in some detail. I think it was Session 102, Implementing UIViewController Containment.
At then end of the day, there's no good reason not to have a root view controller. Apple wants to be able to assume it's there in their APIs going forward. If the tutorial you're looking at doesn't account for that, it's broken.
While I agree that there may be workarounds, another question to address is: why do you want an app without a view? Even if it's designed to run in the background and present no visual interface, at least make a simple view showing the application name and version, a largeish icon and perhaps a status. This kind of idle screen uses very little system resources, especially when the app is backgrounded, but improves the overall experience of the app.
If you set your deployment target to 4.3 and run on the iPhone 4.3 simulator, you won't get the warning.
To install the iOS 4.3 simulator, go to Xcode > Preferences > Downloads.