UITableView bottom area keeps out of screen if navigationBar.translucent is NO; - ios

I use UITableView instance as the subview of my ViewController's view, the table's content is higher than the screen so it is scrollable. Here is the code in AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)opts {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UINavigationController *nav = [[UINavigationController alloc] init];
self.window.rootViewController = nav;
[self.window makeKeyAndVisible];
UIViewController *controller = [[ViewController alloc] init];
[nav pushViewController:controller animated:YES];
// set to No cause the problem
nav.navigationBar.translucent = NO;
return YES;
}
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_tableView = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain];
_tableView.delegate = self;
_tableView.dataSource = self;
[self.view addSubview:_tableView];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 20;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [[UITableViewCell alloc] init];
cell.textLabel.text = [NSString stringWithFormat:#"test %u", indexPath.row];
return cell;
}
#end
Now the problem is
if nav.navigationBar.translucent = YES, the content is scrolling right, the bottom line is visible if I scroll to bottom.
if nav.navigationBar.translucent = NO, the content isn't scrolling right, the bottom line automatically move out of the screen if I end the swip.
Seems like the auto hidden area is of the height of navigationBar, any one who knows how to fix it? I want it work the same no matter translucent = YES or translucent = NO.

Try this & let me know if it works:
self.tableView.contentInset = UIEdgeInsetsMake(44,0,0,0);

I figure out the solution, I set the tableView as the mainview of the controller, not a subview of the controller's mainview
[self setView:_tableView];
instead of
[self.view addSubview:_tableView];

Related

UITableView memory bug

I have a problem with memory leak in UITableView. If I'm at the bottom of DetailViewController table and I want to go back to MasterViewController I have a crash. If I use UITableViewController, crash does not happen.
AppDelegate
_window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
_window.backgroundColor = [UIColor blackColor];
_window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[MasterViewController alloc] init]];
[_window makeKeyAndVisible];
MasterViewController
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
DetailViewController *detailViewController = [[DetailViewController alloc] init];
[self.navigationController pushViewController:detailViewController animated:YES];
}
DetailViewController
#interface DetailViewController ()
#property (nonatomic, strong) UITableView *tableView;
#end
#implementation DetailViewController
- (void)viewDidLoad {
[super viewDidLoad];
_tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.rowHeight = 60;
[self.view addSubview:_tableView];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 30;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
return cell;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSLog(#"scrollViewDidScroll");
}
#end

Getting started with UICollectionViewController Programmatically

I am currently working on writing a UICollectionViewController to load images from a server and put the images into custom UICollectionViewCells within a UICollectionView. To make things simpler than it already is, I don't pull from a database, I just simply create an array of images that are stored locally. It works but for some reason, not all of the cells show the image until I start scrolling.
Heres an image of whats going on!
Image
I have read up on a few tutorials but they all use storyboard... I am wanting to write this programmatically.
Heres some code:
AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
JSMediaCollectionController *instagram = [[JSMediaCollectionController alloc] initWithCollectionViewLayout:[UICollectionViewFlowLayout new]];
instagram.datasource = self;
self.array = [NSMutableArray array];
for (int i = 0; i < 100; i++) {
[self.array addObject:#"instant_noodle_with_egg.jpg"];
}
UINavigationController *navCon = [[UINavigationController alloc] initWithRootViewController:instagram];
self.window.rootViewController = navCon;
[self.window makeKeyAndVisible];
return YES;
}
- (NSArray *)itemsToLoad
{
return [NSArray arrayWithArray:self.array];
}
JSMediaController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = NO;
// Register cell classes
[self.collectionView registerClass:[JSMediaCollectionCell class] forCellWithReuseIdentifier:reuseIdentifier];
self.showOneItemPerRow = false;
// Do any additional setup after loading the view.
}
#pragma mark <UICollectionViewDataSource>
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [[self.datasource itemsToLoad] count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
JSMediaCollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
[cell setImage:[UIImage imageNamed:[[self.datasource itemsToLoad] objectAtIndex:indexPath.row]]];
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"photo-frame.png"]];
return cell;
}
...
...
JSMediaCell.m:
#interface JSMediaCollectionCell()
#property (nonatomic) UIImageView *view;
#end
#implementation JSMediaCollectionCell
- (id)initWithFrame:(CGRect)frame
{
if (!(self = [super initWithFrame:frame])) return nil;
self.view = [[UIImageView alloc] initWithFrame:self.frame];
[self.viewForBaselineLayout addSubview:self.view];
return self;
}
- (void)setImage:(UIImage *)image
{
self.view.image = image;
}
I greatly appreciate anyones help in getting me on the right track... Just as a reminder... As I start scrolling, the images are reloaded, but not all the cells have an image loaded in the subview... just some.
I can see that you are initialising the view property in the cell file with self.frame.
Instead, it should be
self.view = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
I think you can guess what went wrong.!!!
The frame should be wrt to the cell.
When the subview is added to cell, it takes the values of the origin of the cell, so it goes out of cell's view

