Two really quick questions, I searched the web but couldn't find answers..
Is there any way to call block animations to a view from a class that is different from the viewController of that view. I also couldn't figure out how to add a subview to that view in a method that exists in a different class than the viewController ( the only way I can do it is [self.view addSubview:xxxxx]; in the viewController for my view)
Any help would be greatly appreciated and helpful.
Thank you!!
Keep a reference to YourViewController instance on ApplicationDelegate, and modify its subviews in OtherClass.
//in ApplicationDelegate.h
#property (strong, nonatomic) YourViewController *ref;
//in ApplicationDelegate.m
#synthesize ref;
self.ref = [[YourViewController alloc] initWithNibName:nil bundle:nil];
//in YourViewController.h
#property (retain, nonatomic) UIImageView *myImageView;
//in YourViewController.m
#synthesize myImageView;
//in OtherClass.m
[UIView animateWithDuration:DURATION delay:DELAY
options:OPTION
animations:^(void)
{
[[UIApplication sharedApplication] delegate].ref.myImageView.center=CGPointMake(100,100);
}
completion:^(BOOL finished)
{
[[UIApplication sharedApplication] delegate].ref.myImageView.center=CGPointMake(200,200);
}];
Well if the view that you're calling on the animation on also has a view controller then what you could do is create a method in that view controller that makes that animation. then in the other view that you want to call that animation you could do
[otherViewController animationMethod];
Honestly that's the best i can think of.
Related
I am trying to change views when I swipe. I have the swipe working find as I have tested this by changing the background color.
Since then however I have added a new view.nib and set the class to be the same as the current view.
Inside this classes .h file I have done this
#interface MasterViewController : UIViewController <UIGestureRecognizerDelegate>{
UIView *myView;
UIView *secondView;
}
#property (strong, nonatomic) IBOutlet UIView *myView; // attached to Viewcontroller nib
#property (strong, nonatomic) IBOutlet UIView *secondView; // attached to the secondView
- (void)swipedScreen;
MyView is the main view that appears first, secondView is the view of the nib that I have created and changed its class to relate to this view.
From there I have done this in the .m file
- (void) setupSwipeGestureRecognizer {
UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipedScreen)];
swipeGesture.direction = (UISwipeGestureRecognizerDirectionRight|UISwipeGestureRecognizerDirectionLeft);
[myView addGestureRecognizer:swipeGesture];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.title = #"Prototype";
[self setupSwipeGestureRecognizer];
}
- (void)swipedScreen
{
// Not sure what to do here.
[[NSBundle mainBundle] loadNibNamed:#"SecondView" owner:self options:nil];
}
I just dont know what to do in swipedScreen method to get the secondView to appear.. I would like to animate this view to slid in from the right.. but at the moment that comes secondary to actually just getting the view to appear... not sure what I am doing wrong here but obviously its something quite fundamental.
any help would be greatly appreciated.
As I commented:
- (void)swipedScreen
{
[UIView animateWithDuration:3.0f delay:0 options:UIViewAnimationOptionCurveLinear
animations:^{
secondView.frame = CGRectMake(180, secondView.frame.origin.y, secondView.frame.size.width, secondView.frame.size.height);
}
completion:^(BOOL finished){
myView.hidden = YES;
}];
}
Actually, you'll have to change the X, Y, Width and height values as you want to animate, and when it's completed, I set the main view - myView - hidden.
I'm a beginner with Xcode and Objective-C, i want to make a view controller in code without a nib file and shape it how i want. Currently with this very simple code I can't seem to even change the background color because of EXC_BAD_ACCESS.
I read on internet it is something with memory management but I can't seem to find the fix for this. Pieces of my code:
AppDelegate.h
#import <UIKit/UIKit.h>
#import "DefaultViewController.h"
#class DefaultViewController;
#interface AppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UIViewController *rootViewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UIViewController *rootViewController;
#end
AppDelegate.m
#synthesize window = _window;
#synthesize rootViewController = _rootViewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIViewController *rvc = [[DefaultViewController alloc] init];
self.rootViewController = rvc;
[rvc release];
[self.window addSubview:self.rootViewController.view];
// Override point for customization after application launch.
[self.window makeKeyAndVisible];
return YES;
}
- (void)dealloc
{
[_window release];
[_rootViewController release];
[super dealloc];
}
The view controller I made via, right click -> new file and UIViewController subclass without xib! In the loadView I only try this:
self.view.backgroundColor = [UIColor redColor];
The problem could be that the rootViewController doesn't have an initialized view. Hard to tell, since you don't show the code of the DefaultViewController. It could also be another error in DefaultViewController.
FWIW, you have two obsolete ivars:
#interface AppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UIViewController *rootViewController;
}
You can delete these, since you synthesize _window and _rootViewController and never use the above.
There are a few issues with your code. But first the key problem you are getting EXC_BAD_ACCESS is because you are calling self.view.backgroundColor inside the loadView. If you override loadView, you must construct your view hierarchy inside the method. By not creating a view hierarchy in that method you are calling backgroundColor on a view that does not exist. Instead completely remove the loadView method or comment it out and move self.view.backgroundColor into the viewDidLoad method. (Remember even an empty loadView method will be a problem, you need to remove it or comment it out)
Second.. change your code to
self.rootViewController = rvc; to self.window.rootViewController = rvc;
BTW, once you add a view controller you don't need to add the view of the rootViewController as a subview to the window again. Assigning a view controller to the rootViewController property installs the view controller's view as the content view of the window.
Third. When you are initializing DefaultViewController you do
UIViewController *rvc = [[DefaultViewController alloc] init];
dont do that, instead do
DefaultViewController *rvc = [[DefaultViewController alloc] init];
Change the code so it's
self.window.rootViewController = rvc;
[self.window makeKeyAndVisible];
return YES;
What's inside your DefaultViewController? If you are not using a nib file, did you implement -(void)loadView ?
You should call:
UIViewController *rvc = [[DefaultViewController alloc]
initWithNibName:#"yournib" bundle:nil];
to load the NIB view. Otherwise, your rvc.view will be nil.
Sorry, I overlooked.
The answer is: you should not call self.view.backgroundColor = [UIColor redColor]; within - (void)loadView since self.view is nil firstly at this stage. He has to show that he has correctly created at least self.view = [[UIView alloc] init] in loadView.
Is it possible to present a modal view from a UIView or a UIWindow in the same .xib?
here is my code:
#interface MyViewController : UIViewController <UIWebViewDelegate> {
IBOutlet UIVIew *myView
}
#property (nonatomic, retain) UIView *myView;
- (void)somefunction;
And my function:
- (void)somefunction {
//here i need to make my view1 gets presented by a modal view style.
}
You need to add IBOutlets for your views. In your MyViewController.h file:
...
IBOutlet UIView *firstView;
IBOutlet UIView *secondView;
...
Then you connect the outlets using Interface Builder (or Xcode 4). After that, in your implementation file you manually hide or show the view that you want.
PresenterViewController.m:
- (void)ShowSecondView{
//Initialize the view controller
MyViewController *modalView = [[MyViewController alloc] initWithNibNamed:#"MyViewController" bundle:nil];
//Hide or show whatever view(s) you want
[modalView.firstView setHidden:YES];
[modalView.secondView setHidden:NO];
//Present the view controller modally
[self presentModalViewController:modalView animated:YES];
//Don't forget memory management!
[modalView release];
}
You may need to tweak this code a little bit, but this is the general idea.
I'm attempting to switch views with an iPhone application- I have a parent view controller, SuperviewController, and then two views that I want to switch within that parent view, MainMenuController and MainGameController.
*EDIT*: I am now using navigation controllers:
SuperviewController.m
viewDidLoad
self.mainMenuController = [[MainMenuController alloc] initWithNibName:#"MainMenu" bundle:nil];
[[self navigationController] pushViewController:self.mainMenuController animated:NO];
switchToMainGame
self.mainGameController = [[MainGameController alloc] initWithNibName:#"MainGame" bundle:nil];
[[self navigationController] pushViewController:self.mainGameController animated:NO];
The app loads correctly with the mainMenu.xib. However, when calling switchToMainGame, nothing happens- it's as if XCode forgot what mainGameController is.
Thanks for any help.
You might consider swapping view controllers not views, using UINavigationController.
In your AppDelegate.h
#interface AppDelegate : NSObject <UIApplicationDelegate>
{
UIWindow *window;
UINavigationController *navigationController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#end
And in -[AppDelegate applicationDidFinishLaunching:] instantiate navigationController, thus:
[self setNavigationController:[[UINavigationController alloc] initWithRootViewController:mySuperviewController]];
[[self navigationController] setNavigationBarHidden:YES];
// Configure and show the window
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
Then within SuperviewController.m you can instantiate your MainMenuController and MainGameController, as you already do. To start with MainMenuController you could do this in SuperviewController -viewDidLoad
[[self navigationController] pushViewController:[self mainMenuController] animated:YES];
You would need to add some smarts to switch directly between mainMenuController and mainGameController - but it wouldn't be difficult.
So as not to reload nibs again and again, consider defining accessor methods like this:
- (MainGameController*) mainGameController
{
if (mainGameController == nil)
{
mainGameController = [[MainGameController alloc] initWithNibName:#"MainGame" bundle:nil];
}
return mainGameController;
}
Also, bear in mind that switching between sibling view controllers involve popping current view controller (e.g., mainMenuController) before pushing other view controller (e.g., mainGameController).
I have a TabBar application with several nibs, most with a NavBar. It works pretty well, except for the "views" that are inside the "More" section of the tabBar.
As expected, it will put a NavBar to return to the "More" list, as well as the NavBar i've placed in the nib.
I've tried to remove the view controllers from the moreNavigationBar and put the top controller from my nib's navBar, but I get and extra view from somewhere:
- (void)viewDidLoad {
TestAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
UITabBarController *ctrl = appDelegate.rootController;
UINavigationController *navCtrl = ctrl.moreNavigationController;
[navCtrl popToRootViewControllerAnimated: NO];
[navCtrl pushViewController: navController.topViewController animated: YES];
navController = navCtrl;
[super viewDidLoad];
}
My AppDelegate:
#interface TestAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UITabBarController *rootController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UITabBarController *rootController;
The MainWindow nib is that of a Window-based project with a TabBarController, linked to the rootController in my app delegate.
The other nibs have a view + navigationController and I have a UITableViewController subclass as my Root View Controller.
If I could get this to work it wouldn't still solve my problem, because I want to allow the user to place this anywhere in the tabBar, so, I must have some way of knowing if there's a navigationBar.
So, my question is, how do you know if there's a navigationBar (in this case, if the tabBar's navigationBar is being shown) and, if so, how do I get my navigationController to "become" the tabBar's navigationController?
Or, if you have another idea on how to solve this problem, i'd also be appreciated :)
The recommendation from apple is that you have the TabBar controller contain the Navigation controllers and not the other way around. I have a setup more or less like this, and I have the More tab hold a Nav controller, basically like this:
#interface SomethingNavViewController : UIViewController {
UIView* aview;
UINavigationController *navigationController;
}
#property (nonatomic, retain) IBOutlet UIView *aview;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#end
In the NIB, I have a separate Nav controller in the view of the more panel, I haven't replaced the tab bar item's view with a nav controller view, I've just added a Nav controller to the view.
In my implementation file, I have:
- (void)viewDidLoad {
[super viewDidLoad];
[[self view] addSubview:[navigationController view]];
SomeOtherController *aController = [[[SomeOtherController alloc ] initWithNibName:#"SomeOtherController" bundle:nil ] autorelease];
aController.title = #"Artwalks";
// lots of application logic here.
[self.navigationController pushViewController:aController animated:YES];
[self.navigationController setDelegate:self];
}
One key thing about this is that I have implemented the navigationController's delegate method, which is really handy when you're just inserting the nav controller. I found when I didn't do this, my views don't get viewDidAppear messages, so I implemented the protocol and added this method:
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if ([viewController respondsToSelector:#selector(viewDidAppear:)]) {
[viewController viewDidAppear:animated];
}
}
and that solved a variety of my lingering problems.
Anyway, I hope this answer gave you the detail you needed. IF it didn't, please give more details about your question. I'm not quite sure what but I get and extra view from somewhere met, but it sounds like something I encountered before I found this solution.