Why my iPhone app cannot call the delegate method - iphone

I'm developing the iPhone app. I custom defined the titleview for navigation bar. The title view contains a button, I also defined the delegate method to support the button click event. But when the button clicked, the delegate cannot be executed. I am not sure why ?
Below as my codes:
UPDelegate.h
#protocol UPDelegate <NSObject>
#optional
-(void)buttonClick;
#end
TitleView.h
#import <UIKit/UIKit.h>
#import "UPDelegate.h"
#interface TitleView :UIView
#property (nonatomic, unsafe_unretained) id<UPDelegate> delegate;
-(id)initWithCustomTitleView;
#end
TitleView.m
#synthesize delegate;
-(id)initWithCustomTitleView
{
self = [super init];
if (self) {
UIButton *titleButton = [UIButton buttonWithType:UIBUttonTypeCustom];
titleButton.frame = CGRectMake(0, 0, 20, 44);
[titleButton setTitle:#"ABC" forState:UIControlStateNormal];
// add action
[titleButton addTarget:delegate action:#selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:titleButton];
}
return self;
}
In my ViewController, i implement the protocal as below:
MyViewController.h
#interface MyViewController : UIViewController<UPDelegate>
and in the .m file, i wrote the delegate method, but cannot be exeucte.
MyViewController.m
-(void)buttonClick{
NSLog("click title button");
}

You have to set your delegate, from you code sample you are creating id<UPDelegate> delegate; in your titleView class.
So in your MyViewController where you have added <UPDelegate>, create an instance of TitleView and set delegate to self.
So in your MyViewController use:
TitleView*titleView=[[TitleView alloc]init];
titleView.delegate=self;

It sounds like you have not set the value of your titleView's delegate property, so any messages sent to the delegate property are ignored because the delegate is nil.
You should make sure that you are setting your titleView's delegate to be your MyViewController. The best place to do this is most likely in your MyViewController's viewDidLoad: method.

Did you set the delegate anywhere? Because you have to set the delegate of your TitleView to MyViewController:
titleView.delegate = self;

Related

Custom Delegate Does Not Receive a Call

My custom delegate does not receive a call. Here is my setup. ViewController has a SliderView object which is a subclass of UIScrollView:
SlideView.h
#import <UIKit/UIKit.h>
#protocol SlideViewDelegate <NSObject
#required
-(void) didTapImageData:(NSMutableArray*)imageData atIndex:(int)index;
#end
#interface SliderView : UIScrollView<UIGestureRecognizerDelegate> {
__weak id<SlideViewDelegate> slideViewDelegate;
}
#property (nonatomic, weak) id<SlideViewDelegate> slideViewDelegate;
#end
SlideView.m
#import "SliderView.h"
#implementation SliderView
#synthesize slideViewDelegate;
- (void) handleTap:(UITapGestureRecognizer *)recognizer{
NSLog(#"tapped");
[[self slideViewDelegate] didTapImageData: imageData atIndex:0 ];
}
ViewController.h
#interface ViewController : UIViewController <
UIScrollViewDelegate,
SlideViewDelegate>{
SliderView *thumbGalleryView;//delegate and reference are set in XCode
}
ViewController.m
#import "ViewController.h"
#implementation ViewController
-(void)didTapImageData:(NSMutableArray*) imageData atIndex:(int)index{
NSLog(#"NOT WORKING HERE");
}
So ViewController never receives a call at the method above. The thumbGalleryView is linked to ViewController and delegate is set to ViewController too. SlideView's handleTap is printing message fine but [[self slideViewDelegate] didTapImageData: imageData atIndex:0 ]; is ignored. Why?
You have set the delegate which is ivar of scroll view.
You have to set the slideViewDelegate to ViewController
Edited
Add IBOutlet
IBOutlet __weak id<SlideViewDelegate> slideViewDelegate;
Then from your xib connect slideViewDelegate to ViewController
Also remember to change the class of scroll view to SliderView
Added Image for clarity
Double-check where you set your delegate - if your delegate is nil at the time -handleTap: calls your -didTapImageData:atIndex: method, nothing will happen.

How to pass digit or data from subclassed UIView to UIViewController?

I have subclassed UITableViewController and inside table I have custom cells. And this custom cells have subclassed UIView inside. So this UIView is written in its own class. In my code the UITableViewController class is named MainViewController.h/.m and UIView's class is named ContentView.h/.m So in ContentView I added an image and tapGestureRecognizer. To when the image is tapped some date(in this case digit) is send to MainViewController. The first problem is that the delegate method does not get called. And if I call it with notificationCenter it logged it as 0.00000 Can someone help me to pass data from view inside cell to ViewController.
This is my code:
ContentView.h:
#class ContentView;
#protocol ContentViewDelegate
- (void)passDigit:(float)someDigit;
#end
#import <UIKit/UIKit.h>
#import "MainViewController.h"
#interface ContentView : UIView
{
id <ContentViewDelegate> delegate;
float someDigit;
}
#property float someDigit;
#property (assign) id <ContentViewDelegate> delegate;
#end
ContentView.m
#import "ContentView.h"
#implementation ContentView
#synthesize someDigit;
#synthesize delegate;
- (void)handleContentTouch:(UIGestureRecognizer *)gesture
{
someDigit = 134;
[self.delegate passDigit:someDigit];
}
- (void)setupView
{
CGRect frame = self.frame;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(handleContentTouch:)];
UIImageView *fifthBackground = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,100,100)];
[self addSubview:fifthBackground];
[fifthBackground setUserInteractionEnabled:YES];
[fifthBackground addGestureRecognizer:tap];
}
MainViewController.h
#import <UIKit/UIKit.h>
#import "ContentView.h"
#interface MainViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource, UIScrollViewDelegate, ContentViewDelegate>
#end
MainViewContorller.m
#import "MainViewController.h"
#implementation MainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
ContentView *contentView = [[ContentView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];
contentView.delegate = self;
}
- (void) passDigit:(float)someDigit
{
NSLog(#"%f",someDigit);
}
Not sure what you are trying to do, may be you are new and learning out some things. Try doing the following:
Change your method in mainViewController
- (void) showDetailViewControllerWithDigit:(float)someDigit
{
NSLog(#"%f",someDigit);
}
to
- (void)passDigit:(float)someDigit
{
NSLog(#"%f",someDigit);
}
and it should work. Also not very relevant here but you have spelled delegate and delegete in two different places. Be mindful that they both will be considered as two different variables. Though not necessary to have an instance variable with the same name, I would definitely not have it with a slight typo, because it will cause a lot of problems later.
When you define a protocol for a delegate, the methods you have defined there should be implemented in the delegate class.
Also in your code you have, obviously you have missed some parts, which show as to where you are adding the contentView in the main view controller. I am assuming that some where you have
[self.view addSubview:contentView];
in the viewDidLoad or some where, without which you cannot even see the contentView and there fore cannot tap it.
Happy coding.

Delegate Being Sent To Wrong Class

I subclassed my navigation bar, making the title view clickable. When clicked, it will present another view controller. I am creating a protocol in the navigation bar, that will tell the navigation controller that the title view has been clicked. Here is how my navigation bar is defined:
NavigationBar.h:
#protocol NavigationBarDelegate;
#interface NavigationBar : UINavigationBar
{
id <NavigationBarDelegate> delegate;
BOOL _titleClicked;
}
#property (nonatomic, assign) id <NavigationBarDelegate> delegate;
#end
#protocol NavigationBarDelegate
#optional
- (void)titleButtonClicked:(BOOL)titleClicked;
#end
The delegate implements one optional method. The .m file is as follows:
NavigationBar.m:
#implementation NavigationBar
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
_titleClicked = 0;
}
return self;
}
- (void)drawRect:(CGRect)rect
{
self.tintColor = [UIColor colorWithRed:(111/255.f) green:(158/255.f) blue:(54/255.f) alpha:(255/255.f)];
UIImage *image = [UIImage imageNamed:#"titlelogo.png"];
UIButton *titleButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, image.size.width, image.size.height)];
titleButton.backgroundColor = [UIColor colorWithPatternImage:image];
[titleButton addTarget:self action:#selector(titleButton:) forControlEvents:UIControlEventTouchUpInside];
// self.navigationController.delegate = self;
[self.topItem setTitleView:titleButton];
[super drawRect:rect];
}
- (void)titleButton:(UIButton *)sender
{
_titleClicked = !_titleClicked;
[self.delegate titleButtonClicked:_titleClicked];
}
This creates a navbar with a logo and calls the titleButton method when the title button has been clicked. Everything is fine up till here and the navigation bar displays nicely.
In my RootViewController:
NavigationBar *navigationBar = [[NavigationBar alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.view.frame.size.width, 44.0f)];
navigationBar.delegate = self;
[self.navigationController setValue:navigationBar forKey:#"navigationBar"];
An implementation of titleButtonClicked is also there. When I click on the title view however, I get the following error: -[UINavigationController titleButtonClicked:]: unrecognized selector sent to instance
Why am I getting titleButtonClicked sent to UINavigationController? Is there something I need to do in my navigation controller? I am just using plain old UINavigationController. Do I need to subclass that too? If so, why?
EDIT:
Calling po self.delegate on line [self.delegate titleViewClicked:_titleClicked]; in NavigationBar.m yields the result below. How did the delegate change its type? How can I fix that?
(lldb) po self.delegate
(objc_object *) $1 = 0x07550170 <UINavigationController: 0x7550170>
As #idz said, the problem is with your:
#property (nonatomic, assign) delegete;
Don't you see that it's weird that you don't even have a:
#synthesize delegete;
That's because UINavigationBar already defines a delegate variable as idz said.
change your declaration to:
// use unsafe_unretained in ARC, not assign
#property (nonatomic, unsafe_unretained) myDelegete;
and of course
#synthesize myDelegate;
You have a clash/ambiguity between your delegate and UINavigationBar's delegate property. Rename your delegate to disambiguate them.

How to create UI elements programmatically

I'd like to be able to create new UI elements (a UIProgressView bar) in a separate UIViewController every time a user taps on a button.
How would I go about doing this?
To create a UIProgressView programmatically, it is simply a matter of using alloc and init, setting a frame, and adding a subview, like so:
//.h
#import <UIKit/UIKit.h>
#interface ExampleViewController : UIViewController {
//create the ivar
UIProgressView *_progressView;
}
/*I like to back up my iVars with properties. If you aren't using ARC, use retain instead of strong*/
#property (nonatomic, strong) UIProgressView *progressView;
#end
//.m
#implementation
#synthesize progressView = _progressView;
-(void)viewDidLoad {
/* it isn't necessary to create the progressView here, after all you could call this code from any method you wanted to and it would still work*/
//allocate and initialize the progressView with the bar style
self.progressView = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleBar];
//add the progressView to our main view.
[self.view addSubview: self.progressView];
//if you ever want to remove it, call [self.progressView removeFromSuperView];
}
Read this guide https://developer.apple.com/library/ios/#DOCUMENTATION/WindowsViews/Conceptual/ViewPG_iPhoneOS/CreatingViews/CreatingViews.html
Most of the UI elements create like this:
UIView *view = [[UIView alloc] initWithFrame:CGRect];
// set the property of the view here
// ...
// finally add your view
[ViewController.view addSubView:view];

