Calling Delegate Method not Working - objective-c

I have a UIButton which calls a method from another UIViewController, that method calls a delegate method which is not happening.
Something like:
FirstViewController
-(void)viewWillAppear:(BOOL)animated {
//Submit Button
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(someMethod)
forControlEvents:UIControlEventTouchDown];
[button setTitle:#"Submit" forState:UIControlStateNormal];
button.frame = CGRectMake(100.0, 120.0, 80.0, 40.0);
[self addSubview:button];
}
- (void)someMethod {
SecondViewController *viewC = [[SecondViewController alloc] init];
[viewC otherMethod];
}
SecondViewController
- (void)otherMethod {
NSLog(#"Verification.....");
[self.delegate foo:self Bar:self.text]; //not working when called the otherMethod from FirstViewController
}
I know I'm doing it wrong way.

A very simple example of the way protocols and delegates work in objective-c
#class A;
#protocol DelegateName<NSObject>
#optional
- (void)doSomething:(NSString *)text;
#end
#interface A: NSObject {
NSString *bar;
id <DelegateName> delegate;
}
#property (nonatomic, retain) NSString *bar;
#property (nonatomic, assign) id <DelegateName> delegate;
- (void)someAction;
#end
This is your protocol declaration.
Then when you are calling the delegate method, you need an object of the class to invoke the delegate method. In your case it is vc. You set delegate like this:
[vc setdelegate: self];
Then you invoke method, like you have done.
See if you are missing any point from this example.

