creating a view controller for universal iOS app - ios

update 0
Hold off on answering this question.
I think I have found part of the problem.
XCode aborted again when I tried to rename the automatically generated .xib files it had created with _ to use ~. Xcode seems to destroy at least one of the .xib files when it aborts, and that file contains the minimal view or window object needed by the app. Although the missing .xib file is gone from the Finder, it still shows in the Navigator.
So now, I am going to leave the _ files alone and try again, but not use the suggestion I got earlier.
update 0
I am having trouble with my xibs having changed the following code as recommended here.
I suspect the problem comes from changing the xib names to using '~' instead of '_' and not being able to revise the corresponding code which refers to the xib names.
The problem could also be that I have the following 4 filenames which could be confusing to Xcode?
BSViewController.h/.m
BSViewController~iPhone.xib
BSViewController~iPad.xib
Original code was.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
self.viewController = [[BSViewController alloc] initWithNibName:#"BSViewController_iPhone" bundle:nil];
} else {
self.viewController = [[BSViewController alloc] initWithNibName:#"BSViewController_iPad" bundle:nil];
}
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
Altered code (including extra) is.
#import "BSAppDelegate.h"
#import "BSViewController.h"
#implementation BSAppDelegate
#synthesize window;
#synthesize viewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[BSViewController alloc] initWithNibName:#"BSViewController" bundle:nil];
[self.window addSubview:viewController.view];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
BSAppDelegate.h follows.
#import <UIKit/UIKit.h>
#class BSApp;
#class BSViewController;
#interface BSAppDelegate : NSObject <UIApplicationDelegate>{
UIWindow *window;
BSViewController *viewController;
}
#property (retain, nonatomic) IBOutlet UIWindow *window;
#property (retain, nonatomic) IBOutlet BSViewController *viewController;
#end
BSViewController.h follows.
#import <UIKit/UIKit.h>
#interface BSViewController : UIViewController<UIImagePickerControllerDelegate, UINavigationControllerDelegate> {
UIImage *workingImage;
IBOutlet UIImageView *imageView;
}
#property (nonatomic, retain) UIImage *workingImage;
#property (nonatomic, retain) IBOutlet UIImageView *imageView;
+ (BOOL)isCameraDeviceAvailable;
- (IBAction) chooseImage:(id) sender;
- (IBAction) grayscale:(id) sender;
#end
BSViewController.m follows.
#import "BSViewController.h"
#interface BSViewController ()
#end
#implementation BSViewController
#synthesize imageView;
#synthesize workingImage;
+(BOOL)isCameraDeviceAvailable
{
BOOL isCameraAvailable=NO;
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
if([UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront] )
isCameraAvailable = YES;
}
return isCameraAvailable;
}
- (IBAction) chooseImage:(id) sender {
[self.view addSubview: self.imageView];
UIImage* testCard = [UIImage imageNamed:#"ipad 7D.JPG"];
CGImageRef num = CGImageCreateWithImageInRect([testCard CGImage],CGRectMake(532, 0, 104, 104));
UIGraphicsBeginImageContext(CGSizeMake( 250,650));
CGContextRef con = UIGraphicsGetCurrentContext();
CGContextDrawImage(con, CGRectMake(0, 0, 13, 13) ,num);
UIImage* im = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGImageRelease(num);
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
self.workingImage = [info objectForKey:UIImagePickerControllerOriginalImage];
[imageView setImage:self.workingImage];
[picker dismissViewControllerAnimated:YES completion:nil];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.imageView = nil;
}
- (void)dealloc {
[workingImage release];
[imageView release];
[super dealloc];
}
#end
I am using Xcode 4.5.2 and designing for iOS 6.
In my BSViewController~iPad.xib I have added a "ViewController" object which upon control-clicking produces 2 Outlets: "searchDisplayController" and "view". There is no "view" top-level object; when I try to drag the "+" to the "File's Owner" I get no result and probably shouldn't.
In my BSViewController~iPhone.xib I have already a "Window" object, and don't know if that is good or needs to be also added to the the ~iPad.xib (but I don't know how).

Related

viewDidLoad is not called after the setting of no storyboard

