I am trying to pass an integer value between UIViewControllers, new to iOS and having problems.
In the UIViewController where the value is being set, there are no problems. But after the value is set NSLog is showing that the value is null in the second UIViewController.
My app is going to use the horizontal slider to determine the length of time in between a UIImage animationDuration in a different UIViewController.
This method is correctly receiving the value from the horizontal slider. I initialized an instance of the "other" UIViewController, imageview.somedata belongs to the other view controller. I know the value is being passed correctly because of the NSLogs below.
- (IBAction) changeButtonPressed:(id)sender {
imageView = [[GTImageView alloc] initWithNibName:#"GTImageView" bundle:nil];
NSLog(#"text value = %#", myTextField);
NSString *textValue = [myTextField text];
int value = [textValue floatValue];
if (value < 0) value = 0;
if (value > 100) value = 100;
mySlider.value = value;
sliderValue = &value;
NSLog(#"sliderValue = %d", *(sliderValue));
myTextField.text = [NSString stringWithFormat:#"%.1d", value];
if ([myTextField canResignFirstResponder]) [myTextField resignFirstResponder];
imageView.someData = *(sliderValue);
NSLog(#"imageView.someData = %d", imageView.someData);
}
This is the top of that implementation file
#import "GTSettingsVC.h"
#import "GTImageView.h"
#import "GTImageView.m"
#interface GTSettingsVC ()
#end
#implementation GTSettingsVC
#synthesize mySlider, myTextField;
#synthesize sliderValue;
That header file
#import "GTImageView.h"
#interface GTSettingsVC : UIViewController
{
IBOutlet UISlider *mySlider;
IBOutlet UITextField *myTextField;
GTImageView *imageView;
int *sliderValue;
}
#property (nonatomic) int *sliderValue;
The header file of the view controller I am trying to send the data to
#import <UIKit/UIKit.h>
#interface GTImageView : UIViewController
{
UIScrollView* scrollView;
UIPageControl* pageControl;
int *someData;
}
#property (nonatomic) int *someData;
The implementation file where I want the variable someData to have the value I gave it in the first controller. NSLog is returning null in this implementation.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
UIImageView *animatedImageView =
[[UIImageView alloc] i nitWithFrame:CGRectMake(0, 55, 400, 550)];
[self.view addSubview:animatedImageView];
animatedImageView.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"IMG_0052.JPG"],
[UIImage imageNamed:#"IMG_0054.JPG"],
[UIImage imageNamed:#"IMG_0081.JPG"],
nil];
NSLog(#"some data = %#", someData);
// NSLog is returning null
int x = someData;
animatedImageView.animationDuration =
x * [animatedImageView.animationImages count];
[animatedImageView startAnimating];
[self.view addSubview: animatedImageView];
}
I believe you have yet to grasp the concept/idea for View Controller Life Cycle and also Model View Controller (MVC).
The GTImageView that you defined and initiated in changeButtonPressed for your First View Controller (GTSettingsVC) is a local object/instance for GTSettingsVC. If your view controller transition from GTSettingsVC to GTImageView, the data will not pass to there.
Since you are using UINavigationController, I believe you have Segue. The easiest way to pass data for UINavigationController is using prepareForSegue. You will have to prepare the data that you want to pass to the second view controller in this method before the transition to it.
You also make some mistake in GTImageView. someData is not an object, it should not have *. And also try not to use variable, use just the property in stead. It should be:-
#property (nonatomic) int someData;
In GTSettingsVC.M, add the following function:-
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
GTImageView * viewController = segue.destinationViewController;
viewController.someData = 99;
}
In GTImageView.H
#interface GTImageView : UIViewController
{
UIScrollView* scrollView;
UIPageControl* pageControl;
}
#property (nonatomic) int someData;
#end
In viewDidLoad in GTImageView.M
- (void)viewDidLoad
{
[super viewDidLoad];
UIImageView *animatedImageView =
[[UIImageView alloc] initWithFrame:CGRectMake(0,55, 400, 550)];
[self.view addSubview:animatedImageView];
animatedImageView.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"IMG_0052.JPG"],
[UIImage imageNamed:#"IMG_0054.JPG"],
[UIImage imageNamed:#"IMG_0081.JPG"],
nil];
NSLog(#"some data = %d", self.someData);
int x = self.someData;
animatedImageView.animationDuration =
x * [animatedImageView.animationImages count];
[animatedImageView startAnimating];
[self.view addSubview: animatedImageView];
}
I added a sample project to Github for your reference:-
https://github.com/voyage11/PassingDataTest
There is no need to take int *. Replace it by int and assign the value directly rather than address.
Related
So I have this problem with using 2 UIPickerView controls in one ViewController. I am using the CountryPicker found here https://github.com/nicklockwood/CountryPicker to show a nice country picker so the user can select his or hers country, and the country code for his or hers phone number. I want to limit the number of countries in one of the pickers and show all countries in the other picker. But when I show the 2 pickers, it seems that the one which has CountryPicker type is actually using the overriden method -countriesOfOperation from the CustomCountryPicker class.
I have tried with the storyboard and then to programatically init the 2 pickers without success. As you can see I've tried to remove the first picker before showing the second one and vice versa, but it won't fix it.
What could be the reason that even that I am setting *countrySelectionPickerView to be CountryPicker, it still uses the overriden method from CustomCountryPicker? So the object is of type CountryPicker, but it still shows the short countries list.
CustomCountryPicker.h
#import <CountryPicker/CountryPicker.h>
#interface CustomCountryPicker : CountryPicker
/// Returns a dictionary of country names, keyed by country code.
+(NSDictionary<NSString *, NSString *> *)countryNamesByCode;
#end
CustomCountryPicker.m
#import "CustomCountryPicker.h"
#implementation CustomCountryPicker
-(instancetype)initWithFrame:(CGRect)frame
{
return [super initWithFrame:frame];
}
+(NSDictionary *)countriesOfOperation
{
NSDictionary *countries = #{ #"DK": #"Denmark",
#"DE": #"Germany",
#"GB": #"Great Britain",
#"FR": #"France",
#"NO": #"Norway",
#"CH": #"Switzerland"
};
return countries;
}
+(NSDictionary *)countryNamesByCode
{
NSDictionary *countries = [self countriesOfOperation];
static NSDictionary *_countryNamesByCode = nil;
if (!_countryNamesByCode)
{
NSMutableDictionary *namesByCode = [NSMutableDictionary dictionary];
for (NSString *code in [NSLocale ISOCountryCodes])
{
if([countries valueForKey:code]) {
NSString *countryName = [[NSLocale currentLocale] displayNameForKey:NSLocaleCountryCode value:code];
//workaround for simulator bug
if (!countryName)
{
countryName = [[NSLocale localeWithLocaleIdentifier:#"en_US"] displayNameForKey:NSLocaleCountryCode value:code];
}
countryName = [countryName stringByAppendingString:#" XXX"];
namesByCode[code] = countryName ?: code;
}
}
_countryNamesByCode = [namesByCode copy];
}
return _countryNamesByCode;
}
SomeViewController.h
#import <CountryPicker/CountryPicker.h>
...
SomeViewController.m
#import "CustomCountryPicker.h"
#interface SomeViewController () <CountryPickerDelegate>
#property (nonatomic, weak) IBOutlet UIView *countryPickerView;
#property (nonatomic, weak) IBOutlet UIView *customCountryPickerView;
#property (nonatomic, strong) CountryPicker *countrySelectionPickerView;
#property (nonatomic, strong) CustomCountryPicker *customCountrySelectionPickerView;
-(IBAction)countrySelection:(id)sender {
[[[UIApplication sharedApplication] keyWindow] endEditing:YES];
UIButton *senderButton = (UIButton *)sender;
if(senderButton.tag == 101) {
[UIView animateWithDuration:0.2 delay:0.0 options:0 animations:^{
self.countryPickerView.hidden = TRUE;
[self.countrySelectionPickerView removeFromSuperview];
[self.customCountrySelectionPickerView removeFromSuperview];
self.customCountrySelectionPickerView = [[CustomCountryPicker alloc] initWithFrame:CGRectMake(0, 44, 375, 216)];
self.customCountrySelectionPickerView.tag = 11;
self.customCountrySelectionPickerView.delegate = self;
[self.customCountryPickerView addSubview:self.customCountrySelectionPickerView];
self.customCountryPickerView.hidden = FALSE;
self.customCountryPickerView.frame = CGRectMake(0, SCREEN_HEIGHT - 260, SCREEN_WIDTH, 260);
} completion:nil];
// update user country
// select user country phone code
} else if(senderButton.tag == 102) {
[UIView animateWithDuration:0.2 delay:0.0 options:0 animations:^{
self.customCountryPickerView.hidden = TRUE;
[self.countrySelectionPickerView removeFromSuperview];
[self.customCountrySelectionPickerView removeFromSuperview];
self.countrySelectionPickerView = [[CountryPicker alloc] initWithFrame:CGRectMake(0, 44, 375, 216)];
self.countrySelectionPickerView.tag = 12;
self.countrySelectionPickerView.delegate = self;
[self.countryPickerView addSubview:self.countrySelectionPickerView];
self.countryPickerView.hidden = FALSE;
self.countryPickerView.frame = CGRectMake(0, SCREEN_HEIGHT - 260, SCREEN_WIDTH, 260);
} completion:nil];
}
This is because the library is using static variables so both your custom subclass and the original CountryPicker share the data. You can remove the static keyword from _countryNames, _countryCodes, _countryNamesByCode and _countryCodesByName and it should work.
when I click on button I get only 1 extra view, but I want a the view to be added dynamically on number of click, (like for loop)...Kindly help me with this code, Thanks in Advance,
this is just a part of my code
if (boolVal == true) {
CGRect newFrameC = CGRectMake(_centreView.frame.origin.x, _centreView.frame.origin.y, _centreView.frame.size.width, 50);
CGRect newFrameL1 = CGRectMake(_label2.frame.origin.x, _label2.frame.origin.y+50, _label2.frame.size.width, 50);
_centreView.frame = newFrameC;
_label2.frame = newFrameL1;
boolVal = false;
}else if (boolVal == false){
CGRect newFrameC = CGRectMake(_centreView.frame.origin.x, _centreView.frame.origin.y, _centreView.frame.size.width, 1);
CGRect newFrameL1 = CGRectMake(_label2.frame.origin.x, _label2.frame.origin.y-50, _label2.frame.size.width, 50);
_centreView.frame = newFrameC;
_label2.frame = newFrameL1;
boolVal = true;
}
DummyViewController.m
#import "DummyViewController.h"
#import "ExtraView.h"
#interface DummyViewController ()
#property (nonatomic) unsigned int numberOfExtraViews;
#property (nonatomic, strong) NSMutableArray<ExtraView*>* extraViews;
#property (nonatomic, strong) UILabel* label1;
#property (nonatomic, strong) UILabel* label2;
#end
#implementation DummyViewController
-(void) removeExtraViews{
for (ExtraView* extraView in _extraViews){
[extraView removeFromSuperview];
}
[_extraViews removeAllObjects];
}
-(CGRect) getExtraViewFrame{
CGRect extraViewFrame = _label1.frame;
if (_numberOfExtraViews > 0) {
extraViewFrame = [_extraViews lastObject].frame;
}
extraViewFrame.origin.x += extraViewFrame.size.height;
return extraViewFrame;
}
- (void) addExtraViews{
//[self removeExtraViews];
int numberOfExtraViewsToDraw = _numberOfExtraViews - _extraViews.count;
for (int iterator = 0; iterator < numberOfExtraViewsToDraw; iterator ++){
CGRect extraViewFrame = [self getExtraViewFrame];
ExtraView *extraView = [[ExtraView alloc]initWithFrame:extraViewFrame];
[self.view addSubview:extraView];
[_extraViews addObject:extraView];
}
if (numberOfExtraViewsToDraw > 0) {
CGRect label2Frame = [_extraViews lastObject].frame;
label2Frame.origin.x += label2Frame.size.height;
_label2.frame = label2Frame;
}
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self addExtraViews];
//rest of your code
}
//Use this code in initWithNib/initWithCoder. Don't copy paste the same
-(instancetype)init{
self = [super init];
if (nil != self){
_numberOfExtraViews = 0;
_extraViews = [[NSMutableArray alloc]init];
}
return self;
}
//the function that gets hit when the button is tapped.
- (void) onButtonTap{
_numberOfExtraViews++;
[self.view setNeedsDisplay];
}
Note the following:
I do not understand what the boolVal is, but if it keeps toggling upon the click of the button, you'll never have multiple views.I assumed it toggles, so I havent used it at all.
Use the init code in initWithNib/initWithCoder. Don't copy paste the same. Don't overwrite the given code. Just append to your current init.
In my code onButtonTap is the function that gets hit when the button is tapped.
I've done it by ensuring viewDidLoad method gets hit agin. But I dont think it's necessary. You can also do this:
//the function that gets hit when the button is tapped.
- (void) onButtonTap{
_numberOfExtraViews++;
[self addExtraViews];
}
What has been done:
Let me call what you call as centerView as extraView. There will be many extraViews, so I'll create an array for the same (extraViews).
The count of the number of views is stored in numberOfExtraViews. Initiated to 0 in init.
Whenever the button is tapped, we increase the count and call view's setNeedsDisplay, which in turn hits the viewDidLoad method
In viewDidLoad, we add the extraViews.
I'm using a contact picker to grab a string, then pass that string to another view controller, however the UILabel is not updating with the data (or any other string).
In the SlingViewController.m logs below, _taggedFriendsNames is being passed successfully.
Perhaps the issue is because the receiving view controller is trying to update the label on another (SlingshotView) view? I don't think that's the case as I've been updating labels in this way in other methods.
The answer is likely related to updating UILabels in general, but I've had no luck after searching.
Things I've checked with no success:
Updating from the main thread asynchronously
#synthesize the label in SlingshotView
calling setDisplay
Included potentially relevant code below. Thanks in advance for any tips!
SlingViewController.m
-(void)updateFriendsPickedLabel:(id)sender {
NSLog(#"updateFriendsPickedLabel: %#", _taggedFriendsNames); // i see this
slingshotView.friendsPickedLabel.text = #"any string"; // i don't see this
}
SlingViewController.h
#class TBMultiselectController;
#class SlingshotView;
#interface SlingViewController : UIViewController
#property (nonatomic, readonly) SlingshotView *slingshotView;
#property(nonatomic) NSString *taggedFriendsNames;
//for friend picker
-(void)updateFriendsPickedLabel:(id)sender;
#end
MultiSelectViewController.m
- (IBAction) sendButton: (id) sender {
NSMutableString *myString = [[NSMutableString alloc]initWithString:#""];
for (int i=0; i < self.selectedContacts.count; i++) {
Contact *myContact = self.selectedContacts[i];
[myString appendString:[NSString stringWithFormat:#"%# %# ", myContact.firstName, myContact.lastName]];
}
SlingViewController *svc = [[SlingViewController alloc] init];
svc.taggedFriendsNames = myString;
[svc updateFriendsPickedLabel:self];
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
MultiSelectViewController.h
#protocol TBMultiselectControllerDelegate;
#class SlingViewController;
#interface TBMultiselectController : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchDisplayDelegate, TBContactsGrabberDelegate>
#property (nonatomic, assign) id<TBMultiselectControllerDelegate> delegate;
- (IBAction)sendButton: (id) sender;
#end
#protocol TBMultiselectControllerDelegate <NSObject>
-(void)updateFriendsPickedLabel:(id)sender;
#end
SlingshotView.h
#property (strong, nonatomic) UILabel *friendsPickedLabel;
SlingshotView.m
#synthesize friendsPickedLabel;
...
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGRect imageFrame = CGRectMake(0, 0, screenRect.size.width, screenRect.size.height);
contentView = [[UIView alloc] initWithFrame:frame];
[contentView setBackgroundColor:[UIColor whiteColor]];
[contentView setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
[self addSubview:contentView];
self.friendsPickedLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, screenRect.size.height/2-100, screenRect.size.width-20, 200)];
self.friendsPickedLabel.shadowColor = [UIColor darkGrayColor];
self.friendsPickedLabel.numberOfLines = 0;
self.friendsPickedLabel.shadowOffset = CGSizeMake(0.5, 0.5);
self.friendsPickedLabel.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0];
[self.friendsPickedLabel setTextAlignment:NSTextAlignmentLeft];
self.friendsPickedLabel.textColor = [UIColor whiteColor];
self.friendsPickedLabel.font = [UIFont fontWithName:#"HelveticaNeue-Bold" size:24];
[contentView addSubview:self.friendsPickedLabel];
You are reallocating this..
SlingViewController *svc = [[SlingViewController alloc] init];
svc.taggedFriendsNames = myString;
[svc updateFriendsPickedLabel:self];
Meaning your
slingshotView.friendsPickedLabel becomes nil..
And you are calling/using the delegate the wrong way, i think it suppose to be
[self.delegate updateFriendsPickedLabel:#"YourData To be Passed"];
From your code you are using the -(void)updateFriendsPickedLabel:(id)sender; inside SlingViewController and not the delegate, you are not implementing the delegate either..
Yes the -(void)updateFriendsPickedLabel:(id)sender; method is called, bacause you are calling it directly from the class..
SlingViewController.h
#interface SlingViewController : UIViewController < TBMultiselectControllerDelegate > // for delegate implementation
#property (nonatomic, readonly) SlingshotView *slingshotView;
#property(nonatomic) NSString *taggedFriendsNames;
//for friend picker
//-(void)updateFriendsPickedLabel:(id)sender;
#end
MultiSelectViewController.m
- (IBAction) sendButton: (id) sender {
NSMutableString *myString = [[NSMutableString alloc]initWithString:#""];
for (int i=0; i < self.selectedContacts.count; i++) {
Contact *myContact = self.selectedContacts[i];
[myString appendString:[NSString stringWithFormat:#"%# %# ", myContact.firstName, myContact.lastName]];
}
/*
SlingViewController *svc = [[SlingViewController alloc] init];
svc.taggedFriendsNames = myString;
[svc updateFriendsPickedLabel:self];
*/
[self.delegate updateFriendsPickedLabel:#"YourString"];
// this will call the method in your implementation class
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
Hmm.. I Think you have implemented the delegates the wrong way.
This is suppose to be a comment but its too long..
The style should be like iBooks or pictures in foursquare. When we flip to the left we see the next picture being pulled. How to do so? Is there a code to do so? I think there must have been a ready code for that
It sounds like you want UIPageViewController.
Try this. One solution. Revise as needed.
Create a new project of type Single View Application, name it BookEffect, uncheck Use Storyboards, uncheck Include Unit Tests, but be sure to check the option Use Automatic Reference Counting.
Then add to the project a few pictures, for example, in JPEG format.
Create a new file - use the Objective-C Class template with a subclass of UIViewController, select the option With XIB for user interface, and name it SinglePageViewController. Save the file inside the BookEffect folder.
Once added, select the SinglePageViewController.xib and add to the view a UILabel control and UIImageView control and make the appropriate connections to the File's Owner.
Revise the SinglePageViewController.h to look like this:
#import <UIKit/UIKit.h>
#interface SinglePageViewController : UIViewController
{
NSUInteger pageNumber;
}
#property (strong, nonatomic) IBOutlet UILabel *titleLabel;
#property (strong, nonatomic) IBOutlet UIImageView *imageView;
#property (nonatomic, assign) NSUInteger pageNumber;
- (void) setPageNumber: (NSUInteger) newPageNumber;
- (NSUInteger) pageNumber;
#end
In SinglePageViewController.m add:
#synthesize imageView, titleLabel;
and add these definitions of methods:
- (void) setPageNumber: (NSUInteger) newPageNumber{
pageNumber = newPageNumber;
}
- (NSUInteger) pageNumber{
return pageNumber;
}
- (void) viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
[titleLabel setText:[NSString stringWithFormat:#"Page %d", pageNumber]];
NSArray *images = [[NSBundle mainBundle] pathsForResourcesOfType:#".jpg" inDirectory:nil];
UIImage *img = [UIImage imageWithContentsOfFile:[images objectAtIndex:pageNumber-1]];
[imageView setImage:img];
}
Now go to the BookEffecViewController.h, and make it look like this:
#import <UIKit/UIKit.h>
#import "SinglePageViewController.h"
#interface BookEffectViewController : UIViewController
<UIPageViewControllerDataSource>
#property( nonatomic, strong) UIPageViewController *pageViewController;
#end
In BookEffectViewController.m revise viewDidLoad to look like this:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
self.pageViewController.dataSource = self;
SinglePageViewController *singlePage = [[SinglePageViewController alloc] initWithNibName:#"SinglePageViewController" bundle:nil];
[singlePage setPageNumber:1];
NSArray *controllers = [[NSArray alloc] initWithObjects:singlePage, nil];
[self.pageViewController setViewControllers:controllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
self.pageViewController.view.frame = self.view.bounds;
}
Define two more methods in BookEffectViewController.m:
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
NSUInteger previousPageNumber = [((SinglePageViewController*)viewController) pageNumber];
if ( previousPageNumber == 1 ) {
return nil;
}
else{
SinglePageViewController *singlePage = [[SinglePageViewController alloc] initWithNibName:#"SinglePageViewController" bundle:nil];
[singlePage setPageNumber:previousPageNumber-1];
return singlePage;
}
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
NSUInteger previousPageNumber = [((SinglePageViewController*)viewController) pageNumber];
if ( previousPageNumber >= [[[NSBundle mainBundle] pathsForResourcesOfType:#".jpg" inDirectory:nil] count] ) {
return nil;
}
else{
SinglePageViewController *singlePage = [[SinglePageViewController alloc] initWithNibName:#"SinglePageViewController" bundle:nil];
[singlePage setPageNumber:previousPageNumber+1];
return singlePage;
}
}
That's it. Command-R to test it with the iPad Simulator
This is a basic shell and other bells and whistles can be added for your own pleasure, i.e. take out Page Number, add a caption, etc.
Hope this helped.
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.