Crash on Setting Delegate - iphone

I have a custom view (settingview) with nib and protocol. i want to add this view on a viewcontoller with delegate. When i set its delegate my app crashes and i don't know what i have done wrong.
i don't have NIB for ViewController.
i am attaching few images of my code and View's NIB.
.h
#protocol SettingViewDelegate
#required
-(void)CornerSlider:(id)sender;
-(void)MarginSlider:(id)sender;
-(void)BorderSlider:(id)sender;
-(void)ShadowSlider:(id)sender;
-(void)BorderColor:(id)sender;
-(void)ShadowColor:(id)sender;
-(void)remove:(id)sender;
#end
#interface SettingView : UIView
#property (nonatomic, assign) id delegate;
-(IBAction)CornerSlider1:(id)sender;
-(IBAction)MarginSlider1:(id)sender;
-(IBAction)BorderSlider1:(id)sender;
-(IBAction)ShadowSlider1:(id)sender;
-(IBAction)BorderColor1:(id)sender;
-(IBAction)ShadowColor1:(id)sender;
-(IBAction)remove1:(id)sender;
#end
.m
#implementation SettingView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self = [[[NSBundle mainBundle] loadNibNamed: #"Setting"
owner: self
options: nil] objectAtIndex:0];
}
return self;
}
-(IBAction)CornerSlider1:(id)sender
{
[self.delegate CornerSlider:sender];
}
-(IBAction)MarginSlider1:(id)sender
{
[self.delegate MarginSlider:sender];
}
-(IBAction)BorderSlider1:(id)sender
{
[self.delegate BorderSlider:sender];
}
-(IBAction)ShadowSlider1:(id)sender
{
[self.delegate ShadowSlider:sender];
}
-(IBAction)BorderColor1:(id)sender{
[self.delegate BorderColor:sender];
}
-(IBAction)ShadowColor1:(id)sender{
[self.delegate ShadowColor:sender];
}
-(IBAction)remove1:(id)sender{
[self.delegate remove:sender];
}
#end
app crashes here after setting its delegate.
SettingView *settingView=[[SettingView alloc]init];
[settingView setDelegate:self];
[self.view addSubview:settingView];

Replace #required with #optional
#protocol SettingViewDelegate
#optional
-(void)CornerSlider:(id)sender;
-(void)MarginSlider:(id)sender;
-(void)BorderSlider:(id)sender;
-(void)ShadowSlider:(id)sender;
-(void)BorderColor:(id)sender;
-(void)ShadowColor:(id)sender;
-(void)remove:(id)sender;
#end

See whether you have implemented all the methods of your delegate into your "self.view" class where you add your "Setting View". Also, see whether you had implemented "SettingsViewDelegate" into the class you add "Setting View" as subview.
For more clarification, look this https://stackoverflow.com/a/12660523/859001

Did you try
#interface BlaBlaViewController : UIViewController<SettingsViewDelegate>
I saw in your code:
-(void)setDelegate:(id)delegate
{
self.delegate = delegate;
}
This would result in an endless loop. You should use the synthesized _ivar for overloading the setter (or leave it out all together).

Mistake found. It was in IB.
I was setting Custom Class (SettingView) to File's Owner's Class. Now Its View's Custom Class and File's Owner is UIView's Class.
and now its working fine. .

Use the following setter method for delegate in the SettingsView implementation.
-(void)setDelegate:(id)adelegate
{
_delegate = adelegate;
}

