Change size of UIViewTable to accommodate for AdWhirl Ad - iphone

I am trying to change the size of my UITableView. I have an ad on the bottom of my view, and when I scroll, the ad scrolls along with it. I was wondering how I can change the size of the UITableView so the ad will always remain on the bottom of the view regardless of whether the UITableView is being scrolled or not. I have tried changing the size of the frame of the TableView, but this doesn't work.
- (void)viewDidAppear:(BOOL)animated
{
tableView.frame = CGRectMake()...
}
I also tried changing it in the scrollViewDidScroll: selector, but no luck. Is there anyway I can change the height so it doesn't conflict with my ad on the bottom? Thanks!

With UITableViewControllers self.view == self.tableView. This is a problem in your case because the desired effect you want requires sibling views (two views added to a common superview) but there is no "superview" for self.tableView.
You have to create a new UIViewController subclass that has a UITableView and your ad view as two subviews. You will need to handle things like setting the data source and delegate for the table view, as well as deselecting table view cells when the controller appears. This is a little more work and requires some care, but is definitely doable.
I've thrown together a quick example below that will get you started:
// Header
#interface CustomTableViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
- (id)initWithStyle:(UITableViewStyle)tableViewStyle;
#property (nonatomic, readwrite, retain) UITableView* tableView;
#end
// Source
#interface CustomTableViewController()
#property (nonatomic, readwrite, assign) UITableViewStyle tableViewStyle;
#end
#implementation CustomTableViewController
#synthesize tableView;
#synthesize tableViewStyle = _tableViewStyle;
- (id)initWithStyle:(UITableViewStyle)tableViewStyle {
if ((self = [super initWithNibName:nil bundle:nil])) {
_tableViewStyle = tableViewStyle;
}
return self;
}
- (void)loadView {
[super loadView];
self.tableView = [[UITableView alloc] initWithStyle:self.tableViewStyle];
self.tableView.autoresizingMask = (UIViewAutoresizingMaskFlexibleWidth
| UIViewAutoresizingMaskFlexibleHeight);
self.tableView.delegate = self;
self.tableView.dataSource = self;
[self.view addSubview:self.tableView];
// Create your ad view.
...
adView.autoresizingMask = (UIViewAutoresizingMaskFlexibleWidth
| UIViewAutoresizingMaskFlexibleTopMargin);
[self.view addSubview:adView];
[adView sizeToFit];
self.tableView.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height - adView.frame.size.height);
adView.frame = CGRectMake(0, self.view.bounds.size.height - adView.frame.size.height, self.view.bounds.size.width, adView.frame.size.height);
[self.tableView reloadData];
}
- (void)viewDidUnload {
self.tableView = nil;
[super viewDidUnload];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSIndexPath* selectedIndexPath = [self.tableView indexPathForSelectedRow];
if (nil != selectedIndexPath) {
[self.tableView deselectRowAtIndexPath:selectedIndexPath animated:animated];
}
}
#end

Simple way to solve this problem is just use .XIB file for your UITableView and then you change the height very easily using Interface Builder.
If you dont have IB file then please go through this post: How do I resize the UITableView's height dynamically?

Related

'EXEC_BAD_ACCESS' in Table View, "[TasksPageViewController tableView:numberOfRowsInSection:]"

