UIScrollView with IUViewController dropping objects - iphone

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.

Related

IPhone iOs 5, need help getting my tab bar at the top to work

I wanted to have the tab bar at the top.
So i created a new project in XCode. Added a view and then inside that view i added (scrollbar, text and another view). See picture.
What i wanted was to have my tab bar at the top. Then in the middle would be the contents from the tab bar and below it a small copyright text. See picture.
No idea how to make this correctly. I have tried to create the UITabBarController on the fly and then assign it into the view at the top. (Top white space on the picture dedicated for the tab bar).
Here is my code to init the MainWindow.
MainWindow.h
#import <UIKit/UIKit.h>
#class Intro;
#interface MainWindow : UIViewController
#property (strong, nonatomic) IBOutlet UIScrollView *mainContentFrame;
#property (strong, nonatomic) IBOutlet UIView *mainTabBarView;
#property (strong, nonatomic) UITabBarController *mainTabBar;
#property (nonatomic, strong) Intro *intro; // Trying to get this tab to show in the tab bar
#end
MainWindow.m
#import "MainWindow.h"
#import "Intro.h"
#interface MainWindow ()
#end
#implementation MainWindow
#synthesize mainContentFrame = _mainContentFrame;
#synthesize mainTabBarView = _mainTabBarView;
#synthesize mainTabBar = _mainTabBar;
#synthesize intro = _intro;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
_intro = [[Intro alloc] init];
NSArray *allViews = [[NSArray alloc] initWithObjects:_intro, nil];
[super viewDidLoad];
// Do any additional setup after loading the view.
_mainTabBar = [[UITabBarController alloc] init];
[_mainTabBar setViewControllers:allViews];
[_mainTabBarView.window addSubview:_mainTabBar.tabBarController.view];
}
- (void)viewDidUnload
{
[self setMainTabBar:nil];
[self setMainContentFrame:nil];
[self setMainContentFrame:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
What am i missing to get this to work? Wanted the content to end up in the scrollview so that all tabs are scrollable.
iOS User Interface Guidelines say that the UITabBar has to be at the bottom of the ViewController. You should either create your own GUI for this kind of View or use the "old-fashioned" way. I would not try to hack around the UITabBar as your app may be rejacted by Apple.

tableHeaderView doesn't display UIView properly

I'm trying to add UIScrollView with paging as a header to my table, but unfortunately it is not displayed correctly.
The htableHaderView is resized to the size of my imagesScrollView, but only half of it is displayed the rest area is blank.
- (void)viewDidLoad
{
[super viewDidLoad];
ImagesViewController *imagesScrollView = [[ImagesViewController alloc] initWithNibName:#"ImagesViewController" bundle:nil];
tableView.tableHeaderView = imagesScrollView.view;
imagesScrollView = nil;
}
Thanks for helping
I tried the following code:
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UITableViewController
#end
ViewController.m
#import "ViewController.h"
#import "ImagesViewController.h"
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
ImagesViewController *imageVC = [[ImagesViewController alloc] initWithNibName:#"ImagesViewController" bundle:nil];
[[self tableView] setTableHeaderView:[imageVC view]];
imageVC = nil;
}
#end
ImagesViewController.h
#import <UIKit/UIKit.h>
#interface ImagesViewController : UIViewController
#property (strong, nonatomic) IBOutlet UIScrollView *ScrollView;
#property (strong, nonatomic) IBOutlet UIView *ViewInScrollView;
#end
ImagesViewController.m
#import "ImagesViewController.h"
#implementation ImagesViewController
#synthesize ScrollView;
#synthesize ViewInScrollView;
- (void)viewDidLoad {
[super viewDidLoad];
[[self ViewInScrollView] setFrame:CGRectMake(0, 0, 768 * 2, 400)];
[[self ViewInScrollView] setBackgroundColor:[UIColor orangeColor]];
[[self ScrollView] setContentSize:[[self ViewInScrollView] frame].size];
}
#end
ImagesViewController's xib is a view, 768 wide by 200 tall (I made an iPad-based UITableView single-view application). Inside its view is a UIScrollView, set to take up the entire [view frame] area. Then I put a UIView inside of it.
My testing gives me a header that is an orange rectangle, and I can scroll it around as you would expect. This leads me to believe that maybe you need to check the shocks/struts of your imagesScrollView in Interface Builder. Make sure all of the margins and widths are fixed/flexible as you need for it to display properly.

Many-to-one UIViewController communication. Navigation Controller Push View. Delegate or NSNotificationCenter or Class Method?

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.

UIViewController with UIView-inherited class, programmatically

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;

How to pass a variable from one view controller to another?

I have three view controllers, one root controller, one login view controller and one customers view controller. I want to pass the entered username and password in login view controller to the customers view controller. My files and code is displayed below, could you please guide me, how can access to variables set in the login view controller? Or how can I pass variables to customers view controller?
I have these class files:
/classes/MySoftwareAppDelegate.h
/classes/MySoftwareAppDelegate.m
/classes/ViewController.h
/classes/ViewController.m
/classes/LoginController.h
/classes/LoginController.m
/classes/CustomersController.h
/classes/CustomersController.m
I have these views:
/resources/MainWindow.xib
/resources/Login.xib
/resources/Customers.xib
In the AppDelegate, I have successfully inserted the sub view "Login" and it's displayed whenever the app starts.
In the login view, I enter my username and password and then click the "Login" button. When this button is clicked, an IBAction is triggered. In this IBAction, I want to change the current subview with the Customers.
Here's the code I have used:
MySoftwareAppDelegate.h
#import <UIKit/UIKit.h>
#class ViewController;
#interface MySoftwareAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
ViewController *viewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet ViewController *viewController;
#end
MySoftwareAppDelegate.m
#import "MySoftwareAppDelegate.h"
#import "ViewController.h"
#implementation MySoftwareAppDelegate
#synthesize window;
#synthesize viewController;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Override point for customization after application launch
[window addSubview:viewController.view];
[window makeKeyAndVisible];
}
- (void)dealloc {
[viewController release];
[window release];
[super dealloc];
}
#end
ViewController.h
#import <UIKit/UIKit.h>
#class LoginController;
#interface ViewController : UIViewController {
LoginController *loginController;
}
#property (nonatomic, retain) LoginController *loginController;
#end
ViewController.m
#import "ViewController.h"
#import "LoginController.h"
#implementation ViewController
#synthesize loginController;
- (void)viewDidLoad {
LoginController *tmpViewController = [[LoginController alloc] initWithNibName:#"Login" bundle:nil];
self.loginController = tmpViewController;
[self.view insertSubview:loginController.view atIndex:0];
[tmpViewController release];
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
if (self.loginController.view.superview == nil) {
self.loginController = nil;
}
// 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 {
[loginController release];
[super dealloc];
}
#end
LoginController.h
#import <UIKit/UIKit.h>
#class CustomersController;
#interface LoginController : UIViewController {
UIButton *loginButton;
UITextField *usernameTextField;
UITextField *passwordTextField;
NSMutableString *available_credits;
NSString *current_xml_element;
CustomersController *customersController;
}
#property (nonatomic, retain) IBOutlet UIButton *loginButton;
#property (nonatomic, retain) IBOutlet UITextField *usernameTextField;
#property (nonatomic, retain) IBOutlet UITextField *passwordTextField;
#property (nonatomic, retain) NSMutableString *available_credits;
#property (nonatomic, retain) NSString *current_xml_element;
#property (nonatomic, retain) CustomersController *customersController;
-(IBAction)textFieldDoneEditing:(id)sender;
-(IBAction)backgroundTap:(id)sender;
-(IBAction)loginToAccount:(id)sender;
#end
LoginController.m
#import "LoginController.h"
#import "CustomersController.h"
#implementation LoginController
#synthesize loginButton;
#synthesize usernameTextField;
#synthesize passwordTextField;
#synthesize customersController;
- (void)viewDidLoad {
UIImage *buttonImageNormal = [UIImage imageNamed:#"whiteButton.png"];
UIImage *stretchableButtonImageNormal = [buttonImageNormal stretchableImageWithLeftCapWidth:12 topCapHeight:0];
UIImage *buttonImagePressed = [UIImage imageNamed:#"blueButton.png"];
UIImage *stretchableButtonImagePressed = [buttonImagePressed stretchableImageWithLeftCapWidth:12 topCapHeight:0];
[loginButton setBackgroundImage:stretchableButtonImageNormal forState:UIControlStateNormal];
[loginButton setBackgroundImage:stretchableButtonImagePressed forState:UIControlStateHighlighted];
}
- (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 {
[usernameTextField release];
[passwordTextField release];
[super dealloc];
}
-(IBAction)textFieldDoneEditing:(id)sender {
[sender resignFirstResponder];
}
-(IBAction)backgroundTap:(id)sender {
[usernameTextField resignFirstResponder];
[passwordTextField resignFirstResponder];
}
-(IBAction)loginToAccount:(id)sender {
// bla bla bla... Login check process is done here
CustomersController *tmpViewController = [[CustomersController alloc] initWithNibName:#"Customers" bundle:nil];
self.customersController = tmpViewController;
[self presentModalViewController:tmpViewController animated:YES];
[self.view removeFromSuperview];
[tmpViewController release];
}
#end
As you can see above, in LoginController.m's loginToAccount method, I am checking the login info and then setting the new view controller for the "customers" sub-view.
Then I am removing the current "Login" subview from the super view but don't know how to add the new "Customers" sub view.
In MainWindow.xib, I have one view controller which is linked to ViewController class and it's the root contoller.
Any help is appreciated. Because I am new to Objective-C and iPhone programming, please do your best to explain considering a novice programmer :)
Thanks again.
Okay, let me answer my question. I just found the answer on StackOverFlow.com
In the view controller which is going to load the next view controller, just add these lines:
NextController *tmpViewController = [[NextController alloc] initWithNibName:#"NextView" bundle:nil];
tmpViewController.enteredUsername = usernameTextField.text;
tmpViewController.enteredPassword = passwordTextField.text;
I'd say that better way is to have separate class for storing globally needed data (and that would be compliant with MVC model).
For example you can store you login information in your MySoftwareAppDelegate, which is easily accessible with [[UIApplication sharedApplication] delegate] call from any part of your application.
It all depends on how serious the data you want to pass it. For a quick variable (maybe a settings change in a modal view controller) TamTam's solution makes the most sense. You alloc/init'ed it, you got the variable, why not access it properties? That same (modally presented) view controller might pass variables back via a delegate pattern.
If you're data needs to be system wide, you can use the singleton pattern. Using "[[UIApplication sharedApplication] delegate]" gets the application delegation (which is a singleton), and many people stuff their variables there for convenience. However, your app delegate wasn't designed for this, and so it's considered bad form. Create your own singleton if your apple isn't a quickie.
If you use a persistent data store like sql, plists or coredata, you can put your system wide data there.