Try this -
.h
#protocol SettingViewDelegate
-(void)CornerSlider:(id)sender;
-(void)MarginSlider:(id)sender;
-(void)BorderSlider:(id)sender;
-(void)ShadowSlider:(id)sender;
-(void)BorderColor:(id)sender;
-(void)ShadowColor:(id)sender;
-(void)remove:(id)sender;
#end
#interface SettingView : UIView
#property (nonatomic, assign) id delegate;
-(IBAction)CornerSlider1:(id)sender;
-(IBAction)MarginSlider1:(id)sender;
-(IBAction)BorderSlider1:(id)sender;
-(IBAction)ShadowSlider1:(id)sender;
-(IBAction)BorderColor1:(id)sender;
-(IBAction)ShadowColor1:(id)sender;
-(IBAction)remove1:(id)sender;
#end
.m
-(IBAction)CornerSlider1:(id)sender
{
if([self.delegate respondsToSelector:#(CornerSlider:)])
{
[self.delegate CornerSlider:sender];
}
}
-(IBAction)MarginSlider1:(id)sender
{
if([self.delegate respondsToSelector:#(MarginSlider:)])
{
[self.delegate MarginSlider:sender];
}
}
-(IBAction)BorderSlider1:(id)sender
{
if([self.delegate respondsToSelector:#(BorderSlider:)])
{
[self.delegate BorderSlider:sender];
}
}
-(IBAction)ShadowSlider1:(id)sender
{
if([self.delegate respondsToSelector:#(ShadowSlider:)])
{
[self.delegate ShadowSlider:sender];
}
}
-(IBAction)BorderColor1:(id)sender{
if([self.delegate respondsToSelector:#(BorderColor:)])
{
[self.delegate BorderColor:sender];
}
}
-(IBAction)ShadowColor1:(id)sender{
if([self.delegate respondsToSelector:#(ShadowColor:)])
{
[self.delegate ShadowColor:sender];
}
}
-(IBAction)remove1:(id)sender{
if([self.delegate respondsToSelector:#(remove:)])
{
[self.delegate remove:sender];
}
}

Related

Delegates in iOS

I am a newbie to iOS world, so please ignore the obvious.
I am pushing a viewController(HelpViewController) on top of another viewController(MainViewController). When a particular action happens in the HelpViewController, I would like to update a variable inside the MainViewController. I understand for this I need to use delegate.
Here is my delegate header...
#protocol ViewControllerDelegate <NSObject>
#required
- (void) switchToggled:(BOOL)status;
#end
// Protocol Definition ends here
#interface ViewDelegate : NSObject
{
// Delegate to respond back
id <ViewControllerDelegate> _delegate;
}
#property (nonatomic,strong) id delegate;
-(void)sendMessage:(BOOL)status; // Instance method
#end
and implementation...
#implementation ViewDelegate
#synthesize delegate;
-(id)init {
self = [super init];
return self;
}
-(void)sendMessage:(BOOL)status
{
[delegate switchToggled:status];
}
- (void)dealloc
{
[super dealloc];
}
#end
So Now If I want to implement Protocol ViewControllerDelegate I need to specify in MainViewController, which I do as follows --
MainViewController <ViewControllerDelegate>
and
#pragma mark - ViewControllerDelegate delegate
-(void)switchToggled:(BOOL)status{
NSLog(#"Switch Toggled(%d) Message passed to MainViewController",status);
}
My question is how do I specify Object, which delegate property needs to point to, so that it can come back to MainViewController's "switchToggled".
One way I do is by having property inside HelpViewController as follows -
MainViewController.m
HelpViewController *helpVC = [[HelpViewController alloc] init];
helpVC.mainView = self;
[self.navigationController pushViewController:helpVC animated:YES];
[helpVC release];
HelpViewController.h
#property (nonatomic) MainViewController *mainView;
HelpViewController.m
#synthesize mainView;
ViewDelegate *myDelegate = [[ViewDelegate alloc] init];
// assign delegate
myDelegate.delegate = mainView;
[myDelegate sendMessage];
[myDelegate release];
Is this correct way to implement or there is better way to achieve this or am I totally wrong.
Thanks
You should do:
// HelpViewController.h
#protocol HelpDelegate
- (void)switchToggled:(BOOL)status;
#end
// HelpViewController.m
#interface HelpViewController : UIViewController
#property (nonatomic, assign) id<HelpDelegate> delegate;
- (id)initWithDelegate:(id<HelpDelegate>)delegate
#end
#implementation HelpViewController
- (id)initWithDelegate:(id<HelpDelegate>)delegate
{
if (self = [super init])
{
self.delegate = delegate;
}
}
- (void)sendMessage:(BOOL)status
{
[self.delegate switchToggled:status];
}
// MainViewController.h
#import "HelpViewController.h"
#interface MainViewController.h : UIViewController <HelpDelegate>
// MainViewController.m
- (void)someMethod
{
HelpViewController* viewController;
viewController = [HelpViewController alloc] initWithDelegate:self];
...
}
#pragma mark - Help Delegate
- (void)switchToggled:(BOOL)status
{
...
}
Give the delegate a name that makes clear to which class it belongs.
You don't need the extra class/files for ViewDelegate/ViewControllerDelegate. Just define the delegate in header of class it belongs to: HelpViewController.n in this case.
Similar: Implement the delegate method switchToggled: in the real class MainViewController, and not in the extra/unnecessary class ViewDelegate.
The purpose of delegates is to avoid class dependencies. By including MainViewController in HelpViewController you create such a dependency. This is not necessary as I show, and is wrong design.
You were also creating a circular dependency, because MainViewController already needed HelpViewController in order to show it, and now they need each other the other way around for sending the event.
Alternatively you can make HelpViewController's delegate public, have an init without argument, and expect users to set it with helpViewController.delegate = self; or something. But this would only make sense when the delegate being set is optional (which don't seems the case here, so adding it to the init method is appropriate).
I tell you what I would have done:
1) the protocol definition is ok, but do NOT create the class ViewDelegate, so:
//ViewControllerDelegate.h
#protocol ViewControllerDelegate <NSObject>
#required
- (void) switchToggled:(BOOL)status;
#end
2) Your implementation of the delegate method in MainViewController is ok.
3) Now... the important point:
//interface
#interface HelpViewController : UIViewController //or whatever superclass..
{
id <ViewControllerDelegate> _delegate;
}
#property (nonatomic,strong) id<ViewControllerDelegate> delegate;
#end
//implementation
#implementation HelpViewController
- (void)someMethodWhichCallsTheDelegate
{
//do something
...
// call delegate
//if switchToggled: were optional then add the following
//if ([self.delegate respondToSelector:#selector(switchToggled:)]) {
[self.delegate switchToggled:status];
}
#end
4) Now you have to assign the delegate:
//MainViewController.m
HelpViewController *helpVC = [[HelpViewController alloc] init];
helpVC.delegate = self;
[self.navigationController pushViewController:helpVC animated:YES];
[helpVC release];
And that's it!
BTW: if this delegate is related only to HelpViewControllerthen add the protocol definition where you define the interface of the class, it is not necessary to create a separate header file. If instead the protocol is "global", then it can have some sense to declare it separately.

Protocol method does not get invoked, shows delegate 'nil'

I'm working on an iPad App and i'm having issue with delegate... the protocol method does not get invoked. i'm not sure what i'm missing, here is my code.
#protocol pickerLabelProtocol <NSObject>
- (void)selectedPickerData:(UILabel *)sender;
#end
#interface showPickerVC : UIViewController
#property (nonatomic, strong) id <pickerLabelProtocol> delegate;
#end
#implementation showPickerVC
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
//i used breakpoint, the 'delegate' is always nil for some reason?
[self.delegate selectedPickerData:self.mainLabel];
}
----------------------
#interface someViewController : UIViewController <pickerLabelProtocol>
#property (nonatomic, strong) showPickerVC *showPicker;
#end
#implementation someViewController
- (void)selectedPickerData:(UILabel *)sender
{
//protocol method
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.showPicker = [[showPickerVC alloc]init];
self.showPicker.delegate = self;
}
I can not got any mistake From your code but i suggest you that Be clear about when you create object of showPickerVC add it's delegate self
Such Like ,
showPickerVC *obj = [[showPickerVC alloc] init];
obj.delegate = self; /// YOur protocol delegate
.
.
[self presentModalViewController:obj animated:YES];
And Also add code as following
#implementation showPickerVC
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if([self.delegate respondsToSelector:#selector(selectedPickerData:)])
{
[self.delegate selectedPickerData:self.mainLabel];
}
}
For More information about How to create/use of Protocol.

Trying to abstract code out into a library, but my code isn't working and I do not know why

I want to make a library that I can reuse over and over to speed up my development, add to new projects if I wish. Basically I want to build an abstraction layer. Can someone show me how I would do that and why this this portion of code:
if ([self.delegate respondsToSelector:#selector(enableCamera)]) {
BOOL enabled;
enabled = [self.delegate enableCamera];
if (enabled == YES) {
[self enableCameraMethod];
}
does not get called?
HERES MY CODE BELOW:
library.h:
#protocol usesCamera <NSObject>
#optional
-(BOOL)enableCamera;
#end
#interface Library : NSObject
#property (nonatomic, weak) id <usesCamera> delegate;
-(void)enableCameraMethod;
#end
library.m
#import "Library.h"
#implementation Library
- (id) init
{
if (self = [super init]) {
if ([self.delegate respondsToSelector:#selector(enableCamera)]) {
BOOL enabled;
enabled = [self.delegate enableCamera];
if (enabled == YES) {
[self enableCameraMethod];
}
}
return (self);
}
}
-(void)enableCameraMethod {
NSLog(#"Implement my camera method here");
}
#end
UIViewController.h
#import <UIKit/UIKit.h>
#import "Library.h"
#interface ViewController : UIViewController <usesCamera>
#end
UIViewController.m
#import "ViewController.h"
#import "Library.h"
#interface ViewController ()
#property (nonatomic, strong) UIViewController *myVC;
#end
#implementation ViewController
-(BOOL)enableCamera {
return YES;
}
- (void)viewDidLoad
{
[super viewDidLoad];
Library *myLibrary = [[Library alloc] init];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
did you set your delegate for myLibrary instance in your ViewController class.
you have to do something like this:
Library *myLibrary = [[Library alloc] init];
myLibrary.delegate = self;
As init is called before setting the delegate, so it might not worked, instead of defining the logic in init function create another method and call this method after setting the delegate.

#protocol on IOS parsing data 2 way?

I have login Code like this :
#protocol LoginDelegate
-(void)DUsername:(NSString *) username DPassword:(NSString *) password;
#end
#interface loginipad : UIViewController {
id<LoginDelegate> delegate;
IBOutlet UITextField *edusername;
IBOutlet UITextField *edpassword;
}
and then i use this object on mainViewController like this :
#interface mainViewController : UIViewController<LoginDelegate> {
and call this methode on mainViewController
-(void)DUsername:(NSString *) username DPassword:(NSString *) password{
userlogin=[username retain];
passlogin=[password retain];
if (!scm.isRunning) {
[scm connectToHost:#"localhost" onPort:8080];
}
}
This method is success to parsing data from login modalview to mainViewController, but i want show progress of process or any message from mainViewController to login modal view when login button is klick (i try MBPrgoressHUD but no success due i use this login on modal view).
My Question how i can parsing data from mainViewController to This login modalview ?
Thanks,
for call the method :
loginipad *plogin = [[loginipad alloc] initWithNibName:#"loginipad" bundle:nil];
plogin.delegate = self;
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:plogin];
plogin.title=#"Login";
[self presentModalViewController:nc animated:YES];
[nc release];
nc = nil;
[plogin release];
plogin = nil;
answer completely edited
Your question leads to multiple solutions and strategies.
First: general posibilities to implement bidirectional data-transfer between two classes.
via multiple protocols: loose cupling but leads to import-loops which are annoying. I know ho to solve import loops for class-definitions (#class) but I dont know how to solve this for protocols
A.h:
#import "B.h"
#protocol ADelegate
-(void) adelegate:(NSString*)data;
#end
#interface A : NSObject<BDelegate>
{
id<ADelegate> delegate;
}
#end
B.h:
#import "A.h"
#protocol BDelegate
-(void) bdelegate:(NSString*)data;
#end
#interface B : NSObject<ADelegate>
{
id<BDelegate> delegate;
}
#end
via a single protocol: dense cupling :( but no import-loop (this is a working ugly style)
A.h:
//no import here needed
#protocol ADelegate
-(void) adelegate:(NSString*)data;
#end
#interface A : NSObject<BDelegate>
{
id<ADelegate> delegate;
}
#end
B.h:
#import "A.h"
#interface B : NSObject<ADelegate>
{
A* delegate;
}
#end
via pipe/stream: bidirectional data-transfer should by done using a pipe (unbuffered) or stream (buffered)
here I show you a small and simple delegate-pipe but there also exists a NSPipe/NSStream
DelegatePipe.h
#protocol DelegatePipeDelegate
- dataArrived:(NSString*)data;
#end
#interface DelegatePipe : NSObject {
NSMutableArray *delegates;
}
-(void)open:(id<DelegatePipeDelegate>)d;
-(void)close:(id<DelegatePipeDelegate>)d;
-(void)send:(NSString*)data;
#end
DelegatePipe.m
#implementation DelegatePipe
-(id)init
{
if(self = [super init])
{
delegates = [NSMutableArray array];
}
return self;
}
-(void) dealloc
{
[delegates release];
delegates = nil;
}
-(void) open:(id <DelegatePipeDelegate>)d
{
#synchronized(self)
{
if([delegates containsObject:d])
return;
//if([delegates count]>=2) //Pipe contains originally only 2 delegates. but a broadcaster is also nice ;)
// return;
[delegates addObject:d];
}
}
-(void) close:(id <DelegatePipeDelegate>)d
{
#synchronized(self)
{
[delegates removeObject:d];
}
}
-(void) send:(NSString *)data
{
#synchronized(self)
{
for(id<DelegatePipeDelegate> d in delegates)
[d dataArrived:data];
}
}
#end
Second: KVO
KVO is often used in a ModelViewController (MVC) Pattern. eg: visualize data in a view. The network-connection-state in your case is part of data and your loginipad is a view (and a controller)
Authentificator.h
typedef enum eAuthState
{
NOT_CONNECTED = 0,
LOGIN_FAILED,
CONNECING,
CONNECTED
} AuthState;
#interface Authentificator : NSObject {
AuthState state;
}
#property (nonatomic, assign) AuthState state;
#end
Authentificator.m
...
-(void) doAuthWithUsername:(NSString*)name password:(NSString*)pw
{
self.state = CONNECING;
//do network-stuff
}
//delegate from network. here NSURLConnection
-(void) connectionDidFinishLoading:(NSURLConnection *)connection
{
//parse network-answer
BOOL success = YES;
if(success)
self.state = CONNECTED;
else
self.state = LOGIN_FAILED;
}
loginipad.h
#interface loginipad : UIViewController
{
Authentificator *auth;
}
#property (nonatomic, retain) Authentificator *auth;
#end
loginipad.m
#implementation loginipad
#synthesize auth;
//override setter for more comfortable use (add/removeObserver)
-(void) setAuth:(Authentificator *)a
{
#synchronized(auth)
{
[auth removeObserver:self forKeyPath:#"state"];
[auth release];
auth = a;
[auth retain];
[auth addObserver:self forKeyPath:#"state" options:0 context:nil];
}
}
-(IBAction) buttonClicked:(id)aSender
{
self.auth = [Authentificator sharedAuthentificator];
}
-(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if(![object isKindOfClass:Authentificator.class])
return;
AuthState state = ((Authentificator*)object).state;
NSLog(#"curState: %i",state);
//do sth with state
}
- (void)dealloc {
self.auth = nil;
[super dealloc];
}

Delegate not working

I have this code in my viewController:
- (GraphModel *)graphModel
{
if (!graphModel) {
graphModel = [[GraphModel alloc] init];
NSLog(#"graphModel = %#", graphModel);
}
return graphModel;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.graphView.delegate = [self graphModel];
NSLog(#"self.graphview.delegate = %#", self.graphView.delegate);
[self updateUI];
}
but the NSLog just says (null) for self.graphview.delegate
even though the NSLog in graphModel says that I successfully created an object. How can this be?
this is the code for the graphViewDelegate
#class GraphView;
#protocol GraphViewDelegate
- (double)yValueForGraphView:(GraphView *)requestor atPosition:(int)i withPrecision:(int)precision;
- (double)scaleForGraphView:(GraphView *)requestor;
#end
#interface GraphView : UIView {
id <GraphViewDelegate> delegate;
}
#property (assign) id <GraphViewDelegate> delegate;
#end
and then I have #synthesize delegate in graphView.m
Most likely guess: graphView is nil. Calling any method on a nil object has no effect and returns nil, and the .delegate is actually a call to the getter or setter as appropriate. I recommend you add:
NSLog(#"self.graphview = %#", self.graphView);
As a quick verification.