I've been trying to solve this bad reference for 2 days now, but I cannot find a fix.
My application is a basic to-do list with several pages (UIPageControl) for different categories and a first page for statistics about the tasks the user has finished. (if you got 3 categories, you end up with 4 pages).
It loads an array of categories from NSUserDefaults, which can be modified by a modal view accessed through a UIButton just like the (i) in the wheather app.
The Page Control is built by the ViewController class, (which is the primary view). For each element in the array of categories, the view controller generates a new TasksPageViewController class instance and instantiates a storyboard view for it.
Everything was working fine untill I put a UITableView in the TasksPageViewController view in storyboard and linked its dataSource to the same class.
After implementing the required classes for the UITableView dataSource in the TasksPageViewController, it runs fine, but if I try to go to the modal view for modifying the categories, when I press DONE (and it should reload the ViewController and rebuild the many pages for the UIPageControll), the application crashes with a EXEC_BAD_ACCESS.
Debugging with NSZombiesEnabled, I got:
2012-02-12 18:55:49.460 Pontinhos[25601:fe03] *
-[TasksPageViewController tableView:numberOfRowsInSection:]: message sent to deallocated instance 0x68c3040
But I don't really know how to proceed, I don't know which object that have been released I'm calling.
The scripts are the following:
ViewController.h
#import <UIKit/UIKit.h>
#import "MainPageViewController.h"
#import "TasksPageViewController.h"
#interface ViewController : UIViewController{
IBOutlet UIScrollView *scrollView;
IBOutlet UIPageControl *pageControl;
NSMutableArray * views;
// To be used when scrolls originate from the UIPageControl
BOOL pageControlUsed;
}
#property (nonatomic, retain) IBOutlet UIScrollView *scrollView;
#property (nonatomic, retain) IBOutlet UIPageControl *pageControl;
#property (nonatomic, retain) NSMutableArray *views;
- (void)scrollViewDidScroll:(UIScrollView *)scrollView;
- (IBAction)changePage;
#end
ViewController.m
#import "ViewController.h"
#implementation ViewController
#synthesize scrollView;
#synthesize pageControl;
#synthesize views;
//carrega views que estão na array.
- (void)viewDidLoad
{
[super viewDidLoad];
//LoadCategories
NSUserDefaults *data = [NSUserDefaults standardUserDefaults];
NSMutableArray *categories = [[NSMutableArray alloc] initWithArray:[data objectForKey:#"categories"]];
// MAIN PAGE
MainPageViewController *mainpage = [self.storyboard instantiateViewControllerWithIdentifier:#"MainPageViewController"];
CGRect mframe = scrollView.frame;
mframe.origin.x = 0;
mframe.origin.y = 0;
mainpage.view.frame = mframe;
[self.scrollView addSubview:mainpage.view];
int i = 1;
NSLog(#"Iniciando criação de páginas!");
for(id name in categories) {
NSLog(#"Carregou página.%i",i);
NSLog(#"categories count:%i",[categories count]);
TasksPageViewController *tasks = [self.storyboard instantiateViewControllerWithIdentifier:#"TasksPageViewController"];
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * i;
frame.origin.y = 0;
tasks.view.frame = frame;
[tasks populateWithData:(i-1) categoryName:name];
[scrollView addSubview:tasks.view];
tasks = nil;
i++;
}
self.pageControl.numberOfPages = [categories count]+1;
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * ([categories count]+1), self.scrollView.frame.size.height);
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (pageControlUsed)
{
// do nothing - the scroll was initiated from the page control, not the user dragging
return;
}
// 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;
}
- (IBAction)changePage {
// update the scroll view to the appropriate page
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * self.pageControl.currentPage;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
[self.scrollView scrollRectToVisible:frame animated:YES];
pageControlUsed = YES;
}
// At the begin of scroll dragging, reset the boolean used when scrolls originate from the UIPageControl
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
pageControlUsed = NO;
}
// At the end of scroll animation, reset the boolean used when scrolls originate from the UIPageControl
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
pageControlUsed = NO;
}
- (void)viewDidUnload
{
[super viewDidUnload];
self.scrollView = nil;
}
#end
TasksPageViewController.h
#import <UIKit/UIKit.h>
#import "TasksTableCellPrototypes.h"
#interface TasksPageViewController : UIViewController <UITableViewDataSource>{
IBOutlet UILabel *categoryName;
IBOutlet UITableView *tableView;
//NSMutableArray *tasksData;
}
//#property (nonatomic,retain) NSMutableArray *tasksData;
#property (nonatomic,retain) UITableView *tableView;
#property (nonatomic,retain) UILabel *categoryName;
- (void) populateWithData:(int)dataId categoryName:(NSString *)name;
#end
TasksPageViewController.m
#import "TasksPageViewController.h"
#implementation TasksPageViewController
#synthesize tableView;
//#synthesize tasksData;
#synthesize categoryName;
- (void)viewDidLoad
{
[super viewDidLoad];
// NSUserDefaults *data = [NSUserDefaults standardUserDefaults];
//tasksData = [[NSMutableArray alloc] initWithArray:[data objectForKey:#"tasks"]];
//tasksData = [[NSMutableArray alloc] initWithObjects:#"lalal",#"lololo",nil];
}
- (void) populateWithData:(int)dataId categoryName:(NSString *)name {
//self.categoryName.text = name;
}
// Número de categorias
- (NSInteger)tableView:(UITableView *)tableViewnumberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
NSLog(#"contou table view tasks");
return 4;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
TasksTableCellPrototypes *cell = [[TasksTableCellPrototypes alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"taskCell"];
return cell;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (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
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
Thank you.
EDIT: apparently The ViewController isn't retaining the reference to the TasksPageViewController and the UITableView cannot find its dataSource. I don't really know how to retain this using ARC.
In your ViewController viewDidLoad, when you loop through the categories you instantiate a TasksPageViewController named tasks, but then you do not retain the reference anywhere. So later the TasksPageViewController cannot be found when the tableView:numberOfRowsInSection: message is sent.
I see that in your ViewController your synthesize a property named views but then you do not use that property anywhere. Perhaps you should rename that property viewControllers and then at the end of the loop in viewDidLoad, you should add your tasks object to the viewControllers mutable array, instead of setting tasks to nil. I think that might prevent the crash.
for(id name in categories) {
TasksPageViewController *tasks = [self.storyboard instantiateViewControllerWithIdentifier:#"TasksPageViewController"];
...
[scrollView addSubview:tasks.view];
[self.viewControllers addObject:tasks];
i++;
}

UIPopOverScreen troubles

Recently I have taken interest in making a popover screen. In my Navigation bar I made this button and when I click on it it should make a popover screen appear.
So I started searching for a usefull tutorial and yet I found mostly tutorials made with interface builder, which is not what I want. So I started experimenting on my own.
This is my result:
First I set the necessary properties in the MainVC.h
Also mind the
#import <UIKit/UIKit.h>
#import "ThePopOverVC.h"
#interface PopoverPrototypeViewController : UIViewController <UIPopoverControllerDelegate>
{
ThePopOverVC *popover;
UIPopoverController *popoverController;
UIButton *popoverButton;
}
#property (nonatomic,retain) ThePopOverVC *popover;
#property (nonatomic,retain) UIPopoverController *popoverController;
#property (nonatomic,retain) UIButton *popoverButton;
- (void)popoverActivation;
#end
Then I set up my view in the MainVC.m
It prepares the view for the popoverscreen when pressing a button.
#import "PopoverPrototypeViewController.h"
#implementation PopoverPrototypeViewController
#synthesize popover;
#synthesize popoverController;
#synthesize popoverButton;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)loadView
{
[super loadView];
self.view.backgroundColor = [UIColor blueColor];
popover = [[ThePopOverVC alloc] init];
popoverController = [[UIPopoverController alloc] initWithContentViewController:popover];
popoverController.popoverContentSize = CGSizeMake(300, 300);
popoverController.delegate = self;
self.popoverButton = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 400, 100)];
self.popoverButton.backgroundColor = [UIColor lightGrayColor];
[self.popoverButton setTitle:#"Click me!" forState:UIControlStateNormal];
[self.popoverButton addTarget:self action:#selector(popoverActivation) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.popoverButton];
}
- (void)popoverActivation
{
if ([self.popoverController isPopoverVisible]) {
[self.popoverController dismissPopoverAnimated:YES];
} else {
UIBarButtonItem *settingsBarButton = [[UIBarButtonItem alloc] initWithCustomView:self.popoverButton];
[self.popoverController presentPopoverFromBarButtonItem:settingsBarButton permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
}
- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
return YES;
}
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
NSLog(#"something");
}
Ok, the MainVC should be setup, now it's time to show the popoverContentViewController.
For my experiment I just want it to be an empty view with just a different backgroundColor.
So the popoverVC.h is empty:
#import <UIKit/UIKit.h>
#interface ThePopOverVC : UIViewController
#end
My popoverVC.m is equally empty except for the backgroundColor change:
#import "ThePopOverVC.h"
#implementation ThePopOverVC
- (void)loadView
{
[super loadView];
self.view.backgroundColor = [UIColor yellowColor];
}
You would say this shouldn't be too hard. But yet I'm experiencing problems loading the project.
I'm getting the following warning: warning: Unable to restore previously selected frame.
Well here comes the question:
What have I overlooked? What have I done wrong and how can I make this simple prototype work?
//---EDIT---//
OK, I'm a bloody idiot for overlooking this one.
[super loadView];
The super loadView wasn't called and gave me this simple problem.
I edited the code so it works properly now.
Use this as a tutorial on how to make UIPopOverScreens if you will (or whatever).
Ref: http://www.raywenderlich.com/1056/ipad-for-iphone-developers-101-uipopovercontroller-tutorial
[super loadView];
Was missing from ThePopOverVC.m
Pretty silly to overlook.. but yeah, it works now.

iOS: Can I have a UITableView scrolling horizontally in the iPhone landscape mode ? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Horizontal scrolling UITableView
Can I have a UITableView scrolling horizontally in the iPhone landscape mode ?
This is how it looks like now: http://cl.ly/95xZ
This is how it should be: http://cl.ly/93IY
I was wondering if I should use a UIScrollView for the landscape mode and therefore to switch between UITableView and UIScrollView depending on the orientation of the device...
thanks
You can try this
HorizontalTable for iOS
What you need is UIScrollView with pagination. It works essentially the same way a standard UITable does. When you scroll from left to right you just push new "cells" on the stack and present them.
Here is a sample code:
// .h File
#interface PagingViewController : UIViewController <UIScrollViewDelegate>{
NSMutableArray *cells;
}
#property(nonatomic,retain)NSMutableArray *cells;
-(id)initWithCells:(NSMutableArray*)tableCells;
-(void)loadPage:(int)page;
#end
// .m File
#interface PagingViewController ()
#property(nonatomic,retain)NSMutableArray *viewControllers;
#property(nonatomic,retain)UIView *contentView;
#property(nonatomic,readwrite)NSUInteger numberOfPages;
#end
#implementation PagingViewController
#synthesize viewControllers;
#synthesize contentView;
#synthesize cells;
#synthesize numberOfPages;
-(id)initWithCells:(NSMutableArray*)tableCells{
self = [super init];
if(self) {
self.cells = tableCells;
numberOfPages = [cells count];
NSMutableArray *controllers = [[NSMutableArray alloc] init];
for (unsigned i = 0; i < numberOfPages; i++)
{
[controllers addObject:[NSNull null]];
}
self.viewControllers = controllers;
[controllers release];
contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
self.view = contentView;
[self loadPage:0];
}
return self;
}
- (void)loadPage:(int)page{
if (page < 0)
return;
if (page >= kNumberOfPages)
return;
else if(page > 0){
CustomCellVC *cell = [viewControllers objectAtIndex:page];
if ((NSNull *)cell == [NSNull null]){
cell = (CustomCellVC*)[cells objectAtIndex:page];
[viewControllers replaceObjectAtIndex:page withObject:cell;
[cell release];
}
if (cell.view.superview == nil)
{
[contentView addSubview:cell.view];
}
}
}
//Dont forget to dealloc.
I wrote this from memory so there might be little bugz.
To implement horizontal scrolling you should use UIScrollView and manage its subviews manually. It's not very hard as it sounds. There are several videos from WWDC about technics which you can use to work with scroll view. They are worth watching.
Advanced ScrollView Techniques at
https://developer.apple.com/videos/play/wwdc2011/104/
Designing Apps with Scroll Views at
https://developer.apple.com/videos/play/wwdc2010/104/
Very simple example, how to show scrollView when user rotates device to landscape:
//header
// tableView and scrollView has the same superview
// scrollView is placed above tableView
#property(nonatomic, retain) IBOutlet UITableView *tableView;
#property(nonatomic, retain) IBOutlet UIScrollView *scrollView;
//implementation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[UIView animateWithDuration:duration
animations:^(void) {
if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) {
self.scrollView.alpha = 1.0f;
} else {
self.scrollView.alpha = 0.0f;
}
}];
}
I would put the UITableView inside the UIScrollView. This gives you the horizontal scrolling.
But I'm a litte bit confused: The 2nd screenshot shows a UINavigationController?

How to implement a TableView where the background scrolls at the same time?

Imagine you have a normal table view where each row is an item on a conveyor belt. You will put the items in each cell of the table view but when you scroll you also want the background image (the conveyor belt) to scroll as well. How can you do this?
You should be able to accomplish this by setting the background color of the table view:
tableView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"background.png"]];
Have the UITableView background transparent, and add a UIScrollView behind it with the UIImageView inside it. Add a listener for when the UITableView scrolls (since it is a subclass of UIScrollView it has all the same delegate methods). Then, when it scrolls, set the scroll position of the UIScrollView behind it to the same programmatically.
You could technically do it without a second UIScrollView behind the UITableView, just with a plain UIIImageView, if you want to reverse the offset values.
I haven't tried this, so I'm not sure what the best approach would be, but one option would be to add your background image as a UIImageView to each of your cells so that every cell has a full-sized copy of your background image. Set clipsToBounds to NO on your cell, and give the bounds of the UIImageView a negative y value equal to the offset from your cell to the top of the table.
You may also want to consider using UIScrollView instead of UITableView.
UITableView is itself a UIScrollView, so you could try just adding your background image as a subview of your UITableView, but I'd be surprised if that worked. I'm guessing the UITableView implementation won't play nice with foreign subviews.
** EDIT **
While I still suspect that UIScrollView may be a more appropriate base class to use here, I decided to try the UIImageView trick I described above. It's fairly simple and doesn't consume excessive memory as long as all your UIImageViews share a single UIImage. Here's my sample code:
// LadderCell.h
#import <UIKit/UIKit.h>
#interface LadderCell : UITableViewCell {
UIImageView *backgroundImageView;
UILabel *titleLabel;
}
#property (nonatomic, retain) UIImageView *backgroundImageView;
#property (nonatomic, retain) UILabel *titleLabel;
- (void)setIndexPath:(NSIndexPath *)indexPath;
- (id)initWithImage:(UIImage *)theImage;
+ (NSString *)reuseIdentifier;
+ (CGFloat)height;
#end
// LadderCell.m
#import "LadderCell.h"
#implementation LadderCell
#synthesize backgroundImageView, titleLabel;
- (void)dealloc {
self.backgroundImageView = nil;
self.titleLabel = nil;
[super dealloc];
}
- (id)initWithImage:(UIImage *)theImage {
if (self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[LadderCell reuseIdentifier]]) {
self.frame = CGRectMake(0.0, 0.0, 320.0, [LadderCell height]);
self.clipsToBounds = YES;
self.backgroundImageView = [[[UIImageView alloc] initWithImage:theImage] autorelease];
backgroundImageView.autoresizingMask = UIViewAutoresizingFlexibleRightMargin;
self.titleLabel = [[[UILabel alloc] initWithFrame:self.bounds] autorelease];
titleLabel.textAlignment = UITextAlignmentCenter;
titleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
titleLabel.backgroundColor = [UIColor colorWithWhite:1 alpha:0];
[self addSubview:backgroundImageView];
[self addSubview:titleLabel];
}
return self;
}
- (void)setIndexPath:(NSIndexPath *)indexPath {
backgroundImageView.frame = CGRectMake(0.0,
-(CGFloat)indexPath.row * [LadderCell height] + 100.0,
backgroundImageView.frame.size.width,
backgroundImageView.frame.size.height);
}
+ (NSString *)reuseIdentifier {
return #"LadderCell";
}
+ (CGFloat)height {
return 30;
}
#end
// TableBackgroundTestViewController.h
#import
#interface TableBackgroundTestViewController : UITableViewController {
UIImage *backgroundImage;
}
#property (nonatomic, retain) UIImage *backgroundImage;
#end
// TableBackgroundTestViewController.m
#import "TableBackgroundTestViewController.h"
#import "LadderCell.h"
#implementation TableBackgroundTestViewController
#synthesize backgroundImage;
- (void)dealloc {
self.backgroundImage = nil;
[super dealloc];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.backgroundImage = [UIImage imageNamed:#"background.png"];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section {
return 1000;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return [LadderCell height];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
LadderCell *cell = (LadderCell *)[tableView dequeueReusableCellWithIdentifier:[LadderCell reuseIdentifier]];
if (!cell) {
cell = [[[LadderCell alloc] initWithImage:self.backgroundImage] autorelease];
}
[cell setIndexPath:indexPath];
cell.titleLabel.text = [NSString stringWithFormat:#"Row %d", indexPath.row];
return cell;
}
#end
My suggestion is similar to Ed Marty (what he suggests "without a second UIScrollView"):
Place the UITableView inside a simple UIView. Make the cell backgrounds transparent so background from below the tableview would show
Below the UITableView, place an UIImageView with your desired background. Both the UITableView and UIImageView now sit inside the same enclosing UIView.
Listen to scroll events of UITableView. When detecting a scroll, simply change the background UIImageView position (frame.origin.y) appropriately, so that it would "stick with" the tableview.
You can have the background as one gigantic image, or have a series of them so you do tiling. You can have an array of the images and add to the array from top/bottom when needed, and also remove the images that have "scrolled away" from screen to conserve memory. You will need to calculate the positions for all these background images yourself, but there's nothing complicated in that.

iPhone - creating a loading view

When the app is in one view controller, I want to add a view to simulate that data is being loaded when I click my tab bar controller to open another view controller.
Example: When I the app is in the recorder-view, I want it to show a loading view (a view with a activity indicator) when I change to the list of recorded files (which can take some time to load). I've tried manipulate this with the viewWillDisappear-event, but I can't get it to work - the view is not being added before after the viewDidAppear-event occurs.
Anyone have any thoughts regarding this?
Thanks
Thank you for your reply. I tried doing like tou suggested, but I still can't get it to show when I want. I try to set hidden = NO in my viewWillDisappear-event, but it does not show before that view controller disappears and the next one appears
Right now it sounds like you have a UITabBarController That takes up the whole screen. What I would do is put the loading view above the TabBarController and hide it when not necessary. I would create a subclass of loadingViewController in the same xib your tab bar controller came from (or programatically if you desire) and set it to an IBOutlet of the App Delegate.
Something like this:
//In your App Delegate
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[window addSubview:tabBarController.view];
loadingView.hidden = YES;
[window insertSubview:loadingViewController.view aboveSubview:abBarController.view];
[window makeKeyAndVisible];
}
//In your loading View Controller
- (void) setLoadingViewHidden:(BOOL)hidden {
self.view.hidden = hidden;
self.activityIndicator.animating = hidden;
}
The way I've done this in the past is to have a content view which houses either an activity view or the view proper.
In the view controller's nib, instead of adding subviews to the main view, leave it empty and create a new view (such as a table view in the example below) for the view proper.
Also create an activity view (with a threaded progress indicator or somesuch) and a "no results" view.
Then derive your controller class from the something like the following:
//
// ContainerViewController.h
//
#import <UIKit/UIKit.h>
#interface ContainerViewController : UIViewController
{
UIView *myContainerView;
UITableView *myTableView;
UIView *mySearchActivityView;
UIView *myZeroResultsView;
UIView *myCurrentlyShowingView;
}
#property (retain, nonatomic) IBOutlet UIView *containerView;
#property (retain, nonatomic) IBOutlet UITableView *tableView;
#property (retain, nonatomic) IBOutlet UIView *searchActivityView;
#property (retain, nonatomic) IBOutlet UIView *zeroResultsView;
#property (assign) UIView *currentlyShowingView;
#end
//
// ContainerViewController.m
//
#import "ContainerViewController.h"
#implementation ContainerViewController
#synthesize containerView = myContainerView;
#synthesize tableView = myTableView;
#synthesize searchActivityView = mySearchActivityView;
#synthesize zeroResultsView = myZeroResultsView;
- (void)dealloc
{
[myContainerView release], myContainerView = nil;
[myTableView release], myTableView = nil;
[mySearchActivityView release], mySearchActivityView = nil;
[myZeroResultsView release], myZeroResultsView = nil;
myCurrentlyShowingView = nil;
[super dealloc];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.currentlyShowingView = mySearchActivityView;
mySearchActivityView.backgroundColor = [UIColor clearColor];
myZeroResultsView.backgroundColor = [UIColor clearColor];
}
- (void)setCurrentlyShowingView:(UIView *)view
{
[myCurrentlyShowingView removeFromSuperview];
CGRect frame = view.frame;
frame.size = myContainerView.frame.size;
view.frame = frame;
[myContainerView addSubview:view];
myCurrentlyShowingView = view;
if (view == myTableView)
[myTableView reloadData];
}
- (UIView *)currentlyShowingView
{
return myCurrentlyShowingView;
}
#end
And in the -viewDidLoad method of the derived class, set off the (asynchronous) query:
- (void)viewDidLoad
{
[super viewDidLoad];
myQueryLoader = [[QueryLoader alloc] initWithQuery:#"whatever" delegate:self];
self.currentlyShowingView = mySearchActivityView;
}
and in the delegate callback:
- (void)queryLoader:(QueryLoader *)queryLoader didEndWithResults:(id)results error:(NSError *)error
{
myItems = [results retain];
if (myItems)
self.currentlyShowingView = myTableView;
else
self.currentlyShowingView = myZeroResultsView;
}
Hope this helps!