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.
Related
I started testing ECSlidingViewController and after I tried to access FirstTopViewController I have a big trouble - because in FirstToViewController I already have ZBarReaderDelegate implemented and all examples of delegate are not triggering any method from my delegate.
Basically I have this stuff:
FirstTopViewController.h
#import ...MyStuff...
#import "UnderRightViewController.h"
#interface FirstTopViewController : UIViewController <RightViewDelegate, ZBarReaderDelegate>
#property (weak, nonatomic) IBOutlet UITextView *labelTotal;
#end
FirstTopViewController.m
#import "FirstTopViewController.h"
#implementation FirstTopViewController
- (void)setTotalViewController:(UnderRightViewController*)controller didTotalChange:(NSString*)total
{
//labelTotal.text = total;
NSLog(#"I'm here!!! and received %#", total);
}
From other side I have
UnderRightViewController.h
#import <UIKit/UIKit.h>
#import "ECSlidingViewController.h"
#class UnderRightViewController;
#protocol RightViewDelegate <NSObject>
- (void)setTotalViewController:(UnderRightViewController*)controller didTotalChange:(NSString*)total;
#end
#interface UnderRightViewController : UITableViewController
#property (nonatomic, weak) id <RightViewDelegate> delegate;
#end
UnderRightViewController.m
#import "UnderRightViewController.h"
#interface UnderRightViewController ()
#end
#implementation UnderRightViewController
#synthesize delegate;
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[delegate setTotalViewController:self didTotalChange:#"foo"];
}
#end
I'm trying this entire day solve this puzzle but I never get setTotalViewController fired.
Thanks in advance.
Friend you did a small mistake, when you navigate from FirstTopViewController to UnderRightViewController at that time you need to do this in FirstTopViewController.m:-
UnderRightViewController *obj = [[UnderRightViewController
alloc] initWithNibName:#"UnderRightViewController" bundle:nil];
obj.delegate = self; // u forget to assign protocol handler
[self.navigationController pushViewController:obj animated:YES];
[obj release];
You don't have any code that is setting the delegate for the UnderRightViewController. I don't know what object owns both of these controllers, but before either UnderRightViewController and FirstTopViewController are displayed it should run code something like this:
FirstTopViewController *ftvc = //... where ever you get a reference to this from
UnderRightViewController *urvc = ...;
urvc.delegate = ftvc;
In your above code you are using custom delegates and also you have used it for sending message to onecontroller class to another controller class. So below is the same sample code of custom delegates, it is working fine in similar way you have to implement and also the problem in your code is you are not setting the delegate, so please follow below how to set the same and call the method. here i have used your same method only return type i have defined as NSString in-spite of void for explaining purpose, but you can use void according to your requirement hope it will be helpful to you:-
First Controller Class AWindowController.h
#interface AWindowController : NSWindowController<sampleDelegate>
{
NSString *textA;
}
#property(readwrite,retain)NSString *textA;
-(IBAction)doSet:(id)sender;
#end
#import "AWindowController.h"
#import "BWindowController.h"
#interface AWindowController ()
#end
#implementation AWindowController
#synthesize textA;
- (id)initWithWindow:(NSWindow *)window
{
self = [super initWithWindow:window];
if (self) {
// Initialization code here.
}
return self;
}
- (NSString *)setTotalViewController:(BWindowController*)controller didTotalChange:(NSString*)total
{
NSLog(#"recieved");
return #"recieved";
}
- (void)windowDidLoad
{
[super windowDidLoad];
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
}
-(NSString*)windowNibName
{
return #"AWindowController";
}
-(IBAction)doSet:(id)sender
{
[self setTextA:#"Awindow Button Pressed"];
BWindowController *b=[[BWindowController alloc]init];
b.delegate=self;
[b showWindow:self];
}
#end
Second Controller Class BWindowController.h
#import <Cocoa/Cocoa.h>
#import "sampleDelegate.h"
#class BWindowController;
#protocol sampleDelegate <NSObject>
#required
//-(NSString *)getDataValue;
- (NSString *)setTotalViewController:(BWindowController*)controller didTotalChange:(NSString*)total;
#end
#interface BWindowController : NSWindowController<sampleDelegate>
{
NSString *bTextValue;
id<sampleDelegate>delegate;
}
#property(readwrite,retain)NSString *bTextValue;
#property(readwrite,assign)id<sampleDelegate>delegate;
#end
#import "BWindowController.h"
#interface BWindowController ()
#end
#implementation BWindowController
#synthesize bTextValue,delegate;
- (id)initWithWindow:(NSWindow *)window
{
self = [super initWithWindow:window];
if (self) {
// Initialization code here.
}
return self;
}
- (NSString *)setTotalViewController:(BWindowController*)controller didTotalChange:(NSString*)total;
{
return nil;
}
- (void)windowDidLoad
{
NSString *str= [[self delegate]setTotalViewController:self didTotalChange:#"recieved"];
self.bTextValue=str;
[super windowDidLoad];
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
}
-(NSString*)windowNibName
{
return #"BWindowController";
}
#end
Attached screen shot in Output:-
Below is window is the AwindowController.h class
Below in the same above window pressing the button and when Awindow button pressed data will send
and notification will be recieved in Bwindow using above define custom delegates as attached in the screen shot.
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.
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.
I have an NSObject called FHSUploadManager, which is a singleton object. Everything has appears to be working, expect today I been getting some strange messages.
2011-09-16 13:26:05.892 FHMedia[6038:6903] -[FHSUploadManager initialize]: unrecognized selector sent to instance 0x6b96900
2011-09-16 13:26:06.975 FHMedia[6038:6903] *** NSInvocation: warning: object 0xb0352cb8 of class 'úè0°8s†Gà–!Ä' does not implement methodSignatureForSelector: -- trouble ahead
2011-09-16 13:26:06.983 FHMedia[6038:6903] *** NSInvocation: warning: object 0xb0352cb8 of class 'úè0°8s†Gà–!Ä' does not implement doesNotRecognizeSelector: -- abort
It does not look like anything is broken, but these messages have me concern. Has anyone seen this before? Anyone have an idea on how to debug this?
I have taken out some of the methods for privacy and space.
Here is my FHSUploadManager.h
#class ListObject;
#class MergedItem;
#class ServerSync;
#class AppDelegate_Shared;
#class RegisteredUser;
#interface FHSUploadManager : NSObject {
NSMutableArray *uploadItems;
NSMutableArray *objectIds;
// KVO values
BOOL isSyncing;
NSString *uploadingStatus;
ListObject *uploadObject;
AppDelegate_Shared *appDelegate;
ServerSync *sync;
}
#property (assign) BOOL isSyncing;
#property (assign) NSString *uploadingStatus;
#property (assign) ListObject *uploadObject;
#property (assign) AppDelegate_Shared *appDelegate;
#end
Here is FHSUploadManager.m
#import "FHSUploadManager.h"
#import "ListObject.h"
#import "Reachability.h"
#import "ServerSync.h"
#import "AppDelegate_Shared.h"
#import "ItemAttribute.h"
#import "CoreItem.h"
#import "Media.h"
#import "MergedItem.h"
#import "WebServices.h"
#import "NSManagedObject+XML.h"
#import "NSNotificationCenter+MainThread.h"
#import "PowerMeXMLParser.h"
#import "RegisteredUser.h"
#import "TBXML.h"
static FHSUploadManager* sharedInstanceFHSUploadManager = nil;
#implementation FHSUploadManager
#synthesize isSyncing;
#synthesize uploadingStatus;
#synthesize uploadObject;
#synthesize appDelegate;
- (void)dealloc {
[uploadItems release];
[uploadingStatus release];
[uploadObject release];
[objectIds release];
[sync release];
[super dealloc];
}
-(void)startUpload
{
if( !isSyncing )
{
self.isSyncing = YES;
[self performSelectorInBackground:#selector(uploadingInBackground) withObject:nil];
}
}
// !!! Other methods and not added here. !!!
#pragma mark - Apple Boiler Plate Singleton -
+ (FHSUploadManager*)sharedInstance {
#synchronized(self)
{
if (sharedInstanceFHSUploadManager == nil) {
sharedInstanceFHSUploadManager = [[super allocWithZone:NULL] init];
sharedInstanceFHSUploadManager.isSyncing = NO;
sharedInstanceFHSUploadManager.appDelegate = (AppDelegate_Shared*)[[UIApplication sharedApplication] delegate];
}
}
return sharedInstanceFHSUploadManager;
}
+ (id)allocWithZone:(NSZone *)zone {
return [[self sharedInstance] retain];
}
- (id)copyWithZone:(NSZone *)zone {
return self;
}
- (id)retain {
return self;
}
- (NSUInteger)retainCount {
return NSUIntegerMax; //denotes an object that cannot be released
}
- (void)release {
//do nothing
}
- (id)autorelease {
return self;
}
#end
Update After comment saying it was gone
It is back! I talked with a fellow programmer and he is wondering if I am stomping on some memory. So I am going to look into a little bit more.
Looks like you are not inheriting from NSObject...
The FHSUploadManager object class is deallocating. In the Edit Schemes Enable Zombie Objects. You will get log of the deallocated instance.
You may be accessing the object once it is freed.
Add a breakpoint on FHSUploadManager dealloc method.
In my app , i created my custom class and i am observing one of its property using KVO ,so that if its value changed it instantly display in firstview controller object (label or .. )
sample code
myCustomClass.h
#interface myCustomClass : NSObject {
NSString * text;
}
#property (nonatomic, retain) NSString * text;
- (void)changetext;
myCustomClass.m
#implementation myCustomClass
#synthesize text;
static myCustomClass * _sharedInstance;
- (id)init
{
if ((self = [super init])) {
text = # "";
}
return self;
}
+ (myCustomClass *)sharedInstance
{
if (!_sharedInstance) {
_sharedInstance = [[myCustomClass alloc] init];
}
return _sharedInstance;
}
- (void)changetext {
text = # "changed";
}
firstViewController.h
#interface FirstViewController:UIViewController {
IBOutlet UILabel * label;
}
#property (nonatomic, retain) IBOutlet UILavel * label;
firstviewController.m
#implementation FirstViewController
#synthesize label;
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id) object change:(NSDictionary *)change context:(void *)context
{
label.text = [change valueForKey:# "new"];
}
- (void)viewDidLoad {
myCustomClass * myEngine = [myCustomClass sharedInstance];
[myEngine addObserver : self forKeyPath : # "text" options : NSKeyValueObservingOptionNew context : nil];
[myEngine changetext];
[super viewDidLoad];
}
but its not changing the data , can any one please tell me where i am wrong ?
thanks in advance
P.S : i wrote in hurry forgive me if any mistakes in writing and sorry for my bad english .
When you assign to an instance variable directly rather than going through a setter, you need to issue change notifications yourself with willChangeValueForKey: and didChangeValueForKey:. There's no magic to variable assignment.
Replace text with self.text as The observer sub-system is tied into the getter and setter methods synthesized as the property.