IOS, UICollectionview

New to IOS and objective C and been doing several tutorials, with adding buttons, textfields etc. Been looking alot on stackoverflow, which has been very helpful :) Now I am trying to create a collectionview within a frame and then put a button below it. I can get a button to show up, and the top half of the screen where I have defined the collection to appear turns black, while the rest goes white, as intended. Currently the collection should come up with a label telling me the cell number, so very basic. Not sure if I'm setting up my views wrong, or if there is something wrong with my CellViews.
I have created a mainView controller, where I have defined my button and collection view, like this:
MainViewController.h:
#interface MainViewController : UIViewController <UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
#property(nonatomic, strong) IBOutlet UICollectionView *collectionView;
#property(nonatomic, strong) IBOutlet UIButton *diaryButton;
- (id)init;
My .m looks like this:
#implementation MainViewController
#synthesize collectionView;
#synthesize diaryButton;
- (id) init {
self = [super init];
if (self) {
CGRect buttonFrame = CGRectMake(10, 250, 70, 30);
diaryButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[diaryButton setFrame:buttonFrame];
[diaryButton setTitle:#"Diary" forState:UIControlStateNormal];
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.itemSize = CGSizeMake(64.0, 64.0);
layout.minimumInteritemSpacing = 4;
layout.minimumLineSpacing = 4;
layout.scrollDirection = UICollectionViewScrollPositionCenteredVertically;
layout.sectionInset = UIEdgeInsetsMake(2.0, 2.0, 2.0, 2.0);
CGRect collectionFrame = CGRectMake(0, 0, 320, 200);
collectionView = [[UICollectionView alloc] initWithFrame:collectionFrame collectionViewLayout:layout];
[self.view addSubview:collectionView];
[self.view addSubview:diaryButton];
//[self.view setBackgroundColor:[UIColor blueColor]];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"ID"];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 30;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"ID" forIndexPath:indexPath];
UILabel *label = [[UILabel alloc] initWithFrame:cell.bounds];
label.textAlignment = NSTextAlignmentCenter;
label.text = [NSString stringWithFormat:#"%d", indexPath.row];
[cell.contentView addSubview:label];
return cell;
}
/////////////////////////////////////////////////////////////////////////////////
// collection view delegate methods ////////////////////////////////////////
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"cell #%d was selected", indexPath.row);
}
My appdelegate looks like this:
#synthesize mainVC;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.mainVC = [[MainViewController alloc] init];
[self.window addSubview:mainVC.view];
//self.window.rootViewController = mainVC;
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
Any help will be greatly appreciated.
I don't know exactly why your collection isn't showing anything, but you're missing the numberOfSectionsInCollectionView: method from the UICollectionViewDataSource. The collection view might be assuming that the number of sections is 0.
http://developer.apple.com/library/ios/#documentation/uikit/reference/UICollectionViewDataSource_protocol/Reference/Reference.html
Also, did you set the datasource and delegate to self for your UICollectionView?

Why does my pushViewController not work

When I hit an element in my tableView it comes up with an error. I have checked all of the connections but still cant work it out. Here is my code
#import "CGViewController.h"
#import "CGAppDelegate.h"
#import "sls.h"
#import "patientController.h"
#interface CGViewController ()
#end
#implementation CGViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Patients";
CGAppDelegate *delegate =
(CGAppDelegate *)[[UIApplication sharedApplication] delegate];
patients = delegate.patients;
self.navigationItem.rightBarButtonItem = self.editButtonItem;
UIBarButtonItem *addButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(add:)];
self.navigationItem.leftBarButtonItem = addButtonItem;
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark UITableViewDataSource Methods
- (UITableViewCell *)tableView:(UITableView *)tv
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:#"cell"];
if( nil == cell) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"cell"];
}
if (indexPath.row < patients.count) {
sls *thissls = [patients objectAtIndex:indexPath.row];
cell.textLabel.text = thissls.patientName;
}
else {
cell.textLabel.text = #"";
cell.textLabel.textColor = [UIColor lightGrayColor];
}
return cell;
}
-(void)setEditing:(BOOL)editing animated:(BOOL)animated {
if ( editing != self.editing) {
[super setEditing:editing animated:animated];
[self.tableView setEditing:editing animated:animated];
NSArray *indexes =
[NSArray arrayWithObject:
[NSIndexPath indexPathForRow:patients.count inSection:0]];
if ( editing == YES ) {
[self.tableView insertRowsAtIndexPaths:indexes withRowAnimation:UITableViewRowAnimationLeft];
} else {
[self.tableView deleteRowsAtIndexPaths:indexes withRowAnimation:UITableViewRowAnimationLeft];
}
}
[self.tableView reloadData];
}
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row < patients.count ) {
return UITableViewCellEditingStyleDelete;
}
else {
return UITableViewCellEditingStyleNone;
}
}
- (NSInteger)tableView:
(UITableView *)tv numberOfRowsInSection:
(NSInteger)section {
NSInteger count = patients.count;
if (self.editing) {
count = count + 1;
}
return count;
}
-(void)tableView:(UITableView *)tv didSelectRowAtIndexPath:
(NSIndexPath *)indexPath {
CGAppDelegate *delegate =
(CGAppDelegate *)[[UIApplication sharedApplication] delegate];
patientController *patient = [[patientController alloc] init];
[delegate.navController pushViewController:patient animated: YES];
[tv deselectRowAtIndexPath:indexPath animated: YES];
}
-(void) tableView:(UITableView *)tv
commitEditingStyle:(UITableViewCellEditingStyle)editing forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editing == UITableViewCellEditingStyleDelete) {
[patients removeObjectAtIndex:indexPath.row];
[tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationLeft];
}
}
#end
Any ideas on what is wrong if you know please can you help as soon as possible as i am on a deadline
Thanks in advance.
The error says Thread 1:signal SIGABRT
The error is in main.m
#import <UIKit/UIKit.h>
#import "CGAppDelegate.h"
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([CGAppDelegate class]));
}
}
it says that the error is here
patientController *patient = [[patientController alloc] init];
here is my patientController.h file
#import <UIKit/UIKit.h>
#interface patientController : UIViewController {
NSIndexPath *index;
IBOutlet UIImageView * pictureView;
IBOutlet UILabel * descriptionView1;
IBOutlet UILabel * descriptionView2;
IBOutlet UILabel * descriptionView3;
}
- (id)initwithIndexPath:(NSIndexPath *)indexPath;
#end
and my .m file
#import "patientController.h"
#import "CGAppDelegate.h"
#import "sls.h"
#interface patientController ()
#end
#implementation patientController
- (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 from its nib.
CGAppDelegate *delegate =
(CGAppDelegate *)[[UIApplication sharedApplication] delegate];
sls *thissls = [delegate.patients objectAtIndex:index.row];
self.title = thissls.patientName;
self->descriptionView1.text = thissls.patientName;
self->descriptionView2.text = thissls.surnameName;
self->descriptionView3.text = thissls.dateOfBirth;
self->pictureView.image = thissls.patientImage;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (id)initwithIndexPath:(NSIndexPath *)indexPath {
if ( (self == [super init]) ) {
index = indexPath;
}
return self;
}
#end
Please can anyone at all help
Use:
[self.navigationController pushViewController:patient animated: YES];
If you are currently in a navigationController (which you have to in order to push a new ViewController), then you can push your new controller by just calling these lines
-(void)tableView:(UITableView *)tv didSelectRowAtIndexPath:
(NSIndexPath *)indexPath {
patientController *patient = [[patientController alloc] init];
[self.navigationController pushViewController:patient animated: YES];
}
Use
[self.navController pushViewController:patient animated: YES];
Every viewcontroller has its navigation controller reference in itself,no need to call the application delegate to invoke it[The navigation controller Must be initialised and all the viewcontrollers must be pushed into the navigation stack until this one to make it work]
So use this to setup the navigation controller in the appdelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//Note : this is an example set like this with your viewcontroller instance
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController_iPhone" bundle:nil];
} else {
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController_iPad" bundle:nil];
}
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
[self.window makeKeyAndVisible];
return YES;
}
To check where your exception is raised, in Xcode, in the breakpoints navigation tab click on the plus button in the bottom-left corner and add an Exceptions Breakpoint. Then run the app from Xcode. The next time an exception is raised, as in your case, the execution of your app will stop and Xcode will point at the line of code where the exception is raised.
Anyway, to make you understand how navigationControllers work:
UINavigationController is a UIViewController that controls a stack of other UIViewController instances. This other view controllers are said to be in the 'navigation stack'. The top item in the navigation stack is the view controller whose view you see at a given time onto the screen. You can push (present) or pop (dismiss) a view controller on/from the navigation stack.
A UINavigationController is initialized with a 'rootViewController' which is going to be it's first view controller onto the stack and therefore the first you see when you add the navigationController onto the screen (e.g. by setting it as the appDelegate window's rootViewController). Each UIViewController on the navigation stack references it's navigationController through the property 'navigationController'.
At any given point, you can use the UINavigationController methods pushViewController:animated: and popViewControllerAnimated: or popToViewController:animated: or popToRootViewControllerAnimated: to add or remove viewControllers from the navigationStack. To see the results of this methods, of course, you should have the navigationController on screen.
For more informations refer to the UINavigationController Class Reference.

