Assigning to properties inside custom init method - ios

I'm trying to write custom init method for my UIViewController. Here is the method itself:
- (instancetype)initWithBottomViewController:(UIViewController *)bottomViewController andTopViewController:(UIViewController *)topViewController {
self = [super init];
if (self) {
self.bottomViewController = bottomViewController;
self.topViewController = topViewController;
}
return self;
}
- (void)setupBottomViewController {
/*crashes here because self.bottomViewController appears to be nil*/
[self addChildViewController:self.bottomViewController];
[self.bottomViewController.view setFrame:self.view.bounds];
[self.view addSubview:self.bottomViewController.view];
[self.bottomViewController didMoveToParentViewController:self];
}
Console says -[__NSArrayM insertObject:AtIndex:] object cannot be nil
I call my init function in AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
BottomViewController *bottomVC = [[BottomViewController alloc] initWithNibName:#"BottomViewController" bundle:nil];
TopViewController *topVC = [[TopViewController alloc] initWithNibName:#"TopViewController" bundle:nil];
SlideMenuController *slideController = [[SlideMenuController alloc] initWithBottomViewController:bottomVC andTopViewController:topVC];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.rootViewController = slideController;
[self.window makeKeyAndVisible];
return YES;
}
Properties self.bottomViewController and self.topViewController are declared in .h file:
#property (strong, nonatomic) UIViewController *bottomViewController;
#property (strong, nonatomic) UIViewController *topViewController;
The problem is in the assignment to self.bottomViewController and self.topViewController. bottomViewController and topViewController aren't nil, but self.bottomViewController and self.topViewController are. I can't figure it out by myself. Thanks in advance!

The problem was that I implemented empty setter methods for both self.bottomViewController and self.topViewController.

Related

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];

iOS 6: supportedInterfaceOrientations is called but shouldAutorotate is not called

