I'm using a library, which is a class that inherits from UIView. How do I programmatically create an UIViewController that uses this class, and not a normal UIView?
The ViewController's .h file looks as follows:
#import <UIKit/UIKit.h>
#import "PLView.h"
#interface HelloPanoramaViewController : UIViewController {
IBOutlet PLView * plView;
}
#property (nonatomic, retain) IBOutlet PLView *plView;
#end
The .m file as follows:
#import "HelloPanoramaViewController.h"
#implementation HelloPanoramaViewController
#synthesize plView;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do stuff here...
}
- (void)dealloc
{
[plView release];
[super dealloc];
}
#end
And then I should use a nib to let "plView variable pointing to the view".
But without using Interface Builder, how would I do this programmatically? How could I let this UIViewController create an PLView, instead of an UIView?
your UIViewController will something that looks like
#import "HelloPanoramaViewController.h"
#implementation HelloPanoramaViewController
- (void)loadView
{
self.view = [PLView plview]//or whatever it takes to create the plview.
}
- (void)viewDidLoad
{
//create more objects
}
- (void)viewDidUnload
{
//release unwanted objects that were created viewDidLoad
}
-(void) dealloc
{
// release all
[super dealloc];
}
#end
more info... here
In the place where you create your viewController, also create an instance of your custom view, and then set that view to your controller's view:
HelloPanoramaViewController *controller = [[HelloPanoramaViewController alloc] init];
PLView *view = [[PLView alloc] init];
controller.view = view;
Related
I have a really weird issue with UIScrollView and added UIViewControllers.
It looks like that when UIViewControllers are added to UIScrollView for paging, the UIViewController drops all its added objects.
In the project i have a storyboard with two views and they are connected correctly to the corresponding code.
I know that the code doesn't move the added UIViewController to the correct X, but in this test im only adding one UIViewController so it doesnt matter.
This is the scroll code .h:
#import <UIKit/UIKit.h>
#import "TestViewController.h"
#interface ViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
#property (weak, nonatomic) IBOutlet UIPageControl *pageControl;
#property (strong, nonatomic) NSMutableArray *scrollController;
#end
This is the scroll code .m:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.scrollController = [[NSMutableArray alloc] init];
}
- (void)viewDidAppear:(BOOL)animated {
//just adding two controllers
TestViewController *first = [[TestViewController alloc] init];
[self.scrollView addSubview:first.view];
[self.scrollController addObject:first];
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * self.scrollController.count, self.scrollView.frame.size.height);
self.pageControl.numberOfPages = [self.scrollController count];
}
- (void)scrollViewDidScroll:(UIScrollView *)sender {
// Update the page when more than 50% of the previous/next page is visible
CGFloat pageWidth = self.scrollView.frame.size.width;
int page = floor((self.scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
self.pageControl.currentPage = page;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
This is the viewcontroller code .h:
#import <UIKit/UIKit.h>
#interface TestViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *lblMsg;
#end
This is the viewcontroller code .m:
#import "TestViewController.h"
#interface TestViewController ()
#end
#implementation TestViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(#"Label: %#", self.lblMsg);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
The output in log is:
Label: (null)
Anybody able to see what im doing wrong?
If you create your ViewController using
TestViewController *first = [[TestViewController alloc] init];
your label (IBOutlet) won't be linked.
Navigate to your storyboard in Xcode, select your viewcontroller and assign a unique storyboard id ("myIdentifier") in the identity inspector in utilities on the right hand side.
Try
NSString *identifier = #"myIdentifier";
TestViewController *first = [self.storyboard instantiateViewControllerWithIdentifier:identifier];
Have a look at the documentation:
Each view controller object is the sole owner of its view. You must
not associate the same view object with multiple view controller
objects. The only exception to this rule is that a container view
controller implementation may add this view as a subview in its own
view hierarchy. Before adding the subview, the container must first
call its addChildViewController: method to create a parent-child
relationship between the two view controller objects.
First of all I have to state that I am a complet newbeginner at Objective-C and iOS-programming.
Okey, so I have a simple app running, but I am facing some problems trying to switch fron one view to another. The plan is to do the "login-logic" in the view called RootView and then send the user to the DataViewController afterwards. I've tried googeling around, but no matter how I try to implement the code, it makes Xcode cry.
How can I achive the wanted effect?
Here are the following files:
RootViewController.h
#import <UIKit/UIKit.h>
#interface RootViewController : UIViewController <UIPageViewControllerDelegate>
#property (strong, nonatomic) UIPageViewController *pageViewController;
#end
RootViewController.m
#interface RootViewController ()
#end
#implementation RootViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
#end
DataViewController.h
#import <UIKit/UIKit.h>
#interface DataViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *dataLabel;
#property (strong, nonatomic) id dataObject;
#end
DataViewController.m
#import "DataViewController.h"
#interface DataViewController ()
#end
#implementation DataViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
#end
It is pretty much just an empty template, but for some reason it does not work with the solutions I've tried earier.
When you are ready to move on, in your RootViewController (can be in any method you like):
GeoPartyDataViewController *dataController = [[GeoPartyDataViewController alloc] initWithNibName:#"GeoPartyDataViewController.xib" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:dataController animated:TRUE];
Don't forget to have #import "DataViewController.h" in your RootViewController.m.
An assumption made base on the info you gave so far, your DataViewController has an associated .xib file named GeoPartyDataViewController.xib. This is just one example. If you are working with storyboards, or some other mechanism, let me know in the comments.
First you need to add GeoPartyDataViewController.h to RootViewController.m such like
#import "GeoPartyDataViewController.h"
And now for go to GeoPartyDataViewController, you need to create instance of it .
GeoPartyDataViewController *obj =[[GeoPartyDataViewController alloc] initWithNibName:#"GeoPartyDataViewController.xib" bundle:[NSBundle mainBundle]];
[self presentViewController:obj animated:YES completion:nil];
Above code write in relavent place that you want to go on GeoPartyDataViewController.
Made it work with this:
- (void)viewDidAppear:(BOOL)animated
{
UIStoryboard *storyboard = self.storyboard;
UIViewController *mtvc = [storyboard instantiateViewControllerWithIdentifier:#"GeoPartyDataViewController"];
[self presentViewController: mtvc animated:NO completion:nil];
}
I want to pass data from second tab to first tab using delegates.But delegate method not triggered.here is the code (I m using storyboard)
in SecondViewController.h
#import <UIKit/UIKit.h>
#class SecondViewController;
#protocol SecondViewControllerDelegate <NSObject>
-(void) sliderValueDidChanged: (SecondViewController *)controller data:(float) sliderValue;
#end
#interface SecondViewController : UIViewController{
__weak id<SecondViewControllerDelegate> delegate;
}
- (IBAction)sliderPressed:(id)sender;
#property (weak, nonatomic) IBOutlet UISlider *mySlider;
#property(weak,nonatomic) id<SecondViewControllerDelegate> delegate;
#end
in SecondViewController.m
#import "SecondViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
#synthesize mySlider;
#synthesize delegate;
- (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.
}
- (void)viewDidUnload
{
[self setMySlider:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (IBAction)sliderPressed:(id)sender {
float value = mySlider.value;
[self.delegate sliderValueDidChanged:self data:value];
NSLog(#"%#",self.delegate);
}
#end
FirstViewController.h
#import <UIKit/UIKit.h>
#import "SecondViewController.h"
#interface FirstViewController : UIViewController<SecondViewControllerDelegate>
#property (weak, nonatomic) IBOutlet UILabel *myLabel;
#end
in FirstViewController.h
#import "FirstViewController.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
#synthesize myLabel;
- (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.
SecondViewController *svc = [[SecondViewController alloc]init];
svc.delegate = self;
}
- (void)viewDidUnload
{
[self setMyLabel:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
-(void) sliderValueDidChanged: (SecondViewController *)controller data:(float) sliderValue{
myLabel.text = [[NSString alloc]initWithFormat:#"%f",sliderValue];
NSLog(#"delegate called");
}
#end
I am trying to set a slider in second tab and send the sider value to first tab which has a label. self.delegate printing null and delegate method never called.
Simply enough, as you already have the delegation code, only change the line where you create a SecondViewController object. Rather than creating a new one, you should have a reference to the one that the tab bar will show.
In the viewDidLoad of FirstViewController,
Change
SecondViewController *svc = [[SecondViewController alloc]init];
to
//assuming you have 2 view controllers in the tab bar controller, first being FirstViewController
SecondViewController *svc = [self.tabBarController.viewControllers objectAtIndex:1];
and that should do it
How do you actually get to the second tab? You're creating an instance of it in viewDidLoad, but if you switch tabs, that instance won't be used to show on screen. The system will create another instance which it'll use. You can access this by accessing the tab bar controller's viewcontrollers property and checking for SecondViewController.
EDIT: You could also question your design. I don't know much about your app, but chances are your first tab shouldn't really be the delegate for your second tab. If you want to pass along data, consider using NSNotificationCenter or persistent storage.
I have a UIViewController "NavigationViewController" that is added as a subview of my "FirstViewController" that takes up the whole screen (i.e. similar to the Flipboard Navigation controller in the iPad application). Many views are added and removed based on what selection the user makes. I want to be able to push a view controller to the "FirstViewController" navigationController from within the "many views" that are added. In this case the "FeaturedViewController" is one of those many views that can be selected. It inherits ContentViewController where the delegate protocol is defined.
TL;DR I want to access the navigationcontroller in the first view to push a view from the added subview "FeaturedViewController".
Here is a visual representation:
Here is the my code from:
Here is my current attempt that does not work. Note, I took some code out relating to the "Navigation Controller"
/* First View Controller */
#import <UIKit/UIKit.h>
#import "ContentViewController.h"
#interface ViewController : UIViewController <BaseViewDelegate, ContentViewDelegate>
{
IBOutlet UINavigationController *navigationController;
ContentViewController *contentView;
}
#property (strong, nonatomic) IBOutlet UINavigationController *navigationController;
#property (strong, nonatomic) ContentViewController *contentView;
---------------------------------------------------------
#import "ViewController.h"
#import "NavigatorViewController.h"
#import "BinViewController.h"
#implementation ViewController
#synthesize navigationController, contentView;
static NSArray *viewArray = nil;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.navigationController.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
[self.view addSubview:navigationController.view];
// Navigation View is used to navigate throughout the entire application
NavigatorViewController *navController = [[NavigatorViewController alloc] init];
contentView = [[ContentViewController alloc] init];
contentView.delegate = self;
// Add the views to the array (using ARC)
viewArray = [NSArray arrayWithObjects:navController, contentView, nil];
}
-(void)displayNavigator
{
// Get the right view controller
UIViewController *viewController = [viewArray objectAtIndex:0];
// Add the subview to the view
[self.view addSubview:viewController.view];
}
-(void)pushViewController:(UIViewController *)viewController
{
NSLog(#"First View Push View Controller called");
[self.navigationController pushViewController:viewController animated:YES];
}
#end
/* Content View Controller */
#class ContentViewController;
#protocol ContentViewDelegate <NSObject>
-(void)pushViewController:(UIViewController *)viewController;
#end
#interface ContentViewController : UIViewController
{
__weak id <ContentViewDelegate> delegate;
}
#property (weak) __weak id <ContentViewDelegate> delegate;
- (void)pushView:(UIViewController *)viewController;
#end
---------------------------------------------------------
#import "ContentViewController.h"
#import "BinViewController.h"
#implementation ContentViewController
#synthesize delegate;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)pushView:(UIViewController *)viewController
{
NSLOG(#"Push View from ContentViewController");
if ([delegate respondsToSelector:#selector(pushViewController)])
[delegate pushViewController];
}
#end
/* View that is added to the navigator view (it inherits ContentViewController where the delegate protocol is defined)*/
#import <UIKit/UIKit.h>
#import "ContentViewController.h"
#interface FeaturedViewController : ContentViewController <CustomPagingDelegate>
#end
---------------------------------------------------------
#import "FeaturedViewController.h"
#import "BinViewController.h"
#implementation FeaturedViewController
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void) touchUpInsideItemAtIndex:(NSUInteger)itemIndex
{
// [[[[[self view] superview] superview] superview] removeFromSuperview];
NSLOG(#"Touch up inside from featured view");
BinViewController *binViewController = [[BinViewController alloc] init];
[self pushView:binViewController];
}
#end
Many to one or one to many sounds like easiest route would be to use NSNotificationCenter.
Hy,
There is no problmen with changing the nib but when I'm in the nib-File with the OPGL ES view my buttons that are integrated in this view won't work. When I press one the application crashes.
This is the Code how I change the View to the Second Nib:
- (IBAction)drawEAGLView:(id)sender {
NSArray* nibViews = [[NSBundle mainBundle] loadNibNamed:#"settingsViewController" owner:self options:nil];
EAGLView* glView = [ nibViews objectAtIndex: 1];
self.view = glView;
[glView startAnimation];}
The Animation is working .
This is the Code of the ViewController where the Button is declared:
SettingsViewController.h:
#import <UIKit/UIKit.h>
#interface SettingsViewController : NSObject {
IBOutlet UIButton *wowButton;
}
#property(nonatomic,retain) IBOutlet UIButton *wowButton;
- (IBAction)wowButtonPressed:(id)sender;
int testvarAnimation;
int animNext;
#end
SettingsViewController.m:
#import "SettingsViewController.h"
#implementation SettingsViewController
#implementation SettingsViewController
#synthesize wowButton;
- (IBAction)wowButtonPressed:(id)sender{
NSLog(#"TOUCHED");
//testvarAnimation = 1;
animNext =1;
}
- (void)dealloc {
[wowButton release];
[super dealloc];
}
#end
Here I show you how I connected the Functions and the Outlets:
http://s3.imgimg.de/uploads/screenshotConna91ea645png.png
Please tell me If you need more informations.
Thanks
Hy I solved my problem, I rewrote my drawEAGLView Methode:
- (IBAction)drawEAGLView:(id)sender {
SettingsViewController *sViewController = [[SettingsViewController alloc] initWithNibName:#"SettingsViewController" bundle:nil];
[[self.view superview] addSubview:sViewController.view];
}
I also corrected my SettingsViewController.h:
#import <UIKit/UIKit.h>
#class EAGLView;
#interface SettingsViewController : UIViewController {
IBOutlet UIButton *wowButton;
EAGLView *glview;
}
#property(nonatomic,retain) IBOutlet UIButton *wowButton;
#property (nonatomic, retain) IBOutlet EAGLView *glView;
- (IBAction)wowButtonPressed:(id)sender;
int testvarAnimation;
int animNext;
#end
And last but not least I changed my SettingsViewController.m:
#import "SettingsViewController.h"
#import "EAGLView.h"
#implementation SettingsViewController
#synthesize wowButton, glView;
- (IBAction)wowButtonPressed:(id)sender{
NSLog(#"TOUCHED");
//testvarAnimation = 1;
animNext =1;
}
- (void)viewDidLoad {
glView.animationInterval = 1.0 / 60.0;
[glView startAnimation];
[super viewDidLoad];
}
- (void)dealloc {
[wowButton release];
[super dealloc];
}
#end
I also changed my Nib file. I removed the ViewController and set the type of the File's Owner to my viewController named "SettingsViewController". I connected the File's Owner Outlet view with the EAGLView and the button with the SettingsViewControllers wowButtonPressed Method
I hope I could help also someone else,
Thanks
Here is the right solution for this problem:
First you have to create a parnet object of your view you want to be shown as first.
You need to do this in the header file of the second view.
//
// SettingsViewController.h
// NeheTutorial2
//
// Created by Global Sound on 05.04.11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import <UIKit/UIKit.h>
#class EAGLView;
#class mobilesynthViewController;
#interface SettingsViewController : UIViewController {
IBOutlet UIButton *wowButton;
IBOutlet UIButton *optiButton;
EAGLView *glView;
//mobilesynthViewController *mViewController;
mobilesynthViewController *parent;
}
#property(nonatomic,retain) IBOutlet UIButton *wowButton;
#property(nonatomic,retain) IBOutlet UIButton *optiButton;
#property (nonatomic, retain) IBOutlet EAGLView *glView;
//#property(nonatomic,retain) IBOutlet mobilesynthViewController *mViewController;
#property (nonatomic, retain) mobilesynthViewController *parent;
- (IBAction)wowButtonPressed:(id)sender;
- (IBAction)optiButtonPressed:(id)sender;
int testvarAnimation;
int animNext;
int musicOn;
int isAnimating;
float zaehler;
#end
Now in the implemetaion File you need to add the parent object to your function:
#import "SettingsViewController.h"
#import "EAGLView.h"
//#import "mobilesynthViewController.h"
#implementation SettingsViewController
#synthesize wowButton, optiButton, glView;//,mViewController;
#synthesize parent;
- (IBAction)wowButtonPressed:(id)sender{
NSLog(#"TOUCHED");
[parent startThread];
[parent showbButtonStop];
testvarAnimation = 0;
animNext =1;
//musicOn =1;
}
- (IBAction)optiButtonPressed:(id)sender{
NSLog(#"OPTIONS ON");
[self dismissModalViewControllerAnimated:YES];
[parent showbButton];
//mobilesynthViewController *aRootViewController = [[mobilesynthViewController alloc] initWithNibName:#"mobilesynthViewContoller" bundle:nil];
//[self setRootViewController:aRootViewController];
//[aRootViewController release];
//mobilesynthViewController *mViewController = [[mobilesynthViewController alloc] initWithNibName:#"mobilesynthViewController" bundle:nil];
//[[self.view superview] addSubview:mViewController.view];
//self.view = mViewController;
//CGRect rect = [[UIScreen mainScreen] applicationFrame];
//mViewController = [[mobilesynthViewController alloc] initWithFrame:CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height)];
//self.view = mViewController;
}
- (void)viewDidLoad {
glView.animationInterval = 1.0 / 60.0;
[glView startAnimation];
[super viewDidLoad];
}
/*
- (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;
}
*/
- (void)dealloc {
[wowButton release];
[optiButton release];
[super dealloc];
}
#end
In my case I'm calling a other function in the main View of my program. When the button in the second view is pressed the function in the first view is called through the the parent object
[parent startThread];
Again the startThread methode was declerated in another view.
I hope I could help you.