How to Change UIButton title?

MyViewController has one UIButton and another MainViewController use MyViewController.
but MainViewController can't change UIButton title in MyViewController.
also, in MyViewController only change UIButton title in viewDidLoad method.
What's wrong?
MyViewController
#interface MyViewcontroller : UIViewController {
IBOutlet UIButton *imageButton;
}
#property (nonatomic, retain) UIButton *imageButton;
#implementation MyViewcontroller : UIViewController {
#synthesize imageButton;
- (void)viewDidLoad { // can change button title
[imageButton setTitle:#"buttonTitle" forState:UIControlStateNormal]
}
- (void)setButtonTitle { // can't change button title
[imageButton setTitle:#"buttonTitle" forState:UIControlStateNormal];
}
}
MainViewController
#implementation MainViewController : UIViewController {
#synthesize scrollView;
- (void)viewDidLoad { // can't change button title
MyViewcontroller *myView = [[MyViewcontroller alloc] initWithNibName:#"MyViewcontroller" bundle:nil];
[myView.imageButton setTitle:#"ddd" forState:UIControlStateNormal];
[scrollView addSubview:myView.view];
[myView release], myView = nil;
}
}
It happens because the outlets don't get wired until after the view is loaded, and the view doesn't get loaded until after it gets called for the first time (it's lazy loading). You can fix this very easily by just ensuring that you always load the view first. However, you might want to reconsider your design and make the button title dependent on some other item that's not part of the view hierarchy.
For example, if you re-order your calls, it will work:
MyViewcontroller *myView = [[MyViewcontroller alloc] initWithNibName:#"MyViewcontroller" bundle:nil];
[scrollView addSubview:myView.view]; // view is loaded
[myView.imageButton setTitle:#"ddd" forState:UIControlStateNormal]; // imageButton is now wired