I know this question has been asked before here iOS 6 shouldAutorotate: is NOT being called. But my scenario is a bit different.
Initially, on application launch I load a viewController like
self.window.rootViewController = self.viewController;
and When this view is loaded I am using a custom tabBar view (inherited from UIView) which has 5 UINavigationController for each tab. The code of this viewController Class is:
\\\ .h File
#protocol tabbarDelegate <NSObject>
-(void)touchBtnAtIndex:(NSInteger)index;
#end
#class tabbarView;
#interface ViewController : UIViewController <tabbarDelegate>
#property(nonatomic,strong) tabbarView *tabbar;
#property(nonatomic,strong) NSArray *arrayViewcontrollers;
#property(nonatomic,strong) UINavigationController * navigation1;
#property(nonatomic,strong) UINavigationController * navigation2;
#property(nonatomic,strong) UINavigationController * navigation3;
#property(nonatomic,strong) UINavigationController * navigation4;
#property(nonatomic,strong) UINavigationController * navigation5;
#end
and m file is
- (void)viewDidLoad
{
[super viewDidLoad];
CGFloat orginHeight = self.view.frame.size.height- 60;
_tabbar = [[tabbarView alloc]initWithFrame:CGRectMake(0, orginHeight, 320, 60)];
_tabbar.delegate = self;
[self.view addSubview:_tabbar];
_arrayViewcontrollers = [self getViewcontrollers];
[self touchBtnAtIndex:0];
}
-(void)touchBtnAtIndex:(NSInteger)index \\This delegate method is called on every custom tabBar button clicked.
{
UIView* currentView = [self.view viewWithTag:SELECTED_VIEW_CONTROLLER_TAG];
[currentView removeFromSuperview];
UINavigationController *viewController = [_arrayViewcontrollers objectAtIndex:index];
viewController.view.tag = SELECTED_VIEW_CONTROLLER_TAG;
viewController.view.frame = CGRectMake(0,0,self.view.frame.size.width, self.view.frame.size.height- 50);
[self.view insertSubview:viewController.view belowSubview:_tabbar];
}
-(NSArray *)getViewcontrollers
{
FirstViewController *firstController = [[FirstViewController alloc]initWithNibName:#"FirstViewController" bundle:nil];
SecondViewController *secondController = [[SecondViewController alloc]initWithNibName:#"SecondViewController" bundle:nil];
ThirdViewController *thirdController = [[ThirdViewController alloc]initWithNibName:#"ThirdViewController" bundle:nil];
ForthViewController *forthController = [[ForthViewController alloc]initWithNibName:#"ForthViewController" bundle:nil];
FifthViewController *fifthController = [[FifthViewController alloc]initWithNibName:#"FifthViewController" bundle:nil];
navigation1 = [[UINavigationController alloc] initWithRootViewController:firstController];
navigation2 = [[UINavigationController alloc] initWithRootViewController:secondController];
navigation3 = [[UINavigationController alloc] initWithRootViewController:thirdController];
navigation4 = [[UINavigationController alloc] initWithRootViewController:forthController];
navigation5 = [[UINavigationController alloc] initWithRootViewController:fifthController];
NSArray* tabBarItems = [[NSArray alloc] initWithObjects:navigation1,navigation2,navigation3,navigation4,navigation5, nil];
return tabBarItems;
}
I have also implemented UINavigationController's category for rotation as:
#implementation UINavigationController (autoRotation)
-(BOOL)shouldAutorotate {
return [[self.viewControllers lastObject] shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations {
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}
My Problem is that only supportedInterfaceOrientations method is called and shouldAutorotate is never called. The main Window's rootViewController is ViewController class, not any UINavigationController or UITabBarController. What I am doing wrong? Please help me.
If you add these to your root view controller:
- (BOOL)shouldAutorotate
{
NSLog(#"ViewController shouldAutorotate super=%d", [super shouldAutorotate]);
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
NSLog(#"ViewController supportedInterfaceOrientations");
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
}
you will see that the system is constantly sending both of these messages. Your code there can query the active Navigation Controller to see what values to return if you wish.
Also, I'm no fan of using a category to override these on a UINavigation Controller - that it works is somewhat of a fluke and importing some other library that does the same could cause unexpected consequences later on. Just create a really simple subclass and over ride both of these. I've been doing that with both UITabBarController and UINavigationController since iOS4 and never had an issue.

UIWebView Not Showing Up

I just added a new UIWebView and it doesn't seem to be showing up. I'm pretty new here, so this could be a very simple error.
I created the view using the storyboard and dragged it into my GuideViewController.h
This is my GuideViewController.h
#import <UIKit/UIKit.h>
#interface GuideViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIWebView *newsWebView;
#end
This is my GuideViewController.m
#import "GuideViewController.h"
#interface GuideViewController ()
#end
#implementation GuideViewController
#synthesize newsWebView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSURL *newsURL = [NSURL URLWithString:#"http://www.yahoo.com"];
NSURLRequest *newsRequest = [NSURLRequest requestWithURL:newsURL];
[newsWebView loadRequest:newsRequest];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
This is what I'm using to add the view to my app delegate. I already have a sidebar menu added.
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
VidViewController *vidViewController = [[VidViewController alloc] init];
GuideViewController *newsWebView = [[GuideViewController alloc] init];
UINavigationController *navController1 = [[UINavigationController alloc] initWithRootViewController:vidViewController];
[self.window setRootViewController:navController1];
SelectVideo1 *selectVideo1 = [[SelectVideo1 alloc] initWith:#"Test"];
//[self.navController pushViewController:selectVideo1 animated:YES];
SelectVideo1 *selectVideo2 = [[SelectVideo1 alloc] initWith:#"Latest News"];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UIStoryboard *tabStoryBoard = [UIStoryboard storyboardWithName:#"TabStoryboard" bundle:nil];
UIStoryboard *navStoryBoard = [UIStoryboard storyboardWithName:#"NavStoryboard" bundle:nil];
UINavigationController *navController = [navStoryBoard instantiateViewControllerWithIdentifier:#"Nav Controller"];
UITabBarController *tabController = [tabStoryBoard instantiateViewControllerWithIdentifier:#"Tab Controller"];
ViewController *redVC, *greenVC;
redVC = [[ViewController alloc] init];
greenVC = [[ViewController alloc] init];
RootController *menuController = [[RootController alloc]
initWithViewControllers:#[navController, selectVideo1, selectVideo2, tabController, newsWebView]
andMenuTitles:#[#"Test", #"Videos", #"Latest News", #"Walkthroughs", #"Official News"]];
self.window.rootViewController = menuController;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
#end
The view shows up in the menu bar, but when I click it, nothing happens. I believe the problem lies in my appdelegate and how I call the view?
If you're using a nib file to define your GuideViewController, use
GuideViewController *newsWebView = [[GuideViewController alloc] initWithNibName:#"Insert_Nib_Name_Here" bundle:nil];
If you define your GuideViewController in a storyboard, use
UIStoryboard *navStoryBoard = [UIStoryboard storyboardWithName:#"NavStoryboard" bundle:nil];
GuideViewController *newsWebView = [navStoryBoard instantiateViewControllerWithIdentifier:#"Insert_Guide_Controller_Name_Here"];
If that doesn't work, make sure your IBOutlet UIWebView is connected (control+drag from the UIWebView object in your nib file)
You can also just add the UIWebView programmatically.
In GuideViewController.h, you probably want to conform to the UIWebViewDelegate protocol. Implement the methods to control the UIWebView's functionality
#interface GuideViewController : UIViewController <UIWebViewDelegate>
In GuideViewController.m...
- (GuideViewController*)init
{
self = [super init];
if (self) {
//Adjust the frame accordingly if you don't want it to take up the whole view
self.newsWebView = [[UIWebView alloc] initWithFrame:self.view.frame];
self.newsWebView.delegate = self;
[self.view addSubview:self.newsWebView];
}
return self;
}

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.

AppDelegate and .xib are not implementing properly, but build is successful?

I really don't know how to explain this without pasting all my code, but ill give it a shot. "Assuming" my .hs and .ms are accurate, i have a feeling my .xib is not set correctly, but i cant really paste the code from that. Instead i've zipped the files and uploaded the source code. (if you are brave enough, it's here: http://bit.ly/ZtDkGi ) Im getting a successful build, but my emulator's screen is just black after the app launches.
Essentially, i had to manually add an appDelegate object. i set the class to the appropriate class - but its still not pulling. If someone would be kind enough to help, that would be great.
here's my Test_TableViewAppDelegate.h
#import <UIKit/UIKit.h>
#interface Test_TableViewAppDelegate : NSObject <UIApplicationDelegate>
{
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UINavigationController *navController;
#end
here's my new Test_TableViewAppDelegate.m
#import "Test_TableViewAppDelegate.h"
#implementation Test_TableViewAppDelegate
#synthesize window=_window;
#synthesize navController=_navController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
//self.window.backgroundColor = [UIColor whiteColor];
UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
window.backgroundColor = [UIColor greenColor];
self.window = window;
UIViewController *fvc = [[UIViewController alloc] init];
UIViewController *rootController = [[UIViewController alloc] initWithNibName:#"RootViewController" bundle:nil];
UINavigationController *nc = [[UINavigationController alloc]initWithRootViewController:rootController];
//UINavigationController *nc = [[UINavigationController alloc]initWithRootViewController:fvc];
self.navController = nc;
//[self.window addSubview: nc.view];
//[self.window makeKeyAndVisible];
self.window.rootViewController = self.navController;
[self.window makeKeyAndVisible];
return YES;
}
RootViewController.h
#import <UIKit/UIKit.h>
#interface RootViewController : UITableViewController {
NSMutableArray *petsArray;
}
#end
RootViewController.m
#import "RootViewController.h"
#interface RootViewController ()
#end
#implementation RootViewController
and last but not least, main.m ( i think this might be an issue too)
#import "Test_TableViewAppDelegate.h"
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([Test_TableViewAppDelegate class]));
}
}
thanks in advance. i'd appreciate it :D
in your delegate Test_TableViewAppDelegate
why you adding views two times to the window?
// you could remove these two lines
[self.window addSubview: nc.view];
[self.window makeKeyAndVisible];
//keep these two lines
self.window.rootViewController = self.navController;
[self.window makeKeyAndVisible];
And this view you are adding to the navigationController it is not initalized with any nib name
UIViewController *fvc = [[UIViewController alloc] init];
initialization should be like this instead in your delegate
RootViewController *rootController = [[RootViewController alloc] initWithNibName:#"RootViewController" bundle:nil];
UINavigationController *nc = [[UINavigationController alloc]initWithRootViewController:rootController];
I believe the reason that you're getting a black screen is that you are not properly allocating and initializing your navigation controller!
Instead, you should try this code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
// create the base window
UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
window.backgroundColor = [UIColor greenColor];
self.window = window;
[window release];
// this is the home page from the user's perspective
FirstViewController *fvc = [[FirstViewController alloc] init];
UINavigationController *nc = [[UINavigationController alloc]initWithRootViewController:fvc];
self.navigationController = nc;
[fvc release];
[nc release];
// show them
[self.window addSubview: nc.view];
[self.window makeKeyAndVisible];
return YES;
}
Hope this works!

Resources