Adding a Navigation Controller but navigation item not displaying - ios

Originally I had a custom NavigationBar, without a navigation controller. I have a sliding menu.
On the home screen there is a tableview, with a list. I would like to be able to add items to this list. So, I had to add in a navigation controller after the fact. I added the navigation controller to the storyboard and linked it to my main view controller [the one with the list]. Then I dragged in a view controller. I dropped in a bar button item into the navigation item, and pushed it to the recently added view controller.
I ran my app and the app shows no navigation bar or navigation item whatsoever now. Originally I had a custom navigation bar.
I'm not too sure what's going on here. Thanks for any help.
- (void)customizeAppearance {
UIImage *NavBG = [UIImage imageNamed:#"nav bar.png"];
[[UINavigationBar appearance] setBackgroundImage:NavBG forBarMetrics:UIBarMetricsDefault];
init View Controller code from .m
#import "initViewController.h"
#import "ECSlidingViewController.h"
#import "MenuViewController.h"
#interface initViewController ()
#end
#implementation initViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.topViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"Main"];
}
from .h
#import "ECSlidingViewController.h"
#interface initViewController : ECSlidingViewController
#end
from main.m
#import "MainViewController.h"
#import "ECSlidingViewController.h"
#import "MenuViewController.h"
#interface MainViewController ()
#end
#implementation MainViewController
{
NSArray *toDoList;
NSIndexPath *selectedIndexPath;
}
#synthesize menuBtn;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
from main.h
#import <UIKit/UIKit.h>
#interface MainViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
{
}
#property (strong, nonatomic) UIButton *menuBtn; // go to MenuViewController.m and synthesize
#end
Second view controller.m file
#import "SecondViewController.h"
#import "ECSlidingViewController.h"
#import "MenuViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
#synthesize menuBtn;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Below is the same stuff pasted from MainViewController.m
// Do any additional setup after loading the view.
self.view.layer.shadowOpacity = 0.75f;
self.view.layer.shadowOpacity = 10.0f;
self.view.layer.shadowColor = [UIColor blackColor].CGColor;
if (![self.slidingViewController.underLeftViewController isKindOfClass:[MenuViewController class]]) {
self.slidingViewController.underLeftViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"Menu"];
}
[self.view addGestureRecognizer:self.slidingViewController.panGesture];
self.menuBtn = [UIButton buttonWithType:UIButtonTypeCustom];
menuBtn.frame = CGRectMake(8, 10, 34, 24);
[menuBtn setBackgroundImage:[UIImage imageNamed:#"menuButton.png"] forState:UIControlStateNormal];
[menuBtn addTarget:self action:#selector(revealMenu:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.menuBtn];
}
Here are all the arrays I use

From the image you are showing, it doesn't look like any of the VCs have the starting arrow to its left. If that is the case, go to SB, click on the Nav controller, go to Attributes inspector on the right,scroll down and check the "Is initial View Controller".
Hope this answers it.
Update: Guessing at your code, you are trying to modify an immutable NSArray. Change your declaration to NSMutableArray *toDoList.

Related

How open a viewController from inside a Static Library in Xcode?

I have a static library that contains a view controller class.
How on a new project in Xcode after include the static library (and headers) can I call this viewController?
View controller on static library:
#import "VC.h"
#interface VC ()
#property (nonatomic, strong) UILabel *label;
#property (nonatomic, strong) UIWindow *window;
#end
#implementation VC
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
_window.backgroundColor = [UIColor whiteColor];
[self.view addSubview: _window];
[super viewDidLoad];
self.label = [[UILabel alloc] initWithFrame:CGRectMake(115.0f, 150.0f, 200.0f, 30.0f)];
self.label.text = #"hello world!";
[self.view addSubview:self.label];
// Do any additional setup after loading the view.
}
#end
I have tried to allocate this ViewController in a new project and call it... but do not work:
VC *vc = [[VC alloc] init];
[self presentViewController:vc animated:YES completion:nil];
Am I missing something else?
* UPDATE
After the last edit, now I can see the viewcontroller, but it's not on top of the main viewcontroller and it becomes black after it loads... any thoughts?
There are a few ways to do this. I would say the most simple way to do this is simply include your viewControllers .xib or storyBoard as files in a folder with the library. If there is no good reason why users cannot have access to this, it shouldn't be that big of an issue.
The other way to do it would be to use the universal framework to make your library. This will return two frameworks for you when you compile it, one with the suffix .framework and the other with the suffix .embeddedframework. The latter will have links to your resources.
The final way to do it is include it in your project as a bundle. This is a somewhat involved and non-intuive process compared to the above ones.
EDIT:
If you are doing it not with a storyboard or .xib file you need to actually alloc and init self.view. It isn't getting loaded in from a storyboard, so you need to load it yourself. That's the issue with this code.
I was missing the basic structure for the view controller.
Creating an UIWindow inside the viewController fixed the problem for me.
Full Source code:
Static library view controller file (VC.m):
#import "VC.h"
#interface VC ()
#property (nonatomic, strong) UILabel *label;
#property (nonatomic, strong) UIButton *button;
#property (nonatomic, strong) UIView *window;
#end
#implementation VC
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// CREATE UIVIEW INSIDE VIEW CONTROLLER
_window = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
_window.backgroundColor = [UIColor whiteColor];
// CREATE BUTTON TO CLOSE VIEW CONTROLLER AFTER IS SHOWN
_button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[_button addTarget:self action:#selector(closeWindow:) forControlEvents:UIControlEventTouchDown];
[_button setTitle:#"Close View" forState:UIControlStateNormal];
_button.frame = CGRectMake(115.0f, 150.0f, 200.0f, 30.0f);
// ADD BUTTON TO THE UIWINDOW
[_window addSubview: _button];
// ADD UIWINDOW TO VIEW CONTROLLER
[self.view addSubview: _window];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Close ViewController
- (IBAction)closeWindow:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
After import the static library and headers to a new app you can invoke the view controller with an IBAction like this:
#import "VC.h" //header for viewcontroller code in static library
...
-(IBAction)callVC:(id)sender {
VC *vc = [[VC alloc] init];
[self presentViewController:vc animated:YES completion:nil];
}

trying to learn objective-c delegates. why wont my sample project work?

I am trying to pass data between two view controllers. viewcontroller2 is a delegate of viewcontroller.. note.. i called the delegate property "homie" yes I know this is bad practice but I am just messing around trying to understand the concept.
here is viewcontroller:
#import <UIKit/UIKit.h>
#protocol ViewControllerDelegate <NSObject>
#required
- (void)sendData:(NSString *)theString;
#end
#interface ViewController : UIViewController
#property (nonatomic, assign) id <ViewControllerDelegate> homie;
- (void)doSomething;
- (IBAction)doneText:(id)sender;
#end
implementation:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)doSomething{
}
- (IBAction)doneText:(id)sender {
UITextField *thisField = sender;
if([_homie respondsToSelector:#selector(sendData:)]){
[_homie sendData:[thisField text]];
}
}
now here is the other view controller implementing the first
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface ViewController2 : UIViewController <ViewControllerDelegate>
- (IBAction)hittingbtn:(id)sender;
#property (weak, nonatomic) IBOutlet UITextField *textfield;
#property (strong, nonatomic) ViewController *vc;
#end
implementation:
#import "ViewController2.h"
#interface ViewController2 ()
#end
#implementation ViewController2
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
ViewController *theview = [[ViewController alloc]init];
theview.homie = self;
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
// DELEGATE METHOD
- (void)sendData:(NSString *)theString{
[_textfield setText:theString];
}
- (IBAction)hittingbtn:(id)sender {
}
#end
in viewdidload I instantiate the first viewcontroller, and set myself as its delegate. im assuming then when that viewcontroller2 runs the code in its method then it will see if its delegate has implemented the delegate method and use that code.. what am i missing here?
Your problem is that you use ViewControllers wrong. You have initialized ViewController
ViewController *theview = [[ViewController alloc]init];
theview.homie = self;
And what next? You haven't assign it to your properties or something. What have you do? It's simple. You have to implement - (void)prepareForSegue:sender:. First of all in your storyboard set segue's identifier. Then do following.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"MySegue"]) {
ViewController *destinationViewController = (ViewController *)[segue destinationViewController];
ViewController.homie = self;
}
}
You need to set the delegate in prepareForSegue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.destinationViewController respondsToSelector:#selector(setHomie)]) {
[segue.destinationViewController setHomie:self];
//or
if ([[segue.destinationViewController isKindOfClass:[ViewController class]]) {
ViewController *destinationViewController = (ViewController *)[segue destinationViewController];
ViewController.homie = self;
}
//or the segue identifier which has already been mentioned
}

Classical MVC in Cocoa

I'm trying to structure some view-code out of the controller (obviously without using a nib). Therefore, I tried a simple example, but for some reason, I can't add the target to the button in the controller, rest is fine. Here's what I'm trying:
Controller.h:
#import <UIKit/UIKit.h>
#import "IndexView.h"
#interface IndexController : UIViewController
{
}
#property (nonatomic) IndexView *contentView;
#end
Controller.m
#import "IndexController.h"
#import "IndexView.h"
#interface IndexController ()
#end
#implementation IndexController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.contentView = [[IndexView alloc]init];
[self.view addSubview:self.contentView];
[self connectUIElements];
}
return self;
}
- (void) connectUIElements
{
[self.contentView.testButton addTarget:self action:#selector(testButtonClicked) forControlEvents:UIControlEventTouchUpInside];
}
#pragma mark --
#pragma mark UIHandler
- (void) testButtonClicked
{
NSLog(#"testbutton clicked");
}
#end
View.h
#import <UIKit/UIKit.h>
#interface IndexView : UIView
#property (nonatomic, strong) UIButton *testButton;
#end
View.m
#import "IndexView.h"
#implementation IndexView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setUpView];
}
return self;
}
- (id) init
{
self = [super init];
if (self) {
[self setUpView];
}
return self;
}
- (void) setUpView
{
[self setBackgroundColor:[UIColor whiteColor]];
self.testButton = [[UIButton alloc]initWithFrame:CGRectMake(10, 50, 100, 50)];
self.testButton.backgroundColor = [UIColor greenColor];
[self.testButton setTitle:#"hello, world" forState:UIControlStateNormal];
[self addSubview:self.testButton];
}
#end
I'm just exploring possibilities to get closer to a classical MVC pattern and a little farther away from Apples mediator-interpretation. Any idea what's wrong?
You have to create your view using initWithFrame:, which is the default initializer for UIView. (The reason that is does not work with a simple init - but I am guessing here! - might be that the views size is zero and therefore the touch events do not work.)

Sending information from a view controller to another

The question is, I have 9 buttons on viewcontroller (ViewController), and i have an outlet collection for storing all these buttons outlet.
Then i have an action method for handling click event of these buttons.
What I want is send the button image background (as an UIImage * img)of the CLICKED button, segue to another viewcontroller (vc2),
here are my code :
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *cardBtns;
- (IBAction)cardAction:(id)sender;
#end
#import "ViewController.h"
#import "ResultViewController.h"
#interface ViewController ()
#property(strong,nonatomic)UIImage *image;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)cardAction:(id)sender {
for(UIButton *cardButton in self.cardBtns){
self.image = [cardButton currentBackgroundImage];
}
[self performSegueWithIdentifier:#"cardSegue" sender:self.image];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
//UIImage * img = [UIImage imageNamed:#"f1"];
UIImage * img = (UIImage *)sender;
ResultViewController *viewcontroller = [segue destinationViewController];
viewcontroller.img = img;
}
#end
in vc2, i have another button here, and i wish to paint this button background img with the img just sent from vc1 segue.
#interface ResultViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIButton *cardBtn;
#property(strong,nonatomic)UIImage *img;
- (IBAction)cardDismiss:(id)sender;
#end
#import "ResultViewController.h"
#interface ResultViewController ()
#end
#implementation ResultViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.cardBtn setImage:self.img forState:UIControlStateNormal];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)cardDismiss:(id)sender {
[self dismissViewControllerAnimated:NO completion:nil];
}
#end
assume my buttons is 1,2,3,4,5,6,7,8,9
for now, whatever buttons i clicked in vc1, it s always displaying as '6' in vc2...
any suggestions? thanks
The problem is this:
- (IBAction)cardAction:(id)sender {
for(UIButton *cardButton in self.cardBtns){
self.image = [cardButton currentBackgroundImage];
}
[self performSegueWithIdentifier:#"cardSegue" sender:self.image];
}
This will set self.image to the last item in self.cardBtns. You want to set self.image to sender.currentBackgroundImage (and change id in the argument type to UIButton *), and just eliminate the loop.

iOS Custom Delegate Returns Nil after setDelegate called from viewController

I have been having a strange problem using a custom delegate class in ARC. In the viewcontroller after viewDidLoad I call the toolbars setDelegate method and assign the viewcontroller as the delegate.
Whenever I try to reference delegate, it is nil, even after being set in the
viewcontroller.
//MPToolbar.h
#import <UIKit/UIKit.h>
//Define the protocol for the delegate
#class MPToolBar;
#protocol MPToolBarDelegate <NSObject>
#required
- (void)writeButtonSelected;
- (void)writeButtonDeSelected;
#end
#interface MPToolBar : UIView{
id <MPToolBarDelegate> delegate;
}
#property(strong) UIButton *lastButton;
#property(strong) id <MPToolBarDelegate> delegate;
-(IBAction)buttonSelected:(id)sender;
-(void)resizeForOrientation:(UIInterfaceOrientation)orientation;
#end
//MPToolbar.m
#import "MPToolBar.h"
#implementation MPToolBar
#synthesize lastButton, delegate;
- (id)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame])) {
// Initialization code
}
NSArray *nibViews = [[NSBundle mainBundle] loadNibNamed:#"MPToolBar" owner:self options:nil];
[self addSubview:[nibViews objectAtIndex:0]];
return self;
}
#pragma button actions
-(IBAction)buttonSelected:(id)sender{
UIButton *btn = (UIButton *)sender;
if(lastButton && lastButton != btn)[self deselect:lastButton];
if (btn.selected){
[self deselect:btn];
return;
}
[btn setSelected:YES];
lastButton = btn;
switch (btn.tag) {
case 0:
[self.delegate writeButtonSelected];
break;
}
}
-(void)deselect:(UIButton *)btn{
[btn setSelected:NO];
switch (btn.tag) {
case 0:
[self.delegate writeButtonDeSelected];
break;
}
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
-(void)resizeForOrientation:(UIInterfaceOrientation)orientation{
if (UIInterfaceOrientationIsLandscape(orientation)) {
self.frame = CGRectMake(0, 44, 1024, 60);
}
if (UIInterfaceOrientationIsPortrait(orientation)) {
self.frame = CGRectMake(0, 44, 768, 60);
}
}
#end
//ViewTest.h
#import <UIKit/UIKit.h>
#import "MPToolBar.h"
#interface ViewTest : UIViewController <MPToolBarDelegate>
{
MPToolBar *toolBar;
}
#property(strong) MPToolBar *toolBar;
#end
//ViewTest.m
#import "ViewTest.h"
#interface ViewTest ()
#end
#implementation ViewTest
#synthesize toolBar;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.toolBar = [[MPToolBar alloc] initWithFrame:CGRectMake(0, 44, 1024, 60)];
[self.view addSubview:self.toolBar];
[self.toolBar setAlpha:1.0];
[self.toolBar setDelegate:self];
// Do any additional setup after loading the view from its nib.
}
#pragma mark - MPToolBar Delegate Methods
-(void)writeButtonSelected{
//set new annotation for write mode and size to screen bounds.
NSLog(#"writeButtonSelected");
}
- (void)writeButtonDeSelected{
NSLog(#"writeButtonDeSelected");
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
#end
Ok so I finally found the problem. In my xib file I had set the UIView class to my custom controls class name instead of setting files owner.
once I changed the first UIView in the xib back to a standard UIView and then set the files owner to my custom class all was right with the world again!
-Thanks for everyone who tried to help!
Several things that could be causing problems:
Do you actually declare your view controller as a MPToolBarDelegate in its header? (that code is not present).
These are the delegate functions in your code:
-(void)ButtonSelected;
-(void)ButtonDeSelected;
However, you're actually invoking this one:
[_delegate writeButtonSelected];
which is not part of your protocol.
Try changing your delegate declarations like this:
#interface MPToolBar : UIView{
id delegate;
}
#property (nonatomic, assign) id <MPToolBarDelegate> delegate;
then when you call your delegate method use this:
[self.delegate ButtonSelected];
Also, the original iPad is upgradeable to iOS 5.0. If you are using ARC you can't be compatible with 4.3 anyway, ARC only started at 5.0 as I understand it.
With a similar symptom for me, my problem was that the segue's destinationViewController was NOT the object I was expecting it to be, because it was embedded in a UINavigationController.
Easy fix. See here. Lose pointer to Delegate while going through Navigation Controller

Resources