Issue with UISearchBar and UITableView in iOS7 - uitableview

I have an app that works fine in iOS6. It has a table view with a search bar. When I run it in iOS7 I got the following issue:
As you can see in the image above, the search results are displayed in a wrong position, they are overlapping the search control, any idea how to fix this?
The first image is showing the search control, and the search results should be shown in the position I marked in red in that first image.
Thanks. -Fernando
Well, I made some changes but it is still not so good:
-(void)searchDisplayController:(UISearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView {
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
// The tableView the search tableView replaces
CGRect f = self.searchFavoriteListTable.frame;
CGRect f1 = tableView.frame;
//CGRect s = self.searchDisplayController.searchBar.frame;
CGRect updatedFrame = CGRectMake(f1.origin.x,
f.origin.y + 45,
f1.size.width,
f1.size.height - 45);
tableView.frame = updatedFrame;
}
}
What I want to remove is the red part in the last image... it is overlapping other view.

First step, create a searchbar with general format and general frame;
UISearchBar *mySearchBar = [[UISearchBar alloc] initWithFrame:CGRectZero];
[mySearchBar sizeToFit]; // if you give it CGRectZero and sizeToFit, it will shown exactly end of the your navigationBar.
mySearchBar.tintColor = [UIColor whiteColor];
mySearchBar.placeholder = #"Search Music";
mySearchBar.showsScopeBar = NO;
mySearchDisplayController *mySearchDisplay = [[mySearchDisplayController alloc] mySearchBar contentsController:self];
Then create a new class type of "UISearchDisplayController" as a name "mySearchDisplayController" and as you see, we should merge your searchbar in it 3 lines up. Don't forget implement UITableView protocol to your new class like that;
#interface mySearchDisplayController : UISearchDisplayController <UISearchDisplayDelegate, UISearchBarDelegate, UITableViewDelegate, UITableViewDataSource>
Then in your new mySearchDisplayController class implement that method;
-(void)searchDisplayControllerWillBeginSearch:(mySearchDisplayController *)controller
{
self.searchResultsDataSource = self;
self.searchResultsTableView.delegate = self;
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1)
{
CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
[UIView animateWithDuration:0.01 animations:^{
for (UIView *subview in self.searchBar.subviews)
subview.transform = CGAffineTransformMakeTranslation(0, statusBarFrame.size.height);
}];
}
}
-(void)searchDisplayControllerWillEndSearch:(mySearchDisplayController *)controller
{
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1)
{
[UIView animateWithDuration:0.01 animations:^{
for (UIView *subview in self.searchBar.subviews)
subview.transform = CGAffineTransformIdentity;
}];
}
}
And last step, you should identify your new frame end of the searchbar to your tableview;
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSInteger)scope
{
[self.filteredSearchResults removeAllObjects]; // First clear the filtered array.
for(NSDictionary *searchResult in // your search array)
{
NSString *searchableString = [NSString stringWithFormat:#"%# %#", [searchResult objectForKey:#"//your search key"]];
NSRange stringRange = [searchableString rangeOfString:searchText options:NSCaseInsensitiveSearch];
}
}
[self.searchResultsTableView reloadData];
CGRect screenBound = [[UIScreen mainScreen] bounds];
CGSize screenSize = screenBound.size;
CGFloat screenHeight = screenSize.height;
CGRect frame = self.searchResultsTableView.frame;
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1)
{
frame.size.height = screenHeight-64.0f;
}
else
{
frame.size.height = screenHeight-44.0f;
}
self.searchResultsTableView.frame = frame;
}
I wrote that code 2 months ago for my app and it works perfect for iOS 7 && 6 && 5. Hope it works.

Related

UIActivityIndicatorView showing and causing crash on two specific views