What I would like to do is to create UIImageView without storyboard, but failed to let it show. At first I deleted storyboard, LaunchScreen.xib and Main StoryBoard file base name from info.plist. and then what I created is as follows:
AppDelegate.h
#import <UIKit/UIKit.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#end
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor greenColor];
[self.window makeKeyAndVisible];
return YES;
}
ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
UIImage *imageData =[UIImage imageNamed:#"aaa.png"];
UIImageView *myImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 30, 100, 100)];
myImage.image = imageData;
[self.view addSubview:myImage];
}
I am a beginner and couldn't find any solution.
Does anybody know how to solve this?
Thank you in advance.
Xcode 6.4
OSX 10.10.5
You just need to set your window's root view controller to an instance of ViewController
self.window.rootViewController = [[ViewController alloc] init];
You'll also have to import ViewController.h at the top of your AppDelegate file

Custom transition between UIViewControllers does not work

I have object that manage custom transition:
#interface NavigationManager : NSObject <UIViewControllerAnimatedTransitioning>
-(NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext;
-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext;
#property (nonatomic, assign) NSTimeInterval presentationDuration;
#property (nonatomic, assign) NSTimeInterval dismissalDuration;
#property (nonatomic, assign) BOOL isPresenting;
#end
#interface NavigationManager()
#property (nonatomic, strong) id<UIViewControllerContextTransitioning> transitionContext;
#end
#implementation NavigationManager
#synthesize presentationDuration, dismissalDuration, isPresenting;
-(id)init{
self = [super init];
if(self){
self.presentationDuration = 1.0;
self.dismissalDuration = 0.5;
}
return self;
}
-(NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{
return self.isPresenting ? self.presentationDuration : self.dismissalDuration;
}
-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
self.transitionContext = transitionContext;
if(self.isPresenting){
[self executePresentation:transitionContext];
}
else{
[self executeDismiss:transitionContext];
}
}
...
#end
And in class that should process implement transitions:
#interface ViewController : UIViewController <UIViewControllerTransitioningDelegate>
#property (nonatomic, strong) NavigationManager navigationManager;
..
#end
#implementation
...
//Here I`m doing navigation to new UIViewController
- (void)navigateToNewScreen
{
DetailedNewsController *secVC = [[DetailedNewsController alloc] init];
secVC.fullDescription = fullDescription;
secVC.headerImage = a.imageView.image;
self.transitioningDelegate = self;
[self.navigationController pushViewController:secVC animated:YES];
}
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented
presentingController:(UIViewController *)presenting
sourceController:(UIViewController *)source
{
self.animationController.isPresenting = YES;
return self.animationController;
}
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
self.animationController.isPresenting = NO;
return self.animationManager;
}
#end
Default animation of transitioning is performed. Also navigation controller bar is not displayed after navigation.
UPDATE:
I thing problem in way how I`m creating UINavigationController in AppDelegate:
firstVC = [[ViewController alloc] init];
navController = [[UINavigationController alloc] initWithRootViewController:firstVC];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor blackColor];
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
I'll make an answer with the new information you have provided. The reason I make it an answer is that I just don't want to give you some copy paste code, but to try to give a brief explanation behind it. If I understand correctly, you now want to present a ViewController with a custom transition.
So you got the custom transition working by changing your code to this:
secVC.transitioningDelegate = self;
secVC.modalPresentationStyle = UIModalPresentationCustom;
[self presentViewController:secVC animated:YES completion:nil];
Since we got that up and running, what's currently missing is the NavigationBar of the ViewController you want to show. Since you're presenting a ViewController, it won't be contained within the existing NavigationController stack in which the the ViewController you're presenting is within.
Therefore, you need to wrap your VC you want to present within a UINavigationController.
[self presentViewController:[[UINavigationController alloc] initWithRootViewController:secVC] animated:YES completion:nil];

Different URI for each instance of UIViewController

I have a UITabController with five tabs. Each tab simply holds an instance of a custom UIViewController, and each instance holds a UIWebView.
I want the UIWebView in each tab to open a different URI, but I don't think it should be necessary to create a new class for each tab.
I can make it work if I do [self.webView loadRequest:] in -(void)viewDidLoad but it seems ridiculous to create five different classes with five different versions of viewDidLoad when all I really want to change is the URI.
Here's what I've tried:
appDelegate.h
#import <UIKit/UIKit.h>
#interface elfAppDelegate : UIResponder <UIApplicationDelegate, UITabBarControllerDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) UITabBarController *tabBarController;
#end
appDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
customVC *start = [[customVC alloc] init];
customVC *eshop = [[customVC alloc] init];
customVC *table = [[customVC alloc] init];
customVC *video = [[customVC alloc] init];
customVC *other = [[customVC alloc] init];
// Doesn't do anything... I wish it would!
[start.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://google.com"]]];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = #[start, eshop, table, video, other];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
customVC.h
#import <UIKit/UIKit.h>
#interface customVC : UIViewController <UIWebViewDelegate> {
UIWebView* mWebView;
}
#property (nonatomic, retain) UIWebView* webView;
- (void)updateAddress:(NSURLRequest*)request;
- (void)loadAddress:(id)sender event:(UIEvent*)event;
#end
customVC.m
#interface elfVC ()
#end
#implementation elfVC
#synthesize webView = mWebView;
- (void)viewDidLoad {
[super viewDidLoad];
self.webView = [[UIWebView alloc] init];
[self.webView setFrame:CGRectMake(0, 0, 320, 480)];
self.webView.delegate = self;
self.webView.scalesPageToFit = YES;
[self.view addSubview:self.webView];
}
Create a property of type NSURL* in your customVC.
Change your customVC's -(id)init method to -(id)initWithURL:(NSURL*)url as follows:
-(id)initWithURL:(NSURL*)url{
self = [super init];
if(self){
self.<URLPropertyName> = url;
}
return self;
}
Then call
[start.webView loadRequest:[NSURLRequest requestWithURL:self.<URLPropertyName>]];
in viewDidLoad
Then when you initialize your different instances of customVC, just use
customVC *vc = [customVC alloc]initWithURL:[NSURL URLWithString:#"http://..."]];
I suspect you are initialising your webview after calling it's loadRequest: method. To avoid this, it's a better practice to initialise nonatomic properties by overriding their setters:
- (UIWebView*)webview {
if (mWebView == nil) {
// do the initialization here
}
return mWebView;
}
This way your webview will be initialised when you first access it (while calling loadRequest:) and not after it, in your custom view controller's viewDidLoad method.

iOS App UIView rotating, content is not

I'm currently building an iOS app, and the only supported orientations are landscape left and right. I've specified this in several ways:
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
return UIInterfaceOrientationIsLandscape(toInterfaceOrientation); //iOS 5 compatibility.
}
-(NSInteger)supportedInterfaceOrientations:(UIWindow *)window{
return UIInterfaceOrientationMaskLandscape; //iOS 6
}
-(BOOL)shouldAutorotate{
return YES;
}
And I've specified the supported orientations as only the landscape ones in the app's Info.plist. When I run the app on my device (or even in the simulator), I know that the root view is in landscape orientation (switcher is on the long side of the screen, as is notification center), however the content still originates from the top left corner of the screen, as if in portrait mode, not the bottom left or top right, like I want it to be. I have no idea what could be causing the content not to rotate with the parent view, as this code worked on iOS 5, but is not on iOS 6.
EDIT: Here's a screenshot.
EDIT: Here's my main.m:
#import <UIKit/UIKit.h>
int main(int argc, char **argv) {
NSAutoreleasePool *p = [[NSAutoreleasePool alloc] init];
int ret = UIApplicationMain(argc, argv, #"ClockApplication", #"ClockApplication");
[p drain];
return ret;
}
And here's my ClockApplication.mm:
#import "RootViewController.h"
#interface ClockApplication: UIApplication <UIApplicationDelegate> {
UIWindow *_window;
RootViewController *_viewController;
}
#property (nonatomic, retain) UIWindow *window;
#end
#implementation ClockApplication
#synthesize window = _window;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
_viewController = [[RootViewController alloc] init];
[_window addSubview:_viewController.view];
[_window makeKeyAndVisible];
}
- (void)dealloc {
[_viewController release];
[_window release];
[super dealloc];
}
#end
Try changing your method from this
-(NSInteger)supportedInterfaceOrientations:(UIWindow *)window{
}
to this
-(NSUInteger)supportedInterfaceOrientations{
}
EDIT
Try calling your view inside a navigationcontroller like this:
UIViewController *yourViewController = [[UIViewController alloc] init];
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:yourViewController];
nc.navigationBarHidden = YES;
[self.navigationController presentModalViewController:nc animated:NO];
[self.navigationController dismissModalViewControllerAnimated:NO];
EDIT
#import "RootViewController.h"
#interface ClockApplication: UIApplication <UIApplicationDelegate> {
UIWindow *_window;
RootViewController *_viewController;
}
#property (nonatomic, retain) UIWindow *window;
#end
#implementation ClockApplication
#synthesize window = _window;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:_viewController];
nc.navigationBarHidden = YES;
_window.rootViewController = nc;
[_window makeKeyAndVisible];
}
- (void)dealloc {
[_viewController release];
[_window release];
[super dealloc];
}
#end
Try to add:
_window.rootViewController = _viewController;
EDIT: Anyway your code looks like using "deprecated" style. I would suggest to set up a new project for iOS6 and use its template. It was working on iOS5 but iOS changes.
Only the rootViewController of your UIWindow will receive rotation events.
[_window setRootViewController:_rootViewController];
Check out the apple technical notes.

Switch between two UIViewControllers programmatically

I have two xib files and for each it's own class which overrides UIViewController class. I have a button in first xib file which should take me to new UIViewController when it's pressed. I have managed to make that transition in different ways:
UIViewController* secondViewController = [[UIViewController alloc] initWithNibName:#"SecondViewControllerName" bundle:[NSBundle mainBundle]];
[self.view addSubview:secondViewController.view];
or
UIViewController* secondViewController = [[UIViewController alloc] initWithNibName:#"SecondViewControllerName" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:secondViewController animated:YES];
In second UIViewController xib file I have also one button which should take me back to first UIViewController. But I don't know how to navigate back to first UIViewController.
I tried:
[self.navigationController popViewControllerAnimated:YES];
for second way of navigating to second UIViewController, but I get unrecognized selector sent to instance error.
Many thanks in advance for any kind of help.
[edit #1: Adding source code]
Here's source code of first view controller .m file:
#import "ViewController.h"
#import "SecondViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (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 != UIInterfaceOrientationPortraitUpsideDown);
}
- (IBAction)switchToSecondPage:(id)sender
{
SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
[UIView beginAnimations:#"flipping view" context:nil];
[UIView setAnimationDuration:1];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition: UIViewAnimationTransitionCurlDown forView:self.view cache:YES];
[self.view addSubview:secondViewController.view];
[UIView commitAnimations];
}
#end
Here's source code of second view controller .m file:
#import "SecondViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (IBAction)switchToFirstPage:(id)sender
{
[UIView beginAnimations:#"flipping view" context:nil];
[UIView setAnimationDuration:1];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationTransition: UIViewAnimationTransitionCurlUp forView:self.view.superview cache:YES];
[self.view removeFromSuperview];
[UIView commitAnimations];
}
#end
Here's my AppDelegate.m file:
#import "AppDelegate.h"
#import "ViewController.h"
#implementation AppDelegate
#synthesize window = _window;
#synthesize viewController = _viewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
}
- (void)applicationWillTerminate:(UIApplication *)application
{
}
#end
Entire project is made as Single View Application and targeted for iOS 5.1 in XCode 4.3. I have found sample project which does the same thing I am having trouble with. Here's URL for that project: http://www.devx.com/wireless/Article/42476/0/page/2
It is just written for earlier iOS version. Is anyone able to see what am I doing wrong, since I am really out of ideas?
PS: With this animations in code, or without - same problem occurs, so animations aren't problem, I've checked that.
[edit #2: Adding error info]
Here's error description. In main method on return line as listed below:
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
I get this error:
Thread 1: EXC_BAD_ACCESS (code=1, address=0xc00000008)
[edit #3: SOLUTION]
I would like to thank #btype for his solution below. I found out why code from edit #2 didn't work. Problem was doing this:
SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
INSIDE OF IBAction METHOD! Looks like ARC wiped my UIViewController as soon as end of scope was reached and that's why I was getting informations about sending messages to released instance. I made SecondViewController private field in my ViewController class and after that everything worked just fine.
If anyone thinks my explanation is wrong and knows what really bothered me, feel free to answer to this question and correct me.
Edit the code:
in AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
ViewController *viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController];
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
return YES;
}
FirstViewController.m
- (IBAction)switchToSecondPage:(id)sender
{
[self.navigationController pushViewController:secondViewController animated:YES];
}
SeconViewController.m
- (IBAction)switchToFirstPage:(id)sender
{
[self.navigationController popToRootViewControllerAnimated:YES];
}
This should help.

Resources