UIView only shows after being called the second time - ios

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;
}

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
}
}

iOS8 UISearchBar in UIToolbar has no left padding

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;
}
}];
}

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

Refactor iOS ViewController to work without needing a nib

I wrote a nice gallery view controller .h .m and .xib that work fine for my purposes. Tap a programmatically created button and load an image, play a movie or view a pdf or website - while in an existing uinavigationcontroller. I want to change it so I can add the contents of the xib in code - without using the nib file. In this way it will be more useable (I think).
The problem is the functions in the .m that reference, for instance - [self presentMoviePlayerViewControllerAnimated:YES] etc do not work. I tried making a property of the rootviewcontroller in this new .h and .m and replacing self with myController (property name). But my view controller code relies on uinavigation existing to push new content or things like that. How can I remove/tweak these references to self or a reliance on uinavigationcontrollers so it will work like when it has a view controller for a nib?
Edit: Code added below. In the nib there is just a uiscrollview called uis_thumbScrollView. I would like to add this anywhere by simply calling something like:
[self.view addSubview:[[ebThumbScroller alloc] initWithFrame:CGRectMake(0, 0, 1024, 733)]];
Everyone's comments reminded me that the uiview this will be put in exists within the rootviewcontroller, over the top. Maybe this is why I can hear the movie playing - but not see it.
Note: The code creates a series of uiviews with buttons inside of a uiscrollview.
.h
#import
#import "ebAppDelegate.h"
#import "MediaPlayer/MediaPlayer.h"
#interface HomeGalleryViewController : UIViewController <UIScrollViewDelegate, UIGestureRecognizerDelegate, UIDocumentInteractionControllerDelegate> {
BOOL pageControlBeingUsed;
int buttonCount;
CGFloat _minimumColumnGap;
UIEdgeInsets _contentInsets;
NSInteger _colCount;
NSInteger _rowCount;
CGFloat _rowGap;
CGFloat _colGap;
UIEdgeInsets _effectiveInsets;
//int iGalleryThumbs;
//int iPlanThumbs;
int iTotalButtons;
ebAppDelegate *ebappdelegate;
ebGalleryItem *ebgalleryItem;
NSDictionary *gallDict;
NSArray *gallerySections;
NSArray *galleryArray;
NSMutableArray *nsm_gallArray;
UIDocumentInteractionController *controller;
}
//#property (nonatomic, retain) IBOutlet UIButton *bItem;
#property (nonatomic, retain) NSString *galleryNameString;
#property (nonatomic, retain) IBOutlet UIScrollView* scrollView;
#property (retain, nonatomic) NSMutableArray *arr_Views;
#property (strong, nonatomic) IBOutlet UIScrollView* uis_thumbScrollView;
#property (strong, nonatomic) IBOutlet UIPageControl* uis_pageControl;
#property (strong, nonatomic) IBOutlet UIView *uiv_thumbView;
#property (strong, nonatomic) MPMoviePlayerController *player;
#property (strong, nonatomic) MPMoviePlayerViewController *playerViewController;
- (IBAction)changePage;
- (IBAction) clickOpen:(id)sender;
- (void)playMovie:(NSString*)movieName;
- (void)movieFinishedCallback:(NSNotification*)_notification;
#end
.m
#import "HomeGalleryViewController.h"
#import "ebAppDelegate.h"
#import "GalleryImagesViewController.h"
#import "Gallery.h"
#import "GalleryThumbnailsViewController.h"
#import "GalleriesListViewController.h"
#import <QuartzCore/CoreAnimation.h>
#import "ebGalleryItem.h"
#import "WebViewController.h"
#implementation HomeGalleryViewController
// buttons
#define hGutter 17
#define vGutter 13
#define btnSize 130
#define topSpace 50
#define leftMargin 100
#synthesize uiv_thumbView;
#synthesize uiv_gallCat0, uiv_gallCat1, uiv_gallCat2,uiv_gallCat3, uiv_gallCat4, uiv_gallCat5,uiv_gallCat6;
#synthesize uis_thumbScrollView, uis_pageControl;
#synthesize galleryNameString,scrollView,arr_Views;
#synthesize player, playerViewController;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
ebappdelegate = (ebAppDelegate *)[[UIApplication sharedApplication] delegate];
arr_Views = [[NSMutableArray alloc] init];
self.scrollView.contentSize = CGSizeMake(1024, 1005);
// nsarray of dictionaries (galleries)
gallerySections = ebappdelegate.arr_galleryData;
NSLog(#"gallerySections count:%i",[gallerySections count]);
nsm_gallArray = [NSMutableArray arrayWithCapacity:1];
[self layoutGalleryThumbs];
}
#pragma mark
#pragma mark Layout Gallery Thumbs
-(void)layoutGalleryThumbs {
NSUInteger numGallSections = [gallerySections count];
NSLog(#"gallerySections data:%#",gallerySections);
NSLog(#"numGallSections count:%i",numGallSections);
// Window bounds.
CGRect bounds = CGRectMake(0, 0, 1024, 215);
for (int i=0; i<numGallSections; i++) {
// Create a view and add it to the window.
UIView* vview = [[UIView alloc] initWithFrame: CGRectMake(0, bounds.size.height*i-1, bounds.size.width, bounds.size.height)];
[vview setBackgroundColor: [UIColor whiteColor]];
[vview setTag:i];
//vview.backgroundColor = (UIColor (i % 2 == 0 ? cyanColor : whiteColor];
vview.backgroundColor = (i % 2 == 0)? [UIColor lightGrayColor] : [UIColor whiteColor];
[arr_Views addObject:vview];
// add line below at bottom
UIView* lineView = [[UIView alloc] initWithFrame: CGRectMake(280, bounds.size.height, 700, 2)];
[lineView setBackgroundColor: [UIColor grayColor]];
lineView.alpha = 0.5;
[vview addSubview:lineView];
[uis_thumbScrollView addSubview: vview];
NSLog(#"start===============i:%i",i);
// grab a gallery
gallDict = [gallerySections objectAtIndex:i]; // grab dict
galleryArray = [gallDict objectForKey:#"gallSectionData"]; // grab array from dict
NSLog(#"galleryArray:%#",[galleryArray description]);
NSString *secTitle = [gallDict objectForKey:#"gallSectionName"];
iTotalButtons = [galleryArray count];
NSLog(#"iTotalButtons count:%i",iTotalButtons);
_minimumColumnGap = 5;
_colCount = floorf((uis_thumbScrollView.bounds.size.width - _contentInsets.left - _contentInsets.right) / btnSize);
while (1) {
_colGap = (uis_thumbScrollView.bounds.size.width - _contentInsets.left - _contentInsets.right - btnSize * _colCount) / (_colCount + 1);
if (_colGap >= _minimumColumnGap)
break;
--_colCount;
};
_rowCount = (iTotalButtons + _colCount - 1) / _colCount;
_rowGap = _colGap;
_effectiveInsets = UIEdgeInsetsMake(_contentInsets.top + _rowGap,
_contentInsets.left + _colGap,
_contentInsets.bottom + _rowGap,
_contentInsets.right + _colGap);
NSLog(#"row count:%i",_rowCount);
NSLog(#"col count:%i",_colCount);
buttonCount=0;
for (int e=0; e<iTotalButtons; e++) {
NSLog(#"e:%i",e);
ebgalleryItem = [galleryArray objectAtIndex:e];
UIImage *thumbImg = [UIImage imageNamed:ebgalleryItem.gallThumb];
UIButton *button = [UIButton buttonWithType: UIButtonTypeCustom];
CGRect frame = CGRectMake (btnSize*e+leftMargin, topSpace,
btnSize-hGutter, btnSize-vGutter );
[button setFrame: frame];
NSLog(#"added button");
//[button setBackgroundImage:thumbImg forState:UIControlStateNormal];
[button setImage:thumbImg forState:UIControlStateNormal];
[button setTitle:ebgalleryItem.gallName forState:UIControlStateNormal];
NSLog(#"%#",button.titleLabel.text);
[button addTarget: NULL action:#selector(clickOpen:) forControlEvents:UIControlEventTouchUpInside];
UILongPressGestureRecognizer *tapAndHold = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longclickOpen:)];
[tapAndHold setMinimumPressDuration:0.33];
[button addGestureRecognizer:tapAndHold];
[button setTag:e];
//[button setTag:i*_colCount+e];
NSLog(#" button tag=%i", button.tag);
button.alpha=1.0;
[[arr_Views objectAtIndex:i] addSubview:button];
NSLog(#"middle====i:%i",i);
// caption label
CGRect labelFrame = CGRectMake( btnSize*e+leftMargin, 125,
btnSize-hGutter, btnSize-vGutter );
UILabel* label = [[UILabel alloc] initWithFrame: labelFrame];
[label setFont:[UIFont fontWithName:#"Arial" size:14]];
label.numberOfLines = 0;
[label setText:ebgalleryItem.gallCaption];
[label setTextColor: [UIColor blackColor]];
[label setTextAlignment:UITextAlignmentCenter];
[label setBackgroundColor:[UIColor clearColor]];
[[arr_Views objectAtIndex:i] addSubview: label];
NSLog(#"middle2====i:%i",i);
buttonCount++;
}
// Section Title label
CGRect titleLabelFrame = CGRectMake(btnSize,0,250,50);
UILabel* titlelabel = [[UILabel alloc] initWithFrame: titleLabelFrame];
[titlelabel setFont:[UIFont fontWithName:#"Arial" size:16]];
[titlelabel setText:secTitle];
[titlelabel setTextColor: [UIColor blackColor]];
[titlelabel setTextAlignment:UITextAlignmentLeft];
[titlelabel setBackgroundColor:[UIColor clearColor]];
[[arr_Views objectAtIndex:i] addSubview: titlelabel];
NSLog(#"end====i:%i",i);
CGFloat scrollViewHeight = 0.0f;
for (UIView* view in self.uis_thumbScrollView.subviews)
{
if (!view.hidden)
{
CGFloat y = view.frame.origin.y;
CGFloat h = view.frame.size.height;
if (y + h > scrollViewHeight)
{
scrollViewHeight = h + y;
}
}
}
[self.uis_thumbScrollView setContentSize:(CGSizeMake(self.uis_thumbScrollView.frame.size.width, scrollViewHeight+74))]; //74 is space from top in IB of scroll
}
uiv_thumbView.alpha = 1.0;
}
#pragma mark Scrollview
- (void)scrollViewDidScroll:(UIScrollView *)sender {
// Update the page when more than 50% of the previous/next page is visible
CGFloat pageWidth = self.uis_thumbScrollView.frame.size.width;
int page = floor((self.uis_thumbScrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
self.uis_pageControl.currentPage = page;
// nslogs zoomsacle/bounds
CGRect visibleRect;
visibleRect.origin = uis_thumbScrollView.contentOffset;
visibleRect.size = uis_thumbScrollView.bounds.size;
float theScale = 1.0 / [uis_thumbScrollView zoomScale];
visibleRect.origin.x *= theScale;
visibleRect.origin.y *= theScale;
visibleRect.size.width *= theScale;
visibleRect.size.height *= theScale;
NSLog( #"Visible rect: %#", NSStringFromCGRect(visibleRect) );
}
- (IBAction)changePage {
// update the scroll view to the appropriate page
CGRect frame;
frame.origin.x = self.uis_thumbScrollView.frame.size.width * self.uis_pageControl.currentPage;
frame.origin.y = 0;
frame.size = self.uis_thumbScrollView.frame.size;
[self.uis_thumbScrollView scrollRectToVisible:frame animated:YES];
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
pageControlBeingUsed = NO;
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
pageControlBeingUsed = NO;
}
//===================================================================
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft | interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
- (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 {
[self setUiv_thumbView:nil];
}
- (void)viewDidDisappear:(BOOL)animated {
}
- (void)viewWillAppear:(BOOL)animated {
[UIApplication sharedApplication].statusBarHidden = YES;
self.view.frame = [UIScreen mainScreen].applicationFrame;
CGRect frame = self.navigationController.navigationBar.frame;
frame.origin.y = 0;
self.navigationController.navigationBar.frame = frame;
[self.navigationController setNavigationBarHidden:YES animated:animated];
self.navigationController.navigationBar.translucent = YES;
}
- (void)viewWillDisappear:(BOOL)animated {
[UIApplication sharedApplication].statusBarHidden = NO;
CGRect frame = self.navigationController.navigationBar.frame;
frame.origin.y = 20.0;
self.navigationController.navigationBar.frame = frame;
}
- (void)viewDidAppear:(BOOL)animated {
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[self.navigationController setNavigationBarHidden:YES animated:animated];
[self.navigationController setToolbarHidden:YES animated:YES];
[super viewDidAppear:animated];
}
//======================================================================
-(IBAction)clickOpen:(id)sender {
UIButton *tmpBtn = (UIButton*)sender;
NSLog(#"sender tag: %i", [sender tag]);
int superviewTag = [sender superview].tag;
NSLog(#"sender superview tag: %i", superviewTag);
gallDict = [gallerySections objectAtIndex:superviewTag]; // grab dict
galleryArray = [gallDict objectForKey:#"gallSectionData"]; // grab array from dict
tmpBtn.alpha = 0.6;
ebgalleryItem = [galleryArray objectAtIndex:[sender tag]];
NSLog(#"%#",ebgalleryItem.gallType);
NSLog(#"%#",ebgalleryItem.gallName);
NSLog(#"gallDict %#",gallDict);
if ([ebgalleryItem.gallType isEqualToString:#"movie"]) {
[self playMovie:ebgalleryItem.gallFilm];
} else if ([ebgalleryItem.gallType isEqualToString:#"image"]) {
[self imageViewer:sender];
} else if ([ebgalleryItem.gallType isEqualToString:#"pdf"]) {
[self viewPDF:ebgalleryItem.gallName];
} else if ([ebgalleryItem.gallType isEqualToString:#"web"]) {
[self openWeb:ebgalleryItem.gallName];
}
}
#pragma mark
#pragma mark Open Websites
- (IBAction)openWeb:(NSString*)thisWEB {
WebViewController *webViewController = [[WebViewController alloc]
initWithNibName:#"WebViewController"
bundle:nil];
[webViewController socialButton:thisWEB];
webViewController.title = thisWEB;
[self presentModalViewController:webViewController animated:YES];
}
#pragma mark
#pragma mark Image Viewer
-(void)imageViewer:(id)sender {
UIButton *tmpBtn = (UIButton*)sender;
galleryNameString = tmpBtn.titleLabel.text;
tmpBtn.alpha = 0.6;
GalleryImagesViewController *vc = [[GalleryImagesViewController alloc] initWithGallery:[Gallery galleryNamed:galleryNameString]];
[vc goToPageAtIndex:0 animated:NO];
CATransition* transition = [CATransition animation];
transition.duration = 0.33;
transition.type = kCATransitionFade;
transition.subtype = kCATransitionFromTop;
[self.navigationController.view.layer
addAnimation:transition forKey:kCATransition];
[self.navigationController pushViewController:vc animated:NO];
}
#pragma mark
#pragma mark PDF Viewer
-(void)viewPDF:(NSString*)thisPDF {
NSString *fileToOpen = [[NSBundle mainBundle] pathForResource:thisPDF ofType:#"pdf"];
NSURL *url = [NSURL fileURLWithPath:fileToOpen];
NSLog(#"%#",fileToOpen);
controller = [UIDocumentInteractionController interactionControllerWithURL:url];
[self previewDocumentWithURL:url];
}
- (IBAction) clickClose:(id)sender {
[self dismissModalViewControllerAnimated:YES];
}
- (void)previewDocumentWithURL:(NSURL*)url
{
UIDocumentInteractionController* preview = [UIDocumentInteractionController interactionControllerWithURL:url];
preview.delegate = self;
[preview presentPreviewAnimated:YES];
}
//======================================================================
- (void)documentInteractionControllerDidDismissOptionsMenu:(UIDocumentInteractionController *)controller{
}
//===================================================================
- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller
{
return self;
}
- (UIView *)documentInteractionControllerViewForPreview:(UIDocumentInteractionController *)controller
{
return self.view;
}
- (CGRect)documentInteractionControllerRectForPreview:(UIDocumentInteractionController *)controller
{
return self.view.frame;
}
-(IBAction)longclickOpen:(UILongPressGestureRecognizer*)gesture {
if (gesture.state == UIGestureRecognizerStateBegan ) {
[self.navigationController setNavigationBarHidden:NO];
ebAppDelegate *appDelegate = (ebAppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.isFromLongPress=YES;
//NSUInteger i = [gesture.view tag];
//galleryNameString = [appDelegate.arr_galleryData objectAtIndex:i];
NSLog(#"load %#",galleryNameString);
UIButton *btn = (UIButton*)gesture.view;
galleryNameString = btn.titleLabel.text; btn.alpha = 0.6;
//NSLog(#"Long Press");
//NSLog(#"llongclickOpen");
UIViewController *vc = [[GalleryThumbnailsViewController alloc] initWithGallery:[Gallery galleryNamed:galleryNameString]];
CATransition* transition = [CATransition animation];
transition.duration = 0.33;
transition.type = kCATransitionFade;
transition.subtype = kCATransitionFromTop;
[self.navigationController.view.layer
addAnimation:transition forKey:kCATransition];
[self.navigationController pushViewController:vc animated:NO];
}
}
-(void)playMovie:(NSString*)movieName {
NSString *url = [[NSBundle mainBundle]
pathForResource:movieName
ofType:#"m4v"];
NSLog(#"%#",movieName);
playerViewController = [[MPMoviePlayerViewController alloc]
initWithContentURL:[NSURL fileURLWithPath:url]];
[[NSNotificationCenter defaultCenter] removeObserver:playerViewController
name:MPMoviePlayerPlaybackDidFinishNotification
object:playerViewController.moviePlayer];
// Register this class as an observer instead
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:playerViewController.moviePlayer];
[self.view insertSubview:playerViewController.view atIndex:50];
//---play movie---
player = [playerViewController moviePlayer];
player.controlStyle = MPMovieControlStyleFullscreen;
player.repeatMode=MPMovieRepeatModeOne;
[self presentMoviePlayerViewControllerAnimated:playerViewController];
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[super viewDidLoad];
}
- (void)movieFinishedCallback:(NSNotification*)aNotification {
// Obtain the reason why the movie playback finished
NSNumber *finishReason = [[aNotification userInfo] objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];
// Dismiss the view controller ONLY when the reason is not "playback ended"
if ([finishReason intValue] != MPMovieFinishReasonPlaybackEnded)
{
MPMoviePlayerController *moviePlayer = [aNotification object];
// Remove this class from the observers
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayer];
// Dismiss the view controller
[self dismissModalViewControllerAnimated:YES];
}
}
#end
If your only problem is the not working [self presentMoviePlayerViewControllerAnimated:YES] method, the problem is that presentMoviePlayerViewControllerAnimated: requires the actual moviePlayerViewController as an argument not a boolean value. (assuming you're refering to this method of the UIViewController category) UIViewController MediaPlayer Additions Reference
So if you replace that by say presentMoviePlayerViewControllerAnimated:self.moviePlayerVC, it should work as expected.
I'm not sure I understand your question, but if you need to wrap your controller to some UINavigationController you can do it like this:
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:myController];
navController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
navController.navigationBar.barStyle = UIBarStyleBlack;
[self presentViewController:navController animated:YES completion:^{
//
}];
later on any child controller will have the navigation hierarchy.

Resources