I am getting a very hard to trace crash in one of my views that is related to UIActivityIndicatorViewSometimes it crashes right away, sometimes it takes a few loads (going back to the previous view in the navigation stack and loading the view again). I have run the app through instruments, and while memory use keeps rising, I don't see any leaks. Could I be running out of memory? I also don't see any memory warnings. Here is the error:
*** -[UIActivityIndicatorView release]: message sent to deallocated instance 0x15f6d6aa0
I am not making any connections, and I can see the ActivityIndicator show up and then the app crashes when it disappears (or it disappears before the app crashes).
I have read that AFNetworking can cause this problem, but I am not using it. I am just using NSURLSession.
Both classes are very similar, and I have included the loading calls of one, as the class is too big to post here.
It is displayed in a Navigation Controller nested in a TabBarController:
- (BOOL)prefersStatusBarHidden {
return NO;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.userDefaults = [NSUserDefaults standardUserDefaults];
self.hairlineHeightConstraint.constant = 0.5f;
self.hairlineDivider.backgroundColor = [UIColor colorWithWhite:0.9f alpha:1.0f];
self.title = #"Course";
[self.classroomButton setTintColor:[UIColor pxColorWithHexValue:self.passedCourse.courseColor]];
[self.classroomButton addTarget:self action:#selector(subscribeToCourse:) forControlEvents:UIControlEventTouchUpInside];
[self getAnySubscribedCourse];
if (self.subscribedCourse) {
if (self.passedCourse == self.subscribedCourse) {
[self.classroomButton setTitle:#"Remove from Classroom" forState:UIControlStateNormal];
self.subscribedToThisCourse = YES;
} else {
self.alreadySubscribed = YES;
}
}
[self configureHeaderView];
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
}
}
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
if (self.shareView) {
CGRect frame = self.shareView.frame;
CGFloat navbarHeight = self.navigationController.navigationBar.frame.size.height;
CGFloat statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
frame = CGRectMake(0.0f, self.tableView.contentOffset.y + statusBarHeight + navbarHeight, frame.size.width, frame.size.height);
self.shareView.frame = frame;
[self.view bringSubviewToFront:self.shareView];
}
NSString *backText = self.navigationItem.backBarButtonItem.title;
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:backText style:UIBarButtonItemStylePlain target:nil action:nil];
[backButton setTitleTextAttributes:[[MSThemeManager currentTheme] barButtonTextDictionaryForState:UIControlStateNormal withTintColor:[UIColor pxColorWithHexValue:self.passedCourse.courseColor]] forState:UIControlStateNormal];
self.navigationItem.backBarButtonItem = backButton;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.navigationController.navigationBarHidden = NO;
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:animated];
[self.tableView reloadData];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if ([self.tableView.tableHeaderView isKindOfClass:[ParallaxCourseDetailHeaderView class]]) {
ParallaxCourseDetailHeaderView *headerView = (ParallaxCourseDetailHeaderView *)self.tableView.tableHeaderView;
[headerView.courseInfoAudioPlayer stop];
self.tableView.tableHeaderView = nil;
}
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - HeaderView
- (void)configureHeaderView
{
CGRect screenBound = [[UIScreen mainScreen] bounds];
CGSize screenSize = screenBound.size;
CGFloat screenWidth = screenSize.width;
NSDictionary *attributesDictionary = #{NSFontAttributeName : self.headerLabel.font};
CGFloat width = screenWidth - self.headerLabel.frame.origin.x - 15.0f;
CGSize boundingBox = CGSizeMake(width, CGFLOAT_MAX);
NSString *descriptionToBound = self.passedCourse.courseDescription;
CGRect labelRect = [descriptionToBound boundingRectWithSize:boundingBox
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributesDictionary
context:nil];
CGRect headerLabelRect = self.headerLabel.frame;
CGRect tableHeaderViewRect = self.tableView.tableHeaderView.frame;
CGRect dividerRect = self.hairlineDivider.frame;
CGFloat heightDifference = ceilf(labelRect.size.height - headerLabelRect.size.height);
tableHeaderViewRect.size.height += heightDifference;
self.tableView.tableHeaderView.frame = tableHeaderViewRect;
dividerRect.origin.y += heightDifference;
headerLabelRect.size.width = ceil(labelRect.size.width);
headerLabelRect.size.height = ceil(labelRect.size.height);
headerLabelRect.origin.y = (dividerRect.origin.y - headerLabelRect.size.height) / 2;
self.headerLabel.frame = headerLabelRect;
CGFloat parallaxViewHeight = 280.0f;
CGFloat headerHeight = parallaxViewHeight + heightDifference;
ParallaxCourseDetailHeaderView *headerView = [[ParallaxCourseDetailHeaderView alloc] initWithTitleViewStyle:SWParallaxTitleViewStyleWhiteWithMask withHeight:tableHeaderViewRect.size.height headerHeight:headerHeight];
UIImage *image = [UIImage imageNaobj:self.passedCourse.headerImage];
headerView.courseImage = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[headerView setTintColor:[UIColor whiteColor]];
headerView.isTitleViewOpaque = YES;
headerView.fadeInDuration = 0.0;
headerView.trackID = self.passedCourse.aboutTrackID;
[headerView courseAudioIntroControl];
UIImage *headerTeacherImage = [UIImage imageNaobj:[NSString stringWithFormat:#"%#", self.passedCourse.teacher.teacherImageID]];
self.headerTeacherImage.image = headerTeacherImage;
self.headerTeacherImage.layer.cornerRadius = self.headerTeacherImage.frame.size.height / 2;
self.headerTeacherImage.clipsToBounds = YES;
self.headerLabel.text = self.passedCourse.courseDescription;
[self.headerTeacherButton setImage:headerTeacherImage forState:UIControlStateNormal];
UIView *oldHeaderView = self.tableView.tableHeaderView;
oldHeaderView.frame = CGRectMake(0, 0, screenWidth, oldHeaderView.frame.size.height);
self.tableView.tableHeaderView = nil;
[headerView.titleView addSubview:oldHeaderView];
self.tableView.tableHeaderView = headerView;
[headerView.imageContainerView setBackgroundColor:[UIColor pxColorWithHexValue:self.passedCourse.courseColor]];
headerView.title = self.passedCourse.title;
headerView.subtitle = [NSString stringWithFormat:#"%lu Sessions", (unsigned long)self.passedCourse.courseObjects.count];
headerView.teacher = [NSString stringWithFormat:#"With %#", self.passedCourse.teacher.teacherName];
[headerView.titleLabel adjustCurrentFontSize];
[headerView.subtitleLabel adjustCurrentFontSize];
[headerView.teacherLabel adjustCurrentFontSize];
}
#pragma mark - ScrollView
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if ([self.tableView.tableHeaderView isKindOfClass:[ParallaxCourseDetailHeaderView class]]) {
ParallaxCourseDetailHeaderView *headerView = (ParallaxCourseDetailHeaderView *)self.tableView.tableHeaderView;
headerView.parallaxOffset = scrollView.contentOffset.y + scrollView.contentInset.top;
}
}

Create UITextField/UITextView similar to iPhone messaging app

How can you create a UITextField very similar to the one apple uses in their messaging app, Instagram uses, edmodo uses, Whatsapp uses and many other message sharing applications? This text field should animate up, animate down, be able to expand, only reach a certain height, and have other properties as well.
I researched for a while, but couldn't find an answer so I just created my own way to do it. There are several things you must do. First of all, this does use a UITextView and not a UITextField. Secondly, this code was written specifically for the iPhone 5, so you may need to play around with the coordinates. It does not use sizing classes or constraints. 1You need to implement the first. Your .h file should look like the following:
int returnPressed = 0;
int newLine;
#interface ViewController : UIViewController <UITextViewDelegate>
{
IBOutlet UIView *dock;
IBOutlet UIButton *sendButton;
IBOutlet UITextView *textView1;
CGRect previousRect;
}
#end
In the .m file there are many needs that need to be met to make it look how the iPhone message app looks. You'll notice how we have created our own custom place holder in here because textview don't really have them. Here is the .m file:
- (void)viewDidLoad {
[super viewDidLoad];
previousRect = CGRectZero;
textView1.delegate = self;
self->textView1.layer.borderWidth = 1.0f;
self->textView1.layer.borderColor = [[UIColor lightGrayColor] CGColor];
self->textView1.layer.cornerRadius = 6;
self->textView1.textColor = [UIColor lightGrayColor];
self->textView1.text = #"Place Holder";
}
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if ([text isEqualToString:#"\n"]) {
returnPressed +=1;
if(returnPressed < 17){
textView1.frame = CGRectMake(8, 8, textView1.frame.size.width, textView1.frame.size.height + 17);
newLine = 17*returnPressed;
[UIView animateWithDuration:0.1 animations:^
{
dock.transform = CGAffineTransformMakeTranslation(0, -250 - newLine);
}
];
}
}
return YES;
}
- (void)textViewDidChange:(UITextView *)textView{
UITextPosition* pos = textView1.endOfDocument;
CGRect currentRect = [textView1 caretRectForPosition:pos];
if (currentRect.origin.y > previousRect.origin.y || [textView1.text isEqualToString:#"\n"]){
returnPressed +=1;
if(returnPressed < 17 && returnPressed > 1){
textView1.frame = CGRectMake(8, 8, textView1.frame.size.width, textView1.frame.size.height + 17);
newLine = 17*returnPressed;
[UIView animateWithDuration:0.1 animations:^
{
dock.transform = CGAffineTransformMakeTranslation(0, -250 - newLine);
}
];
}
}
previousRect = currentRect;
}
- (BOOL)textViewShouldBeginEditing:(UITextView *)textField {
if([textView1.text isEqualToString:#""] || [textView1.text isEqualToString:#"Place Holder"]){
textView1.text = #"";
}
textView1.textColor = [UIColor blackColor];
[UIView animateWithDuration:0.209 animations:^
{
dock.transform = CGAffineTransformMakeTranslation(0, -250 - newLine);
}
completion:^(BOOL finished){}];
return YES;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch * touch = [touches anyObject];
if(touch.phase == UITouchPhaseBegan) {
[textView1 resignFirstResponder];
[self.view endEditing:YES];
int height = returnPressed*20;
[UIView animateWithDuration:0.209 animations:^
{
dock.transform = CGAffineTransformMakeTranslation(0, -height);
}];
if([textView1.text isEqualToString:#""]){
self->textView1.textColor = [UIColor lightGrayColor];
self->textView1.text = #"Place Holder";
}
}
}
That is everything. I hope this helps anyone who was trying to do this and I hope you can integrate this into an app of yours.
There is a pod that you can use for growing text view's :
https://cocoapods.org/pods/HPGrowingTextView
With this you can manage animation and maximum height of text view.

UITableViewController always display search bar

In iOS 5, is there a way to never hide the search bar in a UITableViewController?
I wouldn't recommend a UITableViewController for that then, a UIViewController with a UITableVIew and UISearchBar on top of it and not on the header would do the job. In a more personal opinion, I wouldn't recommend UITableViewController for anything, I find it too much strict for what it really offers. If for some reason I am using a UITableViewControllerand the customer asks me to add a new element to the screen, I am basically screwed.
I know it's an old question, but I found out a solution for this, which works with the classic UITableViewController and UTSearchDisplayController.
I created a container view for the searchBar 1st then put the searchbar inside it. The container must not clip to bounds. After this you can change the position of the searchbar relative to the container. One problem with this that this way the searchbar not handle user interactions. So we need to use our own container which get the events below its real frame.
Our container class:
#interface _SearchContainerView : UIView
#end
#implementation _SearchContainerView
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
if (self.subviews.count > 0) {
UISearchBar *searchBar = (UISearchBar *) self.subviews[0];
CGRect f = searchBar.frame;
f = CGRectMake(0, 0, f.size.width, f.origin.y + f.size.height);
if (CGRectContainsPoint(f, point)) return YES;
}
return [super pointInside:point withEvent:event];
}
#end
If you create the searchBar programmatically you can set the this up with a following like code:
- (void)setSearchEnabled:(BOOL)searchEnabled {
if (searchBar == nil && searchEnabled) {
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.tableView.bounds.size.width, 44)];
searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar
contentsController:self];
searchBar.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin
| UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
searchDisplayController.delegate = self;
searchDisplayController.searchResultsDataSource = self;
searchContainer = [[_SearchContainerView alloc] initWithFrame:searchBar.frame];
[container addSubview:searchBar];
container.clipsToBounds = NO;
self.tableView.tableHeaderView = container;
} else {
[searchBar removeFromSuperview];
self.tableView.tableHeaderView = nil;
searchBar = nil;
searchDisplayController = nil;
searchContainer = nil;
}
}
Then you can change the position based on the tableView's scroll position:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (searchBar == nil || searchDisplayController.isActive) return;
CGRect b = self.tableView.bounds;
// Position the searchbar to the top of the tableview
searchBar.frame = CGRectMake(0, b.origin.y, b.size.width, 44);
}
And the last part is to restore everything after searching:
- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller {
// Restore header alpha
searchContainer.alpha = 1.0;
// Place the searchbar back to the tableview
[searchBar removeFromSuperview];
[searchContainer addSubview:searchBar];
// Refresh position and redraw
CGPoint co = self.tableView.contentOffset;
[self.tableView setContentOffset:CGPointZero animated:NO];
[self.tableView setContentOffset:co animated:NO];
}

How to show app-specific status bar at bottom of screen, outside of app?

I have a requirement to show a status bar at certain times at the bottom of my application. I can easily put this at the bottom of my application's main view, but whenever I push a view controller on top of this (either modally or not) it hides this status bar.
Is there any way I can add a status bar like this, and have it be outside the bounds of my application itself? Ideally I'd like this to work like the call-in-progress status bar on the iPhone - when this bar appears, the app is pushed down, and a call to [[UIScreen mainScreen] applicationFrame] returns the correct size (i.e. it accounts for the presence of this status bar when calculating the height available for the app).
I wanted to do this, too, so I tried View Controller Containment. I'm still trying it out, so I'm not willing to give this a ringing endorsement, but it might be something you'd want to try playing around with yourself if you're in iOS5. But it appears to give you a status bar that will appear or disappear from the bottom of the screen.
This is a view controller that will open another view controller, but if there is status text to show, it pops up from the bottom of the screen and stays there until you get rid of it. I've only done a little testing so far, but it looks like this handles pushViewController/popViewController, but maybe not modal views.
My header looks like:
// StatusBarViewController.h
//
// Created by Robert Ryan on 7/8/12.
#import <UIKit/UIKit.h>
#interface StatusBarViewController : UIViewController
#property (strong, nonatomic) UIViewController *appController;
- (void)setStatus:(NSString *)text;
#end
My implementation file (this is ARC) looks like:
// StatusBarViewController.m
//
// Created by Robert Ryan on 7/8/12.
#import "StatusBarViewController.h"
#interface StatusBarViewController ()
{
BOOL _statusHidden;
UIView *_appView;
UILabel *_statusLabel;
}
#end
#implementation StatusBarViewController
#synthesize appController = _appController;
- (void)dealloc
{
_appView = nil;
_statusLabel = nil;
[self setAppController:nil]; // usually I don't like setters in dealloc, but this does some special stuff
}
- (void)createControlsWithStatusHidden
{
// create default app view that takes up whole screen
CGRect frame = self.view.frame;
frame.origin = CGPointMake(0.0, 0.0);
_appView = [[UIView alloc] initWithFrame:frame];
_appView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_appView.clipsToBounds = YES;
[self.view addSubview:_appView];
// create status label that is just off screen below the app view
_statusLabel = [[UILabel alloc] init];
_statusLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size:12.0];
_statusLabel.backgroundColor = [UIColor darkGrayColor];
_statusLabel.textColor = [UIColor whiteColor];
CGSize size = [#"Hey!" sizeWithFont:_statusLabel.font]; // test size of box with random text
_statusLabel.frame = CGRectMake(0.0, frame.size.height, frame.size.width, size.height);
_statusLabel.textAlignment = UITextAlignmentCenter;
_statusLabel.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
[self.view addSubview:_statusLabel];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self createControlsWithStatusHidden];
_statusHidden = YES;
// I'm instantiating from storyboard. If you're using NIBs, just create your controller controller using initWithNib and then set our appController accordingly.
self.appController = [self.storyboard instantiateViewControllerWithIdentifier:#"MainNavigator"];
}
- (void)setAppController:(UIViewController *)controller
{
if (controller)
{
controller.view.frame = CGRectMake(0.0, 0.0, _appView.frame.size.width, _appView.frame.size.height);
[self addChildViewController:controller];
[controller didMoveToParentViewController:self];
if (self.appController)
{
// if we have both a new controller and and old one, then let's transition, cleaning up the old one upon completion
[self transitionFromViewController:self.appController
toViewController:controller
duration:0.5
options:UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionCurveEaseInOut
animations:nil
completion:^(BOOL finished){
if (self.appController)
{
[self.appController willMoveToParentViewController:nil];
[self.appController removeFromParentViewController];
}
}];
}
else
{
// if we have no previous controller (i.e. this is our first rodeo), then just add it to the view
[_appView addSubview:controller.view];
}
}
else
{
// no new controller, so we're just removing any old on if it was there
if (self.appController)
{
// if there was an old controller, remove it's view, and remove it from the view controller hierarchy
[self.appController.view removeFromSuperview];
[self.appController willMoveToParentViewController:nil];
[self.appController removeFromParentViewController];
}
}
_appController = controller;
}
- (void)hideStatusWithCompletion:(void (^)(BOOL finished))completion
{
[UIView animateWithDuration:0.25
animations:^{
CGRect labelFrame = _statusLabel.frame;
labelFrame.origin.y += labelFrame.size.height;
_statusLabel.frame = labelFrame;
CGRect appFrame = _appView.frame;
appFrame.size.height += labelFrame.size.height;
_appView.frame = appFrame;
}
completion:completion];
}
- (void)unhideStatusWithCompletion:(void (^)(BOOL finished))completion
{
[UIView animateWithDuration:0.25
animations:^{
CGRect labelFrame = _statusLabel.frame;
labelFrame.origin.y -= labelFrame.size.height;
_statusLabel.frame = labelFrame;
CGRect appFrame = _appView.frame;
appFrame.size.height -= labelFrame.size.height;
_appView.frame = appFrame;
}
completion:completion];
}
- (void)setStatus:(NSString *)text
{
BOOL hasText = (text && [text length] > 0);
if (hasText)
{
if (!_statusHidden)
{
// if we have text, but status is already shown, then hide it and unhide it with new value
[self hideStatusWithCompletion:^(BOOL finished){
_statusLabel.text = text;
[self unhideStatusWithCompletion:nil];
}];
}
else
{
// if we have text, but no status is currently shown, then just unhide it
_statusLabel.text = text;
[self unhideStatusWithCompletion:nil];
}
_statusHidden = NO;
}
else
{
if (!_statusHidden)
{
// if we don't have text, but status bar is shown, then just hide it
[self hideStatusWithCompletion:^(BOOL finished){
_statusLabel.text = text;
}];
_statusHidden = YES;
}
}
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
And then, any view controller that wants to update the status message would use a method kind of like:
- (void)setStatus:(NSString *)text
{
UIViewController *controller = [UIApplication sharedApplication].delegate.window.rootViewController;
if ([controller isKindOfClass:[StatusBarViewController class]])
{
[(StatusBarViewController *)controller setStatus:text];
}
}

Best practice to calculate view size within loadView method

What is the best practice to calculate the view size in the loadView method (in an UIViewController) without a XIB file?
Here is my solution:
- (void)loadView {
//Calculate Screensize
BOOL statusBarHidden = [[UIApplication sharedApplication] isStatusBarHidden ];
BOOL navigationBarHidden = [self.navigationController isNavigationBarHidden];
BOOL tabBarHidden = [self.tabBarController.tabBar isHidden];
CGRect frame = [[UIScreen mainScreen] bounds];
if (!statusBarHidden) {
frame.size.height -= [[UIApplication sharedApplication] statusBarFrame].size.height;
}
if (!navigationBarHidden) {
frame.size.height -= self.navigationController.navigationBar.frame.size.height;
}
if (!tabBarHidden) {
frame.size.height -= self.tabBarController.tabBar.frame.size.height;
}
UIView *v = [[UIView alloc] initWithFrame: frame];
[v setBackgroundColor: [UIColor whiteColor] ];
[v setAutoresizingMask: UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight ];
[self setView: v ];
[v release];
}
Is this code okay, or should I edit something?
The docs recommend using [[UIScreen mainScreen] applicationFrame] to get the screen bounds without the status bar
so for anyone who want to know a best practice example:
#pragma mark -
#pragma mark LoadView Methods
- (void)loadView {
//Calculate Screensize
BOOL statusBarHidden = [[UIApplication sharedApplication] isStatusBarHidden ];
BOOL navigationBarHidden = [self.navigationController isNavigationBarHidden];
BOOL tabBarHidden = [self.tabBarController.tabBar isHidden];
BOOL toolBarHidden = [self.navigationController isToolbarHidden];
CGRect frame = [[UIScreen mainScreen] applicationFrame];
//check if you should rotate the view, e.g. change width and height of the frame
BOOL rotate = NO;
if ( UIInterfaceOrientationIsLandscape( [UIApplication sharedApplication].statusBarOrientation ) ) {
if (frame.size.width < frame.size.height) {
rotate = YES;
}
}
if ( UIInterfaceOrientationIsPortrait( [UIApplication sharedApplication].statusBarOrientation ) ) {
if (frame.size.width > frame.size.height) {
rotate = YES;
}
}
if (rotate) {
CGFloat tmp = frame.size.height;
frame.size.height = frame.size.width;
frame.size.width = tmp;
}
if (statusBarHidden) {
frame.size.height -= [[UIApplication sharedApplication] statusBarFrame].size.height;
}
if (!navigationBarHidden) {
frame.size.height -= self.navigationController.navigationBar.frame.size.height;
}
if (!tabBarHidden) {
frame.size.height -= self.tabBarController.tabBar.frame.size.height;
}
if (!toolBarHidden) {
frame.size.height -= self.navigationController.toolbar.frame.size.height;
}
UIView *v = [[UIView alloc] initWithFrame: frame];
v.backgroundColor = [UIColor whiteColor];
v.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.view = v;
[v release]; //depends on your ARC configuration
}
You are adjusting the height depend on the status bar and navigation bars.. But you have not done anything with respect to the origin of the view.

Resources