Try to understand how delegate methods work .
#protocol CPUPerformanceDelegate <NSObject>
-(void)getUsedCpuOperations:(float)percent;
-(void)getKernelCpuOperations:(float)percent;
-(void)getIdleCpuOperations:(float)percent;
-(void)getUserCpuOperations:(float)percent;
-(void)getNiceCpuOperations:(float)percent;
#end
#interface CPUPerformance : NSObject{
processor_info_array_t cpuInfo, prevCpuInfo;
mach_msg_type_number_t numCpuInfo, numPrevCpuInfo;
unsigned numCPUs;
NSLock *CPUUsageLock;
}
#property(nonatomic,assign)id<CPUPerformanceDelegate>delegate;
#property(nonatomic,retain)NSTimer *updateTimer;
#end
Then
#import "CPUPerformance.h"
#implementation CPUPerformance
#synthesize delegate,updateTimer;
- (void)updateInfo
{
idlepercent = ((idle/total)*100);
userpercent = (user/total)*100;
syspercent = (sys/total)*100;
nicepercent = (nice/total)*100;
inUsepercent = (inUse/total)*100;
[delegate getIdleCpuOperations:idlepercent];
[delegate getKernelCpuOperations:syspercent];
[delegate getNiceCpuOperations:nicepercent];
[delegate getUsedCpuOperations:inUsepercent];
[delegate getUserCpuOperations:userpercent];
}
and finally
#import "CPUPerformance.h"
#interface SpecProjectFirstViewController : UIViewController<UITableViewDataSource,UITableViewDelegate,CPUPerformanceDelegate>{
//Ivars
NSMutableArray *processArray;
//User Interface Object
UILabel *cpuUsage;
UILabel *cpuIdle;
UILabel *cpuUser;
UILabel *cpuNice;
UILabel *cpuKernel;
IBOutlet UITableView *tableViews;
CPUPerformance *cpuObject;
}
=================
#import "SpecProjectFirstViewController.h"
#implementation SpecProjectFirstViewController
-(void)getIdleCpuOperations:(float)percent{
[cpuIdle setText:nil];
[cpuIdle setText:[NSString stringWithFormat:#"Idle :%.0f %%",percent]];
[cpuIdle setTextAlignment:UITextAlignmentCenter];
}
-(void)getKernelCpuOperations:(float)percent{
[cpuKernel setText:nil];
[cpuKernel setText:[NSString stringWithFormat:#"Kernel :%.0f %%",percent]];
[cpuKernel setTextAlignment:UITextAlignmentCenter];
}
-(void)getNiceCpuOperations:(float)percent{
[cpuNice setText:nil];
[cpuNice setText:[NSString stringWithFormat:#"Nice :%.0f %%",percent]];
[cpuNice setTextAlignment:UITextAlignmentCenter];
}
-(void)getUsedCpuOperations:(float)percent{
[cpuUsage setText:nil];
[cpuUsage setText:[NSString stringWithFormat:#"Used :%.0f %%",percent]];
[cpuUsage setTextAlignment:UITextAlignmentCenter];
}

It is customary to validate that the delegate responds to the method you want to call, so your otherMethod method should be implemented like this, adding more logging to help debug:
- (void)otherMethod
{
NSLog(#"delegate = %p", self.delegate);
if ([self.delegate respondsToSelector:#selector(foo::)])
{
NSLog(#"Calling delegate foo");
[self.delegate foo:self Bar:self.text];
}
else
{
NSLog(#"Delegate doesn't respond to foo");
}
}

Related

Can NSProxy stand in for NSView subclasses?

I've tried a simple test which results in EXC_BAD_ACCESS error:
#import "AppDelegate.h"
#interface CrashingProxy : NSProxy
#property (strong) id target;
- (instancetype)initWithTarget:(id)targetObj;
#end
#implementation CrashingProxy
#synthesize target;
- (instancetype)initWithTarget:(id)targetObj {
[self setTarget:targetObj];
return self;
}
- (void)forwardInvocation:(NSInvocation *)invocation {
[invocation invokeWithTarget:[self target]];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
return [[self target] methodSignatureForSelector:selector];
}
#end
#interface AppDelegate ()
#property (weak) IBOutlet NSWindow *window;
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSButton *button = [[NSButton alloc] initWithFrame:NSMakeRect(20.0, 20.0, 100.0, 32.0)];
[button setButtonType:NSButtonTypeMomentaryLight];
[button setTitle:#"Hello"];
[[[self window] contentView] addSubview:[[CrashingProxy alloc] initWithTarget:button]];
}
#end
Is there something wrong with this test, or is there a fundamental reason why NSView subclasses cannot be used with NSProxy?
Error details:
Thread 1: EXC_BAD_ACCESS (code=1, address=0xc)
at [NSView addSubview:]

how to give action to UIButtoun Outlet from another UIViewController

I have two UIViewController class with names : (RootViewController & SecondViewController).
I have one UIButton Outlet in my SecondViewController.now I want give action method to my UIButton in RootViewController.but I don't know about it.
please guide me and tell me how to get my UIButton in another View and give action method on it in another View....
I'm not sure why you are doing this, it doesn't look good.
Anyway, here's the way.
SecondViewController.h
#interface SecondViewcontroller:UIViewController
#property (nonatomic, weak) IBOutlet UIButton *theButton;
#end
RootViewController.m
SecondViewContoller * sv = [[SecondViewController alloc] init];
[sv.theButton addTarget:self action:#selector(buttonHandler:) forControlEvents:UIControlEventTouchUpInside];
You have to removeTarget when you've done with the button.
Why don't you use delegate or block callback?
ADDED
delegate
SecondViewController.h
#protocol SecondViewControllerDelegate <NSObject>
- (void)theButtonPressed;
#end
#interface SecondViewController : UIViewController
#property (nonatomic, strong) id<SecondViewControllerDelegate>delegate;
#end
SecondViewController.m
#interface SecondViewController ()
{
UIButton *theButton;
}
#end
#implementation SecondViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[theButton addTarget:self.delegate action:#selector(theButtonPressed) forControlEvents:UIControlEventTouchUpInside];
}
#end
RootViewcontroller.h
#interface RootViewController : UIViewController <SecondViewControllerDelegate>
#end
RootViewController.m
SecondViewController *sv = [[SecondViewController alloc] init];
[sv setDelegate:self];
and
- (void)theButtonPressed
{
}
block
SecondViewController.h
typedef void(^TheButtonTouched)(void);
#interface SecondViewController : UIViewController
- (void)addButtonEvent:(TheButtonTouched)event;
#end
SecondViewController.m
#interface SecondViewController ()
{
UIButton *theButton;
TheButtonTouched buttonBlock;
}
#end
#implementation SecondViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// button alloc init here and..
[theButton addTarget:self action:#selector(buttonEvent:) forControlEvents:UIControlEventTouchUpInside];
}
- (void)buttonEvent:(UIButton *)sender
{
if(buttonBlock)
{
buttonBlock();
}
}
- (void)addButtonEvent:(TheButtonTouched)event
{
buttonBlock = event;
}
#end
RootViewController.m
SecondViewController *sv = [[SecondViewController alloc] init];
[sv addButtonEvent:^{
// ADD SOMTHING HERE
}];
You need to create the button's iboutlet property.
Than using object of secondclass.button name you can assign selector.
[classobjectname..btnname addTarget:objectname.class action:#selector(objectname.methodname:);
Just Create RootViewController 's Object and passed into target parameter.
e.g.
[btnShow addTarget:self.rootCtrlObj action:#selector(viewPhoto_click:)
forControlEvents:UIControlEventTouchUpInside];
where rootCtrlObj is #property inside SecondViewController.h file
and when you push this controller in RootViewController you have to pass reference of RootViewController .
For Example,
secVCObj.rootCtrlObj = self;
[self.navigationController pushViewController:secVCObj animated:YES];
as i said custom delegate methods will work perfect for these cases,
in SecondViewController.h file define a custom delegate method like below
#import <UIKit/UIKit.h>
#import "ViewController.h"
#protocol SecondControllerDelegate<NSObject>
- (void)someActionToPerformInRootController;
#end
#interface SecondViewController : UIViewController
#property (nonatomic, assign) id<SecondControllerDelegate>delegate; //declare a custom delegate
#end
in SecondViewController.m file lets take an action of some button
- (IBAction)myButtonActionMethod:(id)sender
{
if([self.delegate respondsToSelector:#selector(someActionToPerformInRootController)])
{
[self.delegate someActionToPerformInRootController]; //this will call the delegate method in first view conroller( root view controller) //do what ever u want t do in the action method of rootviewcontroller
}
}
in RootViewController.h file
#import "SecondViewController.h"
#interface RootViewController : UIViewController < SecondControllerDelegate> //confirmas to delegate
in RootViewController.m while presenting the SecondViewController set the delegate to self
- (IBAction)showAction:(id)sender
{
SecondViewController *secondController = [[SecondViewController alloc]initWithNibName:#"SecondViewController" bundle:nil];
secondController.delegate = self; //call back to this controller
[self presentViewController:secondController animated:YES completion:nil];
}
//this method called from the secondViewcontroller
- (void) someActionToPerformInRootController
{
NSLog(#"perform action in root view controller");
}

UIWebView: Delegate won't be called

I try to calculate the size of a UIWebView with a given content, but without showing the view. I only need to know the size.
My Problem: When I execute the code, the delegate of the UIWebView isn't called. Why?
MessageSizeCaluclator.h
#import < Foundation/Foundation.h>
#class Message;
#interface MessageSizeCaluclator : NSObject <UIWebViewDelegate>
- (id)initWithMessage:(Message*)message;
- (void)saveSize;
#end
MessageSizeCaluclator.m
#import "Message.h"
#import "MessageSizeCaluclator.h"
#interface MessageSizeCaluclator () <UIWebViewDelegate>
#property (strong, nonatomic) Message* message;
#property (strong, nonatomic) UIWebView* webView;
#end
#implementation MessageSizeCaluclator
#synthesize message = _message;
#synthesize webView = _webView;
- (id)initWithMessage:(Message*)message
{
self = [super init];
if (self) {
_message = message;
// WebView
_webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
_webView.delegate = self;
}
return self;
}
- (void)saveSize
{
NSLog(#"%s message = %#", __PRETTY_FUNCTION__, _message.text);
[_webView loadHTMLString:[NSString stringWithFormat:#"<div style='font-family:Helvetica;font-size:13px;'>This is a test</div>", _message.text]
baseURL:nil];
}
#pragma mark - Web view delegate
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
NSLog(#"%s", __PRETTY_FUNCTION__);
}
- (void)webViewDidStartLoad:(UIWebView *)webView
{
NSLog(#"%s", __PRETTY_FUNCTION__);
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
NSLog(#"%s", __PRETTY_FUNCTION__);
}
#end
Implementation
MessageSizeCaluclator* messageSizeCalculator = [[MessageSizeCaluclator alloc] initWithMessage:message];
[messageSizeCalculator saveSize];
Add your UIWebView to some UIView, make its frame offscreen (so users can't see it). The delegate methods won't be called if UIWebView is not in the view hierarchy of the app.

Objective-c update NSTextField at ControllerView init

#interface TestViewController : NSViewController
#property (nonatomic, retain) IBOutlet NSTextField *myLabel;
- (IBAction)sendMessage:(NSButton *)sender;
#end
#implementation TestViewController
#synthesize myLabel = _myLabel;
- (id)init{
self = [super init];
if(self){
[self updateLabel];
}
return self;
}
- (IBAction)sendMessage:(NSButton *)sender {
[self updateLabel];
NSLog(#"Message sent");
}
- (void) updateLabel{
NSLog(#"Update!! %#");
[self.myLabel setStringValue:#"random text"];
}
#end
I want to update an NSTextField when view is displayed, and i put my updateLabel at init in the log i see Update!! but the NSTextField it's not update with my text.
But when i press the button that calls the same updateLabel the NSTextField is updatet. Can someone help me to understand why it's not working as expected ?
I follow the suggestion of #rdelmar to use loadView. Thank you.
And here is how to implement it if anyone interested.
- (void)loadView
{
[super loadView];
[self updateLabel];
}

UIPopoverController Delegate Problem?

I have a UIPopover that I want to use either
-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController{
return NO;
}
or
-(void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController{}
on. Neither of them seem to work (and I'm sure once one is fixed, the other will be too since it's probably a problem with delegates). For delegates, here is what I have:
In optionsViewController.h, the view which is inside the popover:
#import <UIKit/UIKit.h>
#protocol OptionsViewControllerDelegate <NSObject>
-(void)didPick:(NSString *)string;
#end
id delegate;
#interface OptionsViewController : UIViewController <OptionsViewControllerDelegate>{
IBOutlet UIPickerView *picker;
NSMutableArray *list;
}
#property (nonatomic, copy) NSArray *passthroughViews;
#property(nonatomic,retain) NSMutableArray *list;
#property(nonatomic,assign) id<OptionsViewControllerDelegate> delegate;
#end
and in the .m:
#synthesize delegate;
and in the .h of the view where the popover appears:
#interface exampleViewController : UIViewController <OptionsViewControllerDelegate,UIPopoverControllerDelegate>{
UIPopoverController *popoverController;
OptionsViewController *optionsViewController;
}
and in the .m:
#synthesize popoverController;
#synthesize optionsViewController;
-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController{
return NO;
}
[popoverController release];
[optionsViewController release];
In the ViewDidLoad, I have:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
optionsViewController =[[OptionsViewController alloc]init];
optionsViewController.delegate = self;
popoverController = [[UIPopoverController alloc] initWithContentViewController:optionsViewController];
popoverController.popoverContentSize = CGSizeMake(320, 216);
}
To present the popover, I use:
-(IBAction)showDecadePopover{
[popoverController presentPopoverFromRect:CGRectMake(150, 50, 150, 50) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
}
I'm probably missing something really obvious (that's why I gave so much of my code). Thanks so much!
Luke
Yep, simple fix. After you init the popoverController you need to set the exampleViewController as the delegate of it.
[popoverController setDelegate:self];
PS: What is the id delegate; floating after your OptionsViewControllerDelegate protocol definition for? Synthesizing delegate, which you already do, is all you need to create storage for it.