iOS8 UISearchBar in UIToolbar has no left padding - uitableview

I have a UIViewController class that contains a UITableView. In the table view header, I have a UIToolbar containing, among other things, a UISearchBar. In iOS8, when I tap on the search bar to search, the search display controller animates the bar to the top of the screen as expected, but the search bar has no margin on the left hand side.
The most stripped down of the code that reproduces is as follows:
- (void)viewDidLoad {
[super viewDidLoad];
UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, 0.0, [self tableView].frame.size.width, 44.0)];
if ([toolbar respondsToSelector:#selector(setBarTintColor:)]) {
[toolbar setBarTintColor:[UIColor lightGrayColor]];
}
[[self tableView] setTableHeaderView:toolbar];
UIView *searchBarView = [[UIView alloc] initWithFrame:[[[self searchDisplayController] searchBar] frame]];
[[[self searchDisplayController] searchBar] setBackgroundImage:[[UIImage alloc] init]];
[searchBarView addSubview:[[self searchDisplayController] searchBar]];
[[[self searchDisplayController] searchBar] setText:#""];
UIBarButtonItem *searchBarItem = [[UIBarButtonItem alloc] initWithCustomView:searchBarView];
[toolbar setItems:#[searchBarItem]];
}
Any help / suggestions is greatly appreciated.
Edit: This works correctly on iOS 6.1 and 7.0/1

It seem to be a iOS8 bug.
You can use a temporary solution from this
Basically, you can create a subclass of UIToolbar.
Then in subclass you just created, add this code to append missing space:
#define DEFAULT_APPLE_PADDING 20.0f
-(void)layoutSubviews{
[super layoutSubviews];
[self.subviews enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) {
if ([NSStringFromClass(view.class) hasPrefix:#"UIToolbar"] &&
[NSStringFromClass(view.class) hasSuffix:#"Button"]) {
CGRect buttonFrame = view.frame;
if (buttonFrame.origin.x == 0) {
buttonFrame.origin.x = DEFAULT_APPLE_PADDING;
} else if (buttonFrame.origin.x + buttonFrame.size.width == self.bounds.size.width) {
buttonFrame.origin.x -= DEFAULT_APPLE_PADDING;
}
view.frame = buttonFrame;
}
}];
}

Related

SearchBar moves when active

I have a UIViewController with a SegmentedControl, UITableView and a UISearchController. The SegmentedControl is at the top of the main View with the tableView just beneath it. The searchController's searchBar is placed in the tableView.tableHeaderView and looks like this:
When the searchBar is tapped (made active) it moves down leaving a gap just above:
Also, if the searchBar is active and then the segmentedConrol is tapped (filtering the table data and reloading the tableView) then the tableView loads but with a gap at the top. (I have purposely set the searchBar to hidden when the 'Category' filter is selected.
If the segmentedControl 'Category' is selected when the searchBar is not active this is how it looks (and should look):
I need two things (I think they are related), 1) for the searchBar to NOT move when active and 2) for the searchBar to not be present when 'Category' is selected and for the tableView to have no gap at the top.
.h:
#interface ExhibitorViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, UISearchControllerDelegate, UISearchBarDelegate, UISearchResultsUpdating>
{
// DATA
NSMutableArray *arrayOfExhibitors;
NSMutableArray *arrayOfExhibitorsFiltered;
NSMutableArray *arrayOfCategories;
NSMutableArray *arrayOfCategoriesFiltered;
// VARS
int selectedSegment;
float searchBarHeight;
float tableViewY;
NSString *currentCategory;
CGRect tableViewStartRect;
// UI
UISegmentedControl *segmentedControl;
UIView *categorySelectedView;
UIView *headerView;
}
#property (nonatomic, strong) UITableView *tableView;
#property (nonatomic, strong) UISearchController *searchController;
#property (nonatomic, readonly) NSArray *searchResults;
#property (strong, nonatomic) NSString *sponsorsOnly;
#end
.m:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:NO animated:NO];
if (selectedSegment == 0) {
self.searchController.searchBar.hidden = FALSE;
}
if (!_searchController.searchBar.superview) {
self.tableView.tableHeaderView = self.searchController.searchBar;
}
}
-(void)loadTableView
{
[self printStats:#"loadTableView START"];
searchBarHeight = self.searchController.searchBar.frame.size.height;
Settings *settingsInstance = [Settings new];
if(!_tableView) {
segmentedControl = [UISegmentedControl new];
segmentedControl = [[UISegmentedControl alloc]initWithItems:[NSArray arrayWithObjects:#"Exhibitor", #"Category", nil]];
[segmentedControl setFrame:CGRectMake(0, 0, self.view.frame.size.width, 35)];
segmentedControl.selectedSegmentIndex = 0;
[segmentedControl addTarget:self action:#selector(segmentedControlHasChangedValue) forControlEvents:UIControlEventValueChanged];
self.automaticallyAdjustsScrollViewInsets = YES;
self.edgesForExtendedLayout = UIRectEdgeNone;
self.searchController.hidesNavigationBarDuringPresentation = NO;
//self.definesPresentationContext = NO;
float tvX = self.view.frame.origin.x;
float tvY = self.view.frame.origin.y + segmentedControl.frame.size.height;
float tvWidth = self.view.frame.size.width;
float frameHeight = self.view.frame.size.height;
float tvHeight = self.view.frame.size.height - segmentedControl.frame.size.height;
tableViewStartRect = CGRectMake(tvX, tvY, tvWidth, tvHeight);
_tableView = [UITableView new];
_tableView = [[UITableView alloc] initWithFrame:tableViewStartRect];
//_tableView.contentInset = UIEdgeInsetsMake(0, 0, 44, 0);
_tableView.separatorColor = [UIColor clearColor];
_tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
[self.view addSubview:segmentedControl];
[self.view addSubview:_tableView];
[_tableView setTag:1];
[_tableView setDataSource:self];
[_tableView setDelegate:self];
}
if (!categorySelectedView) {
float levelOneStart = (0);
categorySelectedView = [[UIView alloc] initWithFrame:CGRectMake(0, levelOneStart, self.view.frame.size.width, (screenHeight * 0.05))];
[categorySelectedView setBackgroundColor:[UIColor grayColor]];
[categorySelectedView setTag:4];
MyLabel *catSelectedLabel = [[MyLabel alloc] initWithFrame:categorySelectedView.frame];
[catSelectedLabel setFont:[UIFont systemFontOfSize:[settingsInstance getFontSizeFor:#"Label"]]];
[catSelectedLabel setTag:5];
[catSelectedLabel setBackgroundColor:[UIColor lightTextColor]];
[catSelectedLabel setTextColor:[UIColor darkGrayColor]];
UIButton *categoryBackButton = [[UIButton alloc] initWithFrame:CGRectMake((screenWidth * 0.6), levelOneStart, (screenWidth * 0.4), (screenHeight * 0.05))];
[categoryBackButton setTitle:#"^ Back ^" forState:UIControlStateNormal];
[categoryBackButton setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal];
[categoryBackButton addTarget:self action:#selector(resetTableViewCategories) forControlEvents:UIControlEventTouchUpInside];
[catSelectedLabel addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(resetTableViewCategories)]];
[categoryBackButton.titleLabel setFont:[UIFont systemFontOfSize:[settingsInstance getFontSizeFor:#"Label"]]];
[categorySelectedView addSubview:catSelectedLabel];
[categorySelectedView addSubview:categoryBackButton];
[categorySelectedView setHidden:TRUE];
}
if (!headerView) {
headerView = [[UIView alloc] initWithFrame:CGRectMake(0, (0), screenWidth, (searchBarHeight))];
[headerView addSubview:categorySelectedView];
[self.view addSubview:headerView];
[headerView setBackgroundColor:[UIColor purpleColor]];
[self.view sendSubviewToBack:headerView];
}
[self.view setTag:11];
tableViewY = _tableView.frame.origin.y;
[self printStats:#"loadTableView END"];
}
-(UISearchController*)searchController
{
if (!_searchController) {
_searchController = [[UISearchController alloc]initWithSearchResultsController:nil];
_searchController.searchResultsUpdater = self;
_searchController.dimsBackgroundDuringPresentation = NO;
_searchController.searchBar.delegate = self;
[_searchController.searchBar sizeToFit];
}
return _searchController;
}
-(void)segmentedControlHasChangedValue
{
[self.searchController setActive:NO];
if ((segmentedControl.selectedSegmentIndex == 0)) {
selectedSegment = 0;
currentCategory = #"";
[self resetTableViewExhibitors];
[_tableView setContentOffset:CGPointMake(0, -1) animated:NO];
} else {
selectedSegment = 1;
[self resetTableViewCategories];
[_tableView setContentOffset:CGPointMake(0, -1) animated:NO];
//[_tableView setContentOffset:CGPointMake(0, 56) animated:NO];
[_tableView setTableFooterView:nil];
}
[_tableView reloadData];
}
I have tried changing the insets of various views and forcing a manual changes to the frames of various views (this is the closest thing to a fix but seems very hacky). What am I doing wrong?
Edit: Have also tried :
-(void)segmentedControlHasChangedValue
{
[self.searchController setActive:NO];
if ((segmentedControl.selectedSegmentIndex == 0)) {
selectedSegment = 0;
currentCategory = #"";
[self resetTableViewExhibitors];
[_tableView setContentOffset:CGPointMake(0, -1) animated:NO];
} else {
selectedSegment = 1;
[_searchController dismissViewControllerAnimated:NO completion^() {
[self resetTableViewCategories];
[_tableView setContentOffset:CGPointMake(0, -1) animated:NO];
[_tableView setTableFooterView:nil];
}];
}
[_tableView reloadData];
}
Because you use UISearchController so searchBar will always move when it actives. To avoid it, use UISearchBar. And when you use UISearchBar, it's easy to hide when you select Category tab

UIImagePickerController duplicates content on close

When I bring up a UIImagePickerController and then close it, it duplicates the content in my modal window. Below are the before and after pictures:
Here's the code that shows the image picker:
-(void) choosePhotos
{
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
[imagePicker setDelegate:self];
[imagePicker setAllowsEditing:YES];
[imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
[self presentViewController:imagePicker animated:YES completion:nil];
}
Here's the rest of my code (if needed):
-(id) init
{
self = [super init];
if (self)
{
[self.navigationItem setTitle:#"Deposit"];
UIBarButtonItem *closeButton = [[UIBarButtonItem alloc] initWithTitle:#"Cancel" style:UIBarButtonItemStyleDone target:self action:#selector(cancel)];
[self.navigationItem setLeftBarButtonItem:closeButton];
toItems = #[#"Account...5544", #"Account...5567"];
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(hideKeyboard)];
[self.view addGestureRecognizer:recognizer];
}
return self;
}
-(void) hideKeyboard
{
for (UITextField *field in [scrollView subviews])
{
[field resignFirstResponder];
}
}
-(void) cancel
{
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return [toItems count];
}
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return [toItems objectAtIndex:row];
}
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
[self.view setBackgroundColor:[UIColor whiteColor]];
UILabel *toLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 0, 50, 100)];
[toLabel setText:#"To:"];
toPicker = [[UIPickerView alloc] initWithFrame:CGRectMake(130, -30, 220, 100)];
[toPicker setDataSource:self];
[toPicker setDelegate:self];
UILabel *amountLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 100, 70, 100)];
amountLabel.lineBreakMode = NSLineBreakByWordWrapping;
amountLabel.numberOfLines = 0;
[amountLabel setText:#"Check Amount:"];
UITextField *amountField = [[UITextField alloc] initWithFrame:CGRectMake(130, 100, 270, 100)];
[amountField setPlaceholder:#"Enter Amount"];
[amountField setReturnKeyType:UIReturnKeyDone];
[amountField setKeyboardType:UIKeyboardTypeDecimalPad];
UILabel *imagesLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 200, 70, 100)];
imagesLabel.lineBreakMode = NSLineBreakByWordWrapping;
imagesLabel.numberOfLines = 0;
[imagesLabel setText:#"Check Images:"];
UIButton *imagesButton = [[UIButton alloc] initWithFrame:CGRectMake(120, 200, 244, 99)];
[imagesButton setBackgroundImage:[UIImage imageNamed:#"photos.png"] forState:UIControlStateNormal];
[imagesButton addTarget:self action:#selector(choosePhotos) forControlEvents:UIControlEventTouchUpInside];
CGRect bounds = [[UIScreen mainScreen] bounds];
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, bounds.size.width, bounds.size.height)];
[scrollView setAlwaysBounceVertical:YES];
[scrollView setShowsVerticalScrollIndicator:YES];
[scrollView addSubview:toLabel];
[scrollView addSubview:toPicker];
[scrollView addSubview:amountLabel];
[scrollView addSubview:amountField];
[scrollView addSubview:imagesLabel];
[scrollView addSubview:imagesButton];
[self.view addSubview:scrollView];
}
I recommend you use viewDidLoad as the place to create and add your views:
- (void)viewDidLoad {
[super viewDidLoad];
//init and add your views here
//example view
self.someLabel = [[UILabel alloc] init];
self.someLabel.text = #"someExampleText";
[self.view addSubview:self.someLabel];
}
And either viewWillAppear or viewDidLayoutSubviews as the place to configure their sizes (i prefer viewDidLayoutSubviews so i'll use it as an example):
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.someLabel.frame = CGRectMake(kMargin,kMargin,kLabelWidth,kLabelHeight);
}
Of course, in order to do this you need to have a reference to all the views you wish to configure this way by creating a property to them in the interface:
#interface YourViewController ()
#property (nonatomic, strong) UILabel *someLabel;
#end;
static CGFloat const kMargin = 20.0f;
static CGFloat const kLabelHeight = 30.0f;
static CGFloat const kLabelWidth = 100.0f;
Also, it is recommended you avoid using hard coded values for their sizes (doing it like CGRectMake(20,20,100,70) but this it not completely wrong.
Not using hard coded values does not mean setting them yourself, it just means to make their values more readable (and on most cases, dynamic).
In my example, i created kMargin, kLabelHeight and kLabelWidth, meaning that anyone who looks at this code will understand what they mean, they will know what to change if needed, and these values can be used in other places.
For example, you could have 4 labels, and in order to keep them all following the same layout rules, all of them will use the kMargin value on the origin.x.
You could also, instead of using a static value for the width, you can implement a dynamic value, like this:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
CGFloat labelWidth = self.view.bounds.size.width - (kMargin * 2);
self.someLabel.frame = CGRectMake(kMargin,kMargin,labelWidth,kLabelHeight);
}
What i did here is to make my label to have the same width as my super view, but i made it account for the left and the right margins (by taking the total view width and reducing twice the margin value).
Since we are doing this on the viewDidLayoutSubviews method, which gets called whenever the superview changes its size (for example, orientation change) this will ensure your UILabel can be shown on any size of view and orientation without extra code to handle 'specific cases'.
Your UI elements are being added to your view every time viewWillAppear is called. This is called when your image picker dismisses and returns to your view, so they're being duplicated. Either check to see whether your UI elements already exist before creating them again, or do your UI setup in the viewDidLoad method which will only be run once. You could try this perhaps, using a BOOL property to keep track:
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
if (!self.alreadyAppeared) {
self.alreadyAppeared = YES;
// Create labels and buttons
}
}

Making a list of UIViews that slide up and down when touched

I'm trying to figure out an approach to build something like the image below, which is a list of items that when a section is clicked slides out content. It's a really common UX on most websites and what not. My idea is to have each gray box (button) slide out a UIView containing some other items. I'm still new to iOS development but I'm struggling to find how you can animate a UIView to slide down and push the content below it down as well. Hoping some one can give me a good starting point or point to some info outside the realm of the apple docs.
Thanks!
So if you just have a few views, I would not recommend the UITableView approach, since it is not so easy to customize with animations and table views usually want to fill the whole screen with cells. Instead write a expandable UIView subclass that has the desired two states. Add a method to switch between extended and collapsed state. On expanding/collapsing adjust their positions so that they always have enough space.
I provide you an example of views adjusting their frames. I guess it should be easy to do the same with auto layout constraints: give the views a fixed height constraint and change this on collapsing/expanding. The same way set the constraints between the views to be 0 so that they are stacked on top of each other.
Expandable View:
#interface ExpandingView(){
UIView *_expandedView;
UIView *_seperatorView;
BOOL _expanded;
}
#end
#implementation ExpandingView
- (id)init
{
self = [super initWithFrame:CGRectMake(15, 0, 290, 50)];
if (self) {
_expanded = NO;
self.clipsToBounds = YES;
_headerView = [[UIView alloc] initWithFrame:self.bounds];
_headerView.backgroundColor = [UIColor colorWithWhite:0.8 alpha:1];
[self addSubview:_headerView];
_seperatorView = [[UIView alloc] initWithFrame:CGRectMake(0, self.bounds.size.height-1, self.bounds.size.width, 1)];
_seperatorView.backgroundColor = [UIColor lightGrayColor];
[self addSubview:_seperatorView];
_expandedView = [[UIView alloc] initWithFrame:CGRectOffset(self.bounds, 0, self.bounds.size.height)];
_expandedView.backgroundColor = [UIColor blueColor];
[self addSubview:_expandedView];
}
return self;
}
- (void)layoutSubviews{
[self adjustLayout];
}
- (void)adjustLayout{
_headerView.frame = CGRectMake(0, 0, self.bounds.size.width, 50);
_seperatorView.frame = CGRectMake(0, 49, self.bounds.size.width, 1);
_expandedView.frame = CGRectMake(0, 50, self.bounds.size.width, self.bounds.size.height-50);
}
- (void)toggleExpandedState{
_expanded = !_expanded;
self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, _expanded?200:50);
[self adjustLayout];
}
#end
ViewController:
#interface ExpandingViewController (){
NSArray *_expandingViews;
}
#end
#implementation ExpandingViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_expandingViews = #[
[[ExpandingView alloc] init],
[[ExpandingView alloc] init],
[[ExpandingView alloc] init],
];
for(ExpandingView *view in _expandingViews){
[view.headerView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(expandingViewTapped:)]];
[self.view addSubview:view];
}
}
- (void)viewWillLayoutSubviews{
int y = 100;
for(ExpandingView *view in _expandingViews){
view.frame = CGRectOffset(view.bounds, (CGRectGetWidth(self.view.bounds)-CGRectGetWidth(view.bounds))/2, y);
y+=view.frame.size.height;
}
}
- (void)expandingViewTapped:(UITapGestureRecognizer*)tapper{
ExpandingView *view = (ExpandingView*)tapper.view.superview;
[UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:0 options:0 animations:^{
[view toggleExpandedState];
[self.view layoutIfNeeded];
} completion:nil];
}

UIView only shows after being called the second time

I have a view controller that is calling a custom UIView via an IBAction.The custom view contains a UIPickerView that slides up from the bottom of the screen and a toolbar with 'cancel' and 'done' buttons above it. The problem is that the view only appears on the screen after being called for the second time. Using breakpoints I can verify that every single line of code is being called both times. Everything seems to be happening the same way each time. Nothing is NIL, and in fact it's like this for the duration that the app is running, not only the first time it's called. You always have to click the button twice to get the view to appear for as long as the app is running.
Admittedly, the code for the custom picker view is not mine. I copied it from someone else's example. I'm not sure if it's the problem or not. I don't see how it could be, but I'm a bit over my head here. This is how I'm calling the view from my view controller.
- (IBAction)statusPickerButtonPressed:(id)sender {
self.scrollPickerView = [[StatusPickerView alloc]init];
[self.navigationController.view addSubview:self.scrollPickerView];
self.scrollPickerView.delegate = self;
self.scrollPickerView.dataSource = self;
}
and here's the custom UIView
#import "StatusPickerView.h"
#interface StatusPickerView ()
#property NSArray *pickerArray;
#property NSInteger selectedRow;
#end
#implementation StatusPickerView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setToolbar];
[self becomeFirstResponder];
float screenWidth = [UIScreen mainScreen].bounds.size.width;
float pickerWidth = screenWidth * 3 / 4;
float xPoint = screenWidth / 2 - pickerWidth / 2;
[self setFrame: CGRectMake(xPoint, 50.0f, pickerWidth, 180.0f)];
self.showsSelectionIndicator = YES;
[self selectRow:3 inComponent:0 animated:YES];
}
return self;
}
-(void)setToolbar
{
_toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
[_toolbar setBarStyle:UIBarStyleDefault];
UIBarButtonItem * btnCancel = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
target:self action:#selector(barbtnPressed:)];
UIBarButtonItem * flexible = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:nil action:nil];
UIBarButtonItem * btnDone = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self action:#selector(barbtnPressed:)];
[btnCancel setTag:1];
[btnCancel setStyle:UIBarButtonItemStyleBordered];
[btnDone setTag:2];
[btnDone setStyle:UIBarButtonItemStyleBordered];
NSArray * btnArray = [[NSArray alloc] initWithObjects:btnCancel, flexible, btnDone, nil];
[_toolbar setItems:btnArray];
self.inputAccessoryView = _toolbar;
self.inputView = self;
}
-(BOOL)canBecomeFirstResponder
{
return true;
}
-(void)barbtnPressed:(id)sender
{
NSInteger tag = [sender tag];
switch (tag) {
case 1:
{
[self removeFromSuperview];
break;
}
case 2:{
[self removeFromSuperview];
self.selectedRow = [self selectedRowInComponent:0];
[[NSNotificationCenter defaultCenter]postNotificationName:#"user_selected_new_section" object:self];
}
default:
break;
}
}
-(int)giveSelectedRow{
return self.selectedRow;
}
I'm fully prepared to feel foolish here, as the solution is probably obvious, just not obvious to myself.
edit:
I tried using [self.view.window addSubview:self.scrollPickerView]; instead of [self.navigationController.view addSubview:self.scrollPickerView];, and the behavior is exactly the same.
This line:
[self.navigationController.view addSubview:self.scrollPickerView];
should read:
[self.view addSubview:self.scrollPickerView];
You’re calling -init instead of -initWithFrame:, so your view is ending up with the default frame of CGRectZero. Considering that you’re then making a frame of your own, that call might as well pass that in to start out with:
self.scrollPickerView = [[ScrollPickerView alloc] initWithFrame:CGRectZero];
Alternatively, you could keep the current self.scrollPickerView = … code and change the -initWithFrame: to an -init, like this:
- (id)init
{
float screenWidth = [UIScreen mainScreen].bounds.size.width;
float pickerWidth = screenWidth * 3 / 4;
float xPoint = screenWidth / 2 - pickerWidth / 2;
self = [super initWithFrame:CGRectMake(xPoint, 50.0f, pickerWidth, 180.0f)];
if (self) {
[self setToolbar];
[self becomeFirstResponder];
self.showsSelectionIndicator = YES;
[self selectRow:3 inComponent:0 animated:YES];
}
return self;
}

Determine if current screen has visible navigation bar

I have a singlton object. Is there any simple way to determine if current screen contains a navigation bar within singlton methods?
The singleton is UIView subclass. It's designed for showing prorgess activity, e.g. network exchange. It looks like black rectangle dropping down from top and hiding when the work is done. Why singleton? It's easy to call it from any place of code
The followed snippet is showing the initialization of activity singleton and published here just for better understaning my idea.
-(void) showUpdatingView:(NSString *) msg {
[self initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 44)];
activity = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite] autorelease];
activity.frame = CGRectMake(5, 10, 22, 22);
labelView = [[[UILabel alloc] initWithFrame:CGRectMake(35, 10, [UIScreen mainScreen].bounds.size.width - 10, 22)] autorelease];
labelView.font = [UIFont boldSystemFontOfSize:12];
labelView.backgroundColor = [UIColor clearColor];
labelView.textColor = [UIColor whiteColor];
labelView.text = msg;
[self addSubview:activity];
[self addSubview:labelView];
self.backgroundColor = [UIColor blackColor];
self.alpha = 0.7;
}
The activity can be called by
[[ActivitySingleton getInstance] showUpdatingView:#"Getting data."];
it's not all.
The singleton is being created in AppDelegate object and the view is added to
inlineActivity = [[CHInlineActivityView alloc] initView];
[self.window.rootViewController.view addSubview:inlineActivity];
I know it may look crazy. But when I was designing it seemed to me reasonable
if you have all in one navigationController:
BOOL navHidden = self.window.rootViewController.navigationController.navigatonBarHidden;
if you don't it is a bit harder.. you could check the window's subviews and see if you can find a UINavigationBar
id navbar = [self.window firstSubviewOfKind:[UINavigationBar class] withTag:NSNotFound];
BOOL navHidden = navbar == nil;
#implementation NSView (findSubview)
- (NSArray *)findSubviewsOfKind:(Class)kind withTag:(NSInteger)tag inView:(NSView*)v {
NSMutableArray *array = [NSMutableArray array];
if(kind==nil || [v isKindOfClass:kind]) {
if(tag==NSNotFound || v.tag==tag) {
[array addObject:v];
}
}
for (id subview in v.subviews) {
NSArray *vChild = [self findSubviewsOfKind:kind withTag:tag inView:subview];
[array addObjectsFromArray:vChild];
}
return array;
}
#pragma mark -
- (NSView *)firstSubviewOfKind:(Class)kind withTag:(NSInteger)tag {
NSArray *subviews = [self findSubviewsOfKind:kind withTag:tag inView:self];
return subviews.count ? subviews[0] : nil;
}
#end

Resources