Well, I have a TableView in a RootViewController with a DetailViewController for the display of the information of the single record.
In the Detail page i have to play a multimedia file and i'm using the framework MediaPlayer, according to this guide:
http://www.techotopia.com/index.php/Video_Playback_from_within_an_iOS_4_iPhone_Application
it seems all ok, but when i click on the play button i have this error:
-[DetailsViewController playmovie]: unrecognized selector sent to instance 0x9117f60
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[DetailsViewController playmovie]: unrecognized selector sent to instance 0x9117f60'
These are my files:
In the AppDelegate I use this navigation controller:
[...]
// Create a table view controller
RootViewController *rootViewController = [[RootViewController alloc]
initWithStyle:UITableViewStylePlain];
rootViewController.managedObjectContext = context;
rootViewController.entityName = #"Porti";
UINavigationController *aNavigationController = [[UINavigationController alloc]
initWithRootViewController:rootViewController];
self.navigationController = aNavigationController;
UIBarButtonItem *homeButton;
homeButton = [[[UIBarButtonItem alloc] initWithTitle:#" Inizio " style:UIBarButtonItemStyleBordered target:self action:#selector(home)] autorelease];
UIBarButtonItem *barButton;
barButton = [[[UIBarButtonItem alloc] initWithTitle:#" Mappa dei porti " style:UIBarButtonItemStyleBordered target:self action:#selector(caricamappa)] autorelease];
[toolbar setItems:[NSArray arrayWithObjects: homeButton, barButton, nil]];
[window addSubview:[navigationController view]];
[window addSubview:toolbar];
[window makeKeyAndVisible];
[rootViewController release];
[aNavigationController release];
and in the RootViewController I use this instruction to pass to the DetailViewController:
//Push the new table view on the stack
[self.navigationController pushViewController:detailsView animated:YES];
[detailsView release];
DetailsViewController.h
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>
#import "MLUtils.h"
#import <MediaPlayer/MediaPlayer.h>
#interface DetailsViewController : UIViewController {
IBOutlet UILabel *titleLabel;
IBOutlet UILabel *descriptionLabel;
IBOutlet UIScrollView *descriptionScrollView;
NSString *cityName;
NSString *nomefile;
NSString *extfile;
NSString *description;
}
#property (nonatomic, retain) UILabel *titleLabel;
#property (nonatomic, retain) UILabel *descriptionLabel;
#property (nonatomic, retain) UIScrollView *descriptionScrollView;
#property (nonatomic, retain) NSString *cityName;
#property (nonatomic, retain) NSString *description;
#property (nonatomic, retain) NSString *nomefile;
#property (nonatomic, retain) NSString *extfile;
- (IBAction)playmovie:(id)sender;
#end
and this is the DetailsViewController.m
#import "DetailsViewController.h"
#implementation DetailsViewController
#synthesize titleLabel, descriptionLabel, descriptionScrollView;
#synthesize cityName,description,nomefile, extfile;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
[self.titleLabel setText:self.title];
[self.descriptionLabel setText:self.description];
float textHeight = [MLUtils calculateHeightOfTextFromWidth:self.description : descriptionLabel.font :descriptionLabel.frame.size.width :UILineBreakModeWordWrap];
CGRect frame = descriptionLabel.frame;
frame.size.height = textHeight;
descriptionLabel.frame = frame;
CGSize contentSize = descriptionScrollView.contentSize;
contentSize.height = textHeight;
descriptionScrollView.contentSize = contentSize;
}
-(void)playmovie:(id)sender
{
NSString *appNomeFile = self.nomefile;
NSString *appExtFile = self.extfile;
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:appNomeFile ofType:appExtFile]];
MPMoviePlayerController *moviePlayer =
[[MPMoviePlayerController alloc] initWithContentURL:url];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayer];
moviePlayer.controlStyle = MPMovieControlStyleDefault;
moviePlayer.shouldAutoplay = YES;
[self.view addSubview:moviePlayer.view];
[moviePlayer setFullscreen:YES animated:YES];
}
- (void) moviePlayBackDidFinish:(NSNotification*)notification {
MPMoviePlayerController *moviePlayer = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayer];
if ([moviePlayer
respondsToSelector:#selector(setFullscreen:animated:)])
{
[moviePlayer.view removeFromSuperview];
}
[moviePlayer release];
}
- (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 {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
//return (interfaceOrientation == UIInterfaceOrientationPortrait);
return YES;
}
- (void)dealloc {
[titleLabel release];
[descriptionLabel release];[descriptionScrollView release];
[cityName release];
[description release];
[nomefile release];
[extfile release];
[super dealloc];
}
#end
My question is: where is my error ? I imagine it is in the call of the playmovie method, but I can't figure out a solution!
P.S.
I've accidentally erased a comment, I'm so sorry! =(
You seem to call playmovie on a class and not on an object, or you forget to give the param. If you show us where you call it, that could help.
Anyway, the problem is that you probably do :
[DetailsViewController playmovie];
or
[oneDetailsViewController playmovie];
instead of :
[oneDetailsViewController playmovie:nil];
Here oneDetailsViewController is a DetailsViewController* object.
EDIT
Delete your XIB link, save, and make your link again to the IBAction by dragging (right-click) from the button to the file's owner.
Related
I created a NavigationBar and added it to the UIViewController. But after init, the reference turns to nil. I'm new to iOS and OC, I don't know why. Anyone can help? Thank you.
code summary:
#interface ContainerViewController()
#property (nonatomic, retain) UINavigationBar *nav;
#property (nonatomic, retain) UINavigationItem *navItem;
#end
#implementation ContainerViewController
- (instancetype) initWithParams:(NSDictionary *)params {
self = [super init];
if (self) {//...}
return self;
}
- setNavTitle:(NSDictionary *) params {
NSString *title = params[#"title"];
/////////////////////////////////
// here goes wrong
// self.navItem == nil here, why?
/////////////////////////////////
self.navItem.title = title;
}
- (void) viewWillAppear:(Bool)animated {
[super viewWillAppear:NO];
static float navHeight = 64.0;
UIViewController *wvController = [WebView init here];
UINavigationBar *nav = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), navHeight)];
UINavigationItem *navItem = [[UINavigationItem alloc] initWithTitle:title];
nav.items = [NSArray arrayWithObjects: navItem, nil];
///////////////////////////////
// I saved the reference here
//////////////////////////////
[self setNav:nav];
[self setNavItem:navItem];
[self.view addSubview:nav];
[self addChildViewController:wvController];
wvController.view.bounds = CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds) - navHeight);
[self.view addSubview:wvController.view];
[wvController didMoveToParentViewController:self];
}
#end
This will be useful for you, kindly check and do
Tutorial point site is very easy to learn some important UI basics if you are working in Objective C
This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 8 years ago.
What I have is menu at the top (vertical slider). On the top I have button, on clicking this button, the view will get scroll down and display the menu.
For this what I am doing is creating a view and showing it at top.
Now when I click on the button, I am planning to change the frame of top view with animation.
I am able to handle the frame and animation, however problem I am facing is setting the text to the right label and left button.
Below is the dropbox link to download the sample project. Any idea/ solution will be appreciated.
https://www.dropbox.com/s/pdaelw2k8ljnaki/TwoView.zip
What I tried is below code
CommonViewController *newClass = [[CommonViewController alloc] init];
newClass.parentObject = self;
NSLog(#"text is %#", newClass.rightSideLabel.text);
newClass.rightSideLabel.text = #"NEW VALUE HERE";
However still on the right side I see products only.
Full Code
CommonViewController.h
#import <UIKit/UIKit.h>
#interface CommonViewController : UIViewController
#property (retain, nonatomic) IBOutlet UIView *topView;
#property (retain, nonatomic) IBOutlet UILabel *rightSideLabel;
#property (retain, nonatomic) IBOutlet UIButton *leftSideButton;
#property (retain, nonatomic) IBOutlet UIButton *middleButton;
#property (retain, nonatomic) IBOutlet UIImageView *topImageView;
#property (nonatomic, assign) CommonViewController *parentObject;
#end
CommonViewController.m
#import "CommonViewController.h"
#interface CommonViewController ()
#end
#implementation CommonViewController
#synthesize topView, rightSideLabel, leftSideButton, middleButton, topImageView, parentObject;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
topView = [[UIView alloc] initWithFrame:CGRectMake(0, -416, 320, 460)];
topImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
topImageView.image = [UIImage imageNamed:#"top_bar_bg4.png"];
middleButton = [UIButton buttonWithType:UIButtonTypeCustom];
[middleButton setFrame:CGRectMake(120, topView.frame.size.height-44, 80, 44)];
[middleButton setBackgroundImage:[UIImage imageNamed:#"slide_arrow_open.png"] forState:UIControlStateNormal];
leftSideButton = [UIButton buttonWithType:UIButtonTypeCustom];
[leftSideButton setFrame:CGRectMake(0, topView.frame.size.height-44, 80, 44)];
[leftSideButton setTitle:#"BACK" forState:UIControlStateNormal];
[leftSideButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
rightSideLabel = [[UILabel alloc] initWithFrame:CGRectMake(200, topView.frame.size.height-40, 110, 40)];
rightSideLabel.text = #"PRODUCTS";
rightSideLabel.textColor = [UIColor whiteColor];
rightSideLabel.backgroundColor = [UIColor clearColor];
[topView addSubview:topImageView];
[topView addSubview:middleButton];
[topView addSubview:leftSideButton];
[topView addSubview:rightSideLabel];
[self.view addSubview:topView];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
bViewController.h
#import <UIKit/UIKit.h>
#import "CommonViewController.h"
#interface bViewController : CommonViewController
#end
bViewController.m
#import "bViewController.h"
#interface bViewController ()
#end
#implementation bViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = [UIColor lightGrayColor];
CommonViewController *newClass = [[CommonViewController alloc] init];
newClass.parentObject = self;
NSLog(#"text is %#", newClass.rightSideLabel.text);
newClass.rightSideLabel.text = #"NEW VALUE HERE";
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
What I want to do is keep common things in CommonViewController
Below is what I did...
In bViewController.m, I added below.
[[NSUserDefaults standardUserDefaults] setValue:#"New Value Here" forKey:#"notValue"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[NSNotificationCenter defaultCenter] postNotificationName:#"ChangeRightSideLabel" object:self];
And in CommonViewController.m, viewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receiveTestNotification:) name:#"ChangeRightSideLabel" object:nil];
- (void) receiveTestNotification:(NSNotification *) notification
{
// [notification name] should always be #"TestNotification"
// unless you use this method for observation of other notifications
// as well.
if ([[notification name] isEqualToString:#"ChangeRightSideLabel"]) {
NSLog (#"Successfully received the test notification!");
trightSideLabel = [[NSUserDefaults standardUserDefaults] valueForKey:#"notValue"];
rightSideLabel.text = trightSideLabel;
}
}
You have to respect MVC design Pattern approach. So instead of "newClass.rightSideLabel.text = #"NEW VALUE HERE";" You have to write :
in NewClass.h:
-#property(strong,nonatomic) stringText;
in NewClass.m:(ViewDidLoad Method)
-rightSideLabel.text=stringText;
in the current class:
-newClass.stringText= #"NEW Value HERE";
You need to make a string property for CommonViewController and assign the text to it.
And in CommonViewController's ViewDidLoad set that text to rightSideLabel.
In my project using Side menu. It is ready template from gitHub , but the problem is that somtimes searchDisplay controller is work and some times give error , What is actual Problem i am not understad... please help me
side menu template contain this files:
1)JWSlideMenuController
2)JWNavigationController
3)JWSlideMenuViewController
Here the throw error
2013-12-22 13:24:22.671 MyProject[3747:13d03] -[JWNavigationController isNavigationBarHidden]: unrecognized selector sent to instance 0x80c4e60
2013-12-22 13:24:22.681 MyProject[3747:13d03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[JWNavigationController isNavigationBarHidden]: unrecognized selector sent to instance 0x80c4e60'
*** First throw call stack:
(0x1979012 0x1295e7e 0x1a044bd 0x1968bbc 0x196894e 0x4bf326 0x4c0e41 0x410ae4 0x12a9705 0x1dd213 0x29ec7e 0x29e310 0x2aaa31 0x2b3f5f 0x2a21e9 0x2e7d95 0x4ab3c3 0x4ad442 0x4a485a 0x4a399b 0x4a50df 0x4a7d2d 0x4a7cac 0x49fa28 0x20c972 0x20ce53 0x1ead4a 0x1dc698 0x18d4df9 0x18d4ad0 0x18eebf5 0x18ee962 0x191fbb6 0x191ef44 0x191ee1b 0x18d37e3 0x18d3668 0x1d9ffc 0x5da2 0x1f65)
libc++abi.dylib: terminate called throwing an exception
Here is code for JWNavigationController.h and .m file
JWNavigationController.h
#import <UIKit/UIKit.h>
#class JWSlideMenuController;
#interface JWNavigationController : UIViewController <UINavigationBarDelegate>
#property (nonatomic, retain) UINavigationBar *navigationBar;
#property (nonatomic, retain) UIView *contentView;
#property (nonatomic, retain) JWSlideMenuController *slideMenuController;
#property (nonatomic, retain, readonly) UIViewController *rootViewController;
- (id)initWithRootViewController:(UIViewController *)rootViewController;
- (void)pushViewController:(UIViewController *)controller;
- (UIViewController *)popViewController;
#end
JWNavigationController.m file
JWNavigationController.m
// JWNavigationController.m
// JWSlideMenu
//
// Created by Jeremie Weldin on 11/22/11.
// Copyright (c) 2011 Jeremie Weldin. All rights reserved.
//
#import "JWNavigationController.h"
#import "JWSlideMenuViewController.h"
#interface JWNavigationController(Private)
-(UIViewController*)removeTopViewController;
#end
#implementation JWNavigationController
#synthesize navigationBar;
#synthesize contentView;
#synthesize slideMenuController;
#synthesize rootViewController=_rootViewController;
#pragma mark - View lifecycle
- (id)init
{
self = [super init];
if (self) {
CGRect masterRect = [[UIScreen mainScreen] bounds];
CGRect contentFrame = CGRectMake(0.0, 44.0, masterRect.size.width, masterRect.size.height - 44.0);
CGRect navBarFrame = CGRectMake(0.0, 0.0, masterRect.size.width, 44.0);
self.view = [[[UIView alloc] initWithFrame:masterRect] autorelease];
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth;
self.view.backgroundColor = [UIColor whiteColor];
self.contentView = [[[UIView alloc] initWithFrame:contentFrame] autorelease];
self.contentView.backgroundColor = [UIColor whiteColor];
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[self.view addSubview:self.contentView];
self.navigationBar = [[[UINavigationBar alloc] initWithFrame:navBarFrame] autorelease];
self.navigationBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
self.navigationBar.delegate = self;
[self.view insertSubview:self.navigationBar aboveSubview:self.contentView];
self.navigationBar.backgroundColor=[UIColor whiteColor];
}
return self;
}
- (id)initWithRootViewController:(JWSlideMenuViewController *)rootViewController
{
self = [self init];
if(self) {
_rootViewController = rootViewController;
UIBarButtonItem *menuButton = [[[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"menu_icon_20x20.png"] style:UIBarButtonItemStyleBordered target:self.slideMenuController action:#selector(toggleMenu)] autorelease];
rootViewController.navigationItem.leftBarButtonItem = menuButton;
[self addChildViewController:rootViewController];
[self.contentView addSubview:rootViewController.view];
[self.navigationBar pushNavigationItem:rootViewController.navigationItem animated:YES];
rootViewController.navigationController = self;
}
return self;
}
#pragma mark - UINavigationBarDelegate
- (void)navigationBar:(UINavigationBar *)navigationBar didPopItem:(UINavigationItem *)item
{
UIViewController *controller = [self.childViewControllers lastObject];
if (item==controller.navigationItem) //Will now called only if a back button pop happens, not in manual pops
{
[self removeTopViewController];
}
}
- (void)navigationBar:(UINavigationBar *)navigationBar didPushItem:(UINavigationItem *)item
{
}
#pragma mark - Stack Interaction
- (void)pushViewController:(JWSlideMenuViewController *)controller
{
[self addChildViewController:controller];
[self.navigationBar pushNavigationItem:controller.navigationItem animated:YES];
controller.navigationController = self;
controller.view.frame = self.contentView.bounds;
if([self.childViewControllers count] == 1)
{
[self.contentView addSubview:controller.view];
}
else
{
UIViewController *previousController = [self.childViewControllers objectAtIndex:[self.childViewControllers count]-2];
[self transitionFromViewController:previousController toViewController:controller duration:0.5 options:UIViewAnimationOptionTransitionNone animations:NULL completion:NULL];
}
}
- (UIViewController *)popViewController
{
//Can use this to pop manually rather than back button alone
UIViewController *controller = [self.childViewControllers lastObject];
UIViewController *previousController = nil;
if([self.childViewControllers count] > 1)
{
previousController = [self.childViewControllers objectAtIndex:[self.childViewControllers count]-2];
previousController.view.frame = self.contentView.bounds;
}
[self transitionFromViewController:controller toViewController:previousController duration:0.3 options:UIViewAnimationOptionTransitionNone animations:NULL completion:NULL];
[controller removeFromParentViewController];
if(self.navigationBar.items.count > self.childViewControllers.count)
[self.navigationBar popNavigationItemAnimated:YES];
return controller;
}
- (void)viewDidUnload
{
_rootViewController = nil;
self.navigationBar = nil;
self.contentView = nil;
self.slideMenuController = nil;
[super viewDidUnload];
}
- (void)dealloc {
[_rootViewController release];
[navigationBar release];
[contentView release];
[super dealloc];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
-(UIViewController*)removeTopViewController
{
UIViewController *controller = [self.childViewControllers lastObject];
UIViewController *previousController = nil;
if([self.childViewControllers count] > 1)
{
previousController = [self.childViewControllers objectAtIndex:[self.childViewControllers count]-2];
previousController.view.frame = self.contentView.bounds;
}
[self transitionFromViewController:controller toViewController:previousController duration:0.3 options:UIViewAnimationOptionTransitionNone animations:NULL completion:NULL];
[controller removeFromParentViewController];
return controller;
}
#end
If hide this code from JWNavigationController.m so searchDisplayController is working
rootViewController.navigationController = self;
but new problem is UITableVIew didselectrowatindexpath is notworking .. what can i do?
isNavigationBarHidden: is a selector which is only available in classes that derive from UINavigationController. You have to modify this line:
#interface JWNavigationController : UIViewController
with this:
#interface JWNavigationController : UINavigationController
Your JWNavigationController does not inherit from UINavigationController.
But, isNavigationBarHidden is a method implemented by UINavigationController.
Now look at the error (which uses the term 'selector', but that refers to the method): It basically says that the instance of your JWNavigationController does not implement isNavigationBarHidden, and this is the issue.
Could it be that you mistyped, and meant to write:
#interface JWNavigationController : UINavigationController <UINavigationBarDelegate>
I am trying to apply UITapGestureRecognizer on a UILabel in order to check and open e-mail service. The current UIView is a part of a UIViewController and displayed once user tap on a button.
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>
#class AddressBook;
#interface ContactInfoUI : UIView <MFMailComposeViewControllerDelegate, UIGestureRecognizerDelegate>{
IBOutlet UIView *view;
UIViewController *mContainerVc;
AddressBook *mAddressBook;
}
#property (nonatomic, retain)UIView *view;
#property (nonatomic, retain)UIViewController *mContainerVc;
#property (nonatomic, retain)AddressBook *mAddressBook;
-(void)addContactInformationFrom:(AddressBook *)addressBook;
#end
.m
#implementation ContactInfoUI
#synthesize view;
#synthesize mContainerVc;
#synthesize mAddressBook;
- (id)init {
self = [super init];
if (self) {
[[NSBundle mainBundle] loadNibNamed:#"ContactInfoView" owner:self options:nil];
self.userInteractionEnabled = YES;
[self addSubview:[self view]];
}
return self;
}
-(void)addContactInformationFrom:(AddressBook *)addressBook{
self.mAddressBook = addressBook;
int y = 20;
CGRect rect = CGRectMake(20, y, 320, 60);
if (![mAddressBook.aEmail isEqualToString:#"-"]) {
UILabel *email = [[UILabel alloc] initWithFrame:rect];
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(showEmailForm:)];
tgr.delegate = self;
tgr.numberOfTapsRequired = 1;
[email addGestureRecognizer:tgr];
email.userInteractionEnabled = YES;
email.text = mAddressBook.aEmail;
[self addSubview:email];
rect.origin.y += 40;
}
}
-(IBAction)showEmailForm:(id)sender{
// Email Subject
NSString *emailTitle = #"Test Email";
// Email Content
NSString *messageBody = #"Some message";
// To address
NSArray *toRecipents = [NSArray arrayWithObject:#"test#apple.com"];
MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
mc.mailComposeDelegate = self;
[mc setSubject:emailTitle];
[mc setMessageBody:messageBody isHTML:NO];
[mc setToRecipients:toRecipents];
[mContainerVc presentViewController:mc animated:YES completion:NULL];
}
#end
VC.h (part)
#class ContactInfoUI;
#class ElementObject;
#interface ElementDetailsViewController : UIViewController{
ElementObject *element;
IBOutlet ContactInfoUI *infoView;
}
#property(nonatomic, retain) ContactInfoUI *infoView;
- (IBAction)showInfo:(id)sender;
#end
VC.m (part)
- (IBAction)showInfo:(id)sender {
if (infoView == nil) {
infoView = [[ContactInfoUI alloc] init];
infoView.userInteractionEnabled = YES;
infoView.mContainerVc = self;
}
AddressBook *ab = element.getElementAddressBook;
[infoView addContactInformationFrom:ab];
[self.view addSubview:infoView];
infoBtn.selected = YES;
sumBtn.selected = NO;
mapBtn.selected = NO;
infoView.hidden = NO;
staticMapScrView.hidden = YES;
summaryView.hidden = YES;
}
The problem is that, even if I can see the actual UILabel on screen, I can't tap on it and the email function never fired.
I'm glad you figured it. Yeah, if a UI element is smaller than any of the its superviews (all the way up the chain), all UI interaction to that element will be blocked. This goes for labels, buttons, etc..
I'm very new to iOS programming (Coming from Java / C++). I'm trying to set up an app with a TabBarController of which one tab should be a SplitView. I've done my research and I know that UISplitview will not work and everywhere people recommend using the MGSplitViewController. I've looked at the demo but I just can't figure out how to use it without it beeing the app's root view and can't find any sample code that could help
So here is what I do with the classes from the demo in a separate UIViewController class that I afterwards add to the TabBarController: This is my class:
#import <UIKit/UIKit.h>
#import "MGSplitCornersView.h"
#import "RootViewController.h"
#import "DetailViewController.h"
#interface ChannelViewController : UIViewController {
MGSplitViewController *splitViewController;
RootViewController *rootViewController;
DetailViewController *detailViewController;
}
#property (nonatomic, retain) MGSplitViewController *splitViewController;
#property (nonatomic, retain) RootViewController *rootViewController;
#property (nonatomic, retain) DetailViewController *detailViewController;
#end
And this is my desperate try to set it up
- (id)initWithTabBar
{
self = [super init];
//this is the label on the tab button itself
self.title = #"SplitView";
//use whatever image you want and add it to your project
//self.tabBarItem.image = [UIImage imageNamed:#"name_gray.png"];
// set the long name shown in the navigation bar at the top
self.navigationItem.title=#"Nav Title";
self.splitViewController = [[MGSplitViewController alloc] init];
self.rootViewController = [[RootViewController alloc] init];
self.detailViewController = [[DetailViewController alloc] init];
[self.splitViewController setDetailViewController:detailViewController];
[self.splitViewController setMasterViewController:rootViewController];
[self.view addSubview:splitViewController.view];
[self.rootViewController performSelector:#selector(selectFirstRow) withObject:nil afterDelay:0];
[self.detailViewController performSelector:#selector(configureView) withObject:nil afterDelay:0];
if (NO) { // whether to allow dragging the divider to move the split.
splitViewController.splitWidth = 15.0; // make it wide enough to actually drag!
splitViewController.allowsDraggingDivider = YES;
}
return self;
}
I guess I'm doing something wrong with delegates? Or do I have something else mixed up?
Is the demo doing things in the IB that I can't see in the code?
I get the split view but no content and especially no navigation bar with the buttons the demo comes with.
I'd be very thankful for hints or sample code!
Ok manny, here we go. This is my working code for the interface:
#import <UIKit/UIKit.h>
#import "MGSplitViewController.h"
#import "ecbView.h"
#import "ecbCalc.h"
#interface splitMain : MGSplitViewController <UIPopoverControllerDelegate,
MGSplitViewControllerDelegate>
{
IBOutlet UIPopoverController* popoverController;
IBOutlet UINavigationController* naviController;
IBOutlet ecbCalc* viewCalcLeft;
IBOutlet ecbView* euroRatesRight;
UIBarButtonItem* savedButtonItem;
BOOL keepMasterInPortraitMode;
BOOL memoryWasDropped;
BOOL viewLoaded;
}
#property (nonatomic, retain) UIPopoverController* popoverController;
#property (nonatomic, retain) UINavigationController* naviController;
#property (nonatomic, retain) ecbCalc* viewCalcLeft;
#property (nonatomic, retain) ecbView* euroRatesRight;
#property (nonatomic, retain) UIBarButtonItem* savedButtonItem;
#property (nonatomic, readonly) BOOL keepMasterInPortraitMode;
#property (nonatomic, readonly) BOOL memoryWasDropped;
#property (nonatomic, readonly) BOOL viewLoaded;
- (void)dismissPopoverController: (BOOL)animated;
- (void)settingsChanged;
#end
and here excerpts from implementation file:
- (id)initWithCoder:(NSCoder *)aDecoder
{
if ((self = [super initWithCoder:aDecoder]))
{
// my initialization...
}
return self;
}
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView
{
CGRect rectFrame = CGRectMake(0.0, 20.0, 768.0, 1004.0 - 48.0); // being above a tab bar!
viewLoaded = NO;
self.view = [[UIView alloc] initWithFrame:rectFrame];
viewCalcLeft = [[ecbCalc alloc] initWithNibName:#"ecbCalc" bundle:nil];
euroRatesRight = [[ecbView alloc] initWithNibName:#"ecbView-iPad" bundle:nil];
naviController = [[UINavigationController alloc] initWithRootViewController:self.viewCalcLeft];
naviController.navigationBar.barStyle = UIBarStyleBlack;
naviController.title = nil;
viewCalcLeft.title = NSLocalizedString(#"BtnTitleCalc", #"");
viewCalcLeft.view.hidden = NO;
NSUserDefaults* prefs = [NSUserDefaults standardUserDefaults];
if ([prefs objectForKey:#"iPadAlwaysSplitTableView"] != nil)
self.keepMasterInPortraitMode = [prefs boolForKey:#"iPadAlwaysSplitTableView"];
else
self.keepMasterInPortraitMode = YES;
NSArray* theViewControllers = [NSArray arrayWithObjects:self.naviController, self.euroRatesRight, nil];
[self setViewControllers:theViewControllers];
[self setDelegate:self];
[self setShowsMasterInPortrait:keepMasterInPortraitMode];
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
// protection because this one is called twice
if (viewLoaded)
return;
[super viewDidLoad];
if (memoryWasDropped)
{
if (!self.keepMasterInPortraitMode && UIInterfaceOrientationIsPortrait(self.interfaceOrientation))
{
// recreate popover controller
self.popoverController = [[UIPopoverController alloc] initWithContentViewController:self.viewCalcLeft];
}
}
viewLoaded = YES;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
memoryWasDropped = YES;
// Release any cached data, images, etc. that aren't in use.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
[self dismissPopoverController:NO];
self.popoverController = nil;
self.naviController = nil;
self.viewCalcLeft = nil;
self.euroRatesRight = nil;
viewLoaded = NO;
}
My MainWindow.xib has a UITabBarController and the button for splitMain is configured for this class but with an empty xib entry. So creation has to go via loadView. Maybe I could have done the viewDidLoad stuff within loadView ... but so I had to protect viewDidLoad from being called twice. That happens in loadView as soon as the view is instantiated from MGSplitViewController class because the initWithCoder there is calling [self setup]. In that function the frame rect is calculated with self.view.bounds so that viewDidLoad is called again because the view doesn't exist yet. Maybe one could implement a workaround within MGSplitViewController.m but I was too lazy doing that.
To get this working on a tab bar controller please make sure you commit most of the changes that are published on the MGSplitViewController's git page. Good luck.