UITabBars and UITableViews. Keeping the Tab bar on screen when a table cell is clicked

I'm trying to get a GUI with a UITabBar and UITableViews set up.
I've got a UITabView that is programmatically created.
One of the Tabs displays a UITableView that is also programmatically created.
This UITableView then displays other views when didSelectRowAtIndexPath is called.
Unfortunately, when a table cell is clicked, my tab view goes away and the new table view is displayed.
What I can't get my head around is how to structure the views so that the tabBar stays on the screen.
Is it as simple as making the UITableViews shorter, or is there some window/view mojo that I'm missing?
Thanks
You should use a UITabBarController to display the UITabBar rather than doing it directly.
Then use a UITableViewController as the view controller for a given tab. Though I get the impression that you want to present descendent UITableViews when a row is selected. If this is the case, you ought to use a UINavigationController as the tab bar's view controller, and let it manage your UITableViewControllers.
Remember that on iOS you really need to use the view controller pattern - the frameworks take care of a lot of things for you under the hood.
Follow-up:
OK, the following straightforward implementation works just fine for me. Please ignore the many obvious issues with this code (beginning with the fact that I hacked it all together in the application delegate!); it's intended purely as a model for how your controllers should be glued together.
#import <UIKit/UIKit.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate, UITableViewDelegate, UITableViewDataSource>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) UINavigationController *navController;
#end
#implementation AppDelegate
#synthesize window = _window;
#synthesize navController = _navController;
- (void)dealloc
{
[_navController release];
[_window release];
[super dealloc];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
UITableViewController *rootTVC = [[UITableViewController alloc] initWithStyle:UITableViewStylePlain];
[[rootTVC tableView] setDelegate:self];
[[rootTVC tableView] setDataSource:self];
[rootTVC setTitle:#"Root Table"];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:rootTVC];
[rootTVC release];
[navController setTitle:#"My Table"];
UIViewController *anotherViewController = [[UIViewController alloc] init];
[anotherViewController setTitle:#"Not the table"];
UITabBarController *tbc = [[UITabBarController alloc] init];
[tbc setViewControllers:[NSArray arrayWithObjects:navController, anotherViewController, nil]];
[self setNavController:navController];
[navController release];
[anotherViewController release];
[[self window] setRootViewController:tbc];
[tbc release];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *reuseIdentifier = #"foo";
UITableViewCell *cell = [[tableView dequeueReusableCellWithIdentifier:reuseIdentifier] retain];
if (! cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
}
[[cell textLabel] setText:[NSString stringWithFormat:#"Row %d", [indexPath row]]];
return [cell autorelease];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
UITableViewController *newTVC = [[UITableViewController alloc] initWithStyle:UITableViewStylePlain];
[newTVC setTitle:[NSString stringWithFormat:#"Table %d", [indexPath row]]];
[[newTVC tableView] setDelegate:self];
[[newTVC tableView] setDataSource:self];
[[self navController] pushViewController:newTVC animated:YES];
}
#end
Use UITabBarController instead of UITabBar.

Resources