Delegate is not calling method - objective-c

So i have a question .
Can someone Tell me the Problem with this line of code for calling(protocol) a Method
[self.delegate poplogin];
poplogin is method name , its not working for some reason.
its not calling the method poplogin
for reference :
#property(nonatomic,retain) id<loginAuthDelegate> delegate;
So let me Explain the Case
so lets say i have a Class abc.h
#protocol loginAuthDelegate <NSObject>
-(void)poplogin;
#end
After interface
#property(nonatomic,retain) id<loginAuthDelegate> delegate;
in .m i am just calling the Delegate and #synthesize it
[self.delegate poplogin];
not i have another files
let say def.h
i am importing the Class abc.h
#interface def : UIViewController<loginAuthDelegate>
def.m
-(void)poplogin
{
NSLog(#"Delegate doesn't respond to here");
vmpaSecureLogin *ivc = [[vmpaSecureLogin alloc] init];
ivc.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:ivc animated:YES];
}

This is probably because self.delegate is nil.
You probably forgot to affect your object's delegate to some other object in which you implemented the delegate methods, like your ViewController or something.

Related

NSSoundDelegate not being called

I am updating some legacy objective C code to be able to be compiled under OSX 10.13. The legacy code worked and most of the update code does as well except for an NSSoundDelegate that needs to handle a didFinishPlaying function. The delegate method is not being called. The delegate method is contained in a class called MyClass. Here is relevant code.
In MyClass.h:
#class MyClass;
#protocol MyClass <NSObject>
#optional
- (void)sound:(NSSound *)sound didFinishPlaying:(BOOL)flag;
#end
#interface MyClass : NSObject <NSSoundDelegate>
{
}
#property (nonatomic, assign) id <NSSoundDelegate> delegate;
- (void)sound:(NSSound *)sound didFinishPlaying:(BOOL)flag;
- (id) init;
#end
Then in MyClass.m:
#implementation MyClass
#synthesize delegate;
- (void)sound:(NSSound *)sound didFinishPlaying:(BOOL)flag
{
if (flag) {
[[NSNotificationCenter defaultCenter] postNotificationName:#"handleNSSoundDidFinishPlaying" object:sound];
}
}
- (id)init
{
MyClass *thePointer;
self = [super init];
if (self) {
thePointer = self;
self.delegate = (id)thePointer;
isInitialized = NO;
isClosing = NO;
[self set_currentSounds:[NSMutableArray arrayWithCapacity:0]];
}
return self;
}
#end
Can anyone see what I'm missing?
I think you should notify the delegate object like:
if([_delegate respondsToSelector:#selector(sound: didFinishPlaying:)])
[_delegate sound:self didFinishPlaying:_flag];
Hope this will help you.
Found the problem! When allocating the sound to be played, you have to set the sounds delegate using [theSnd setDelegate:self]; so that when the sound stops playing, the delegate gets called, in this case the delegate is in the MyClass .m file.

trying to implement [self.delegate.view addSubview:]

I am trying to make a reusable class that handles iAds.
In my .h file I do the following:
#import <iAd/iAd.h>
#protocol AdHelperDelegate;
#interface AdHelper:NSObject<ADBannerViewDelegate>
#property (strong) id<AdHelperDelegate> delegate;
#property (nonatomic, strong) ADBannerView *iAdBannerView;
...
#end
#protocol AdHelperDelegate;
#end
Then in my .m file I implement the iAd banner:
-(void)showBanner
{
self.iAdBannerView = [[ADBannerView alloc] initWithFrame:CGRectZero];
self.iAdBannerView.frame = CGRectOffset(self.iAdBannerView.frame, 0, 361);
self.iAdBannerView.requiredContentSizeIdentifiers = [NSSet setWithObject:ADBannerContentSizeIdentifierPortrait];
self.iAdBannerView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
self.iAdBannerView.delegate = self;
[self.delegate.view addSubview:self.iAdBannerView];
}
I of course also implement the delegate method -(void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
I am planing to call up the AdHelper in a UIViewController in my project
with something like:
AdHelper *ah = [[AdHelper alloc] init];
ah.delegate = self;
[ah showBanner];
Problem is that the compiler is saying: Property 'view' not found on object of type 'id<AdHelperDelegate>'
Is there a way for me to access the delegate's view?
You need to manually cast your view controller so that the compiler knows what kind of object you have:
[((MyViewController *)self.delegate).view addSubview:self.iAdBannerView];
You could also change the declaration of the view from id<AdHelperDelegate> to UIViewController<AdHelperDelegate>*, which would eliminate the need for casting in this case.
You need to cast the id to a UIViewController. The compiler has no way of knowing that id has a view property.
[((UIViewController *)self.delegate).view addSubview:self.iAdBannerView];

Objective-C: why a custom object will be a zombie

I'm developing an app in Objective-C using ARC.
My simplified code looks like this:
ClassA (.m)
MyCustomClass *obj = [[MyCustomClass alloc] initWithValue1:#"abc" value2:1000];
MyViewController *vc = [[MyViewController alloc] initWithObject:obj];
// "vc" will become the first item of a UITabBarController
MyViewController (.h)
- (id)initWithObject:(MyCustomClass *)obj {
...
localReferenceToOjbect = obj;
...
}
- (void)viewWillAppear:(BOOL)animated {
// do something with "localRefernceToObject" <---
}
launching the app will result in a call to a zombie: when the ViewController is shown, the "obj" will be already deallocated and so i can't use it anymore.
my workaround is:
ClassA (.h)
#interface ClassA : UIViewController {
MyCustomClass *obj;
}
ClassA (.m)
obj = [[MyCustomClass alloc] initWithValue1:#"abc" value2:1000];
MyViewController *vc = [[MyViewController alloc] initWithObject:obj];
// "vc" will become the first item of a UITabBarController
is this the right way?! i don't think so: why i've to store an istance of an object that is useless for ClassA?
i can't get an explanation on what's actually happening. could you help me?
You're right in the fact that it is not logical to keep around a reference to obj in ClassA.
But if you need to keep around the reference to obj for MyViewController to use it, retain it in MyViewController, not in ClassA, because that's MyViewController that will use it.
The easiest way to do this is to transform your localReferenceToObject you use in MyViewController into a #property(retain) propertyToObject; (or #property(strong) propertyToObject if you use ARC) and access it in your MyViewController.m with self.propertyToObject (instead of localReferenceToObject, to be sure to call the property's setter and thus really retain the object).
This way, the object will be retained and kept around while your MyViewController instance is still alive.
[EDIT] If you want this property to be private, you can declare it in the class extension so that it is not accessible from other classes, as in the below example. See here in Apple's documentation for more details.
In your MyViewController.h header file
#interface MyViewController : UIViewController
// Here you write the public API in the .h / public header
// If you don't want your property to be visible, don't declare it there
#end
In your MyViewController.m file
#interface MyViewController ()
// This is the private API, only visible inside the MyViewController.m file and not from other classes
// Note the "()" to declare the class extension, as explained in Apple doc
#property(nonatomic, retain) MyCustomClass* referenceToObject; // Note: use strong (which is a synonym of retain) if you use ARC
#end
#implementation MyViewController
#synthesize referenceToObject = _referenceToObject; // not even needed with modern ObjC and latest LLVM compiler
- (id)initWithObject:(MyCustomClass *)obj
{
self = [super init];
if (self) {
...
self.referenceToOjbect = obj;
...
}
return self;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// do something with "self.refernceToObject"
}
// This memory management code is only needed if you don't use ARC
-(void)dealloc
{
self.referenceToObject = nil; // release memory
[super dealloc];
}
Personally, as suggested by Apple in some WWDC sessions, I now really rarely use instance variables and prefer the use of properties instead, either public in the .h or private in the .m.
If you use ARC, you can still use an instance variable instead of a property as ARC will retain it for you, but as long as you make sure your instance variable is declared as strong and not weak.

Passing data between objects/threads in Cocoa

I create a new thread from a controller like this:
[NSThread detachNewThreadSelector:#selector(makeMovie) toTarget:movieMaker withObject:nil];
What is the best way to call methods on the controller from the new thread/movieMaker object?
In this case, you probably want to use the delegate pattern. In your movie-maker class’s .h file:
#protocol MovieMakerDelegate;
#interface MovieMaker : NSObject
{
id<MovieMakerDelegate> delegate;
...
}
#property (nonatomic, assign) id<MovieMakerDelegate> delegate;
...
#end
#protocol MovieMakerDelegate <NSObject>
- (void)movieMaker:(MovieMaker *)maker didSomething:(id)result;
#end
...and in its .m:
#implementation MovieMaker
#synthesize delegate;
...
- (void)makeMovie
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
...
[self performSelectorOnMainThread:#selector(notifyDelegateOfDoingSomethingWithObject:) withObject:someObject waitUntilDone:YES];
[pool release];
}
- (void)notifyDelegateOfDoingSomethingWithObject:(id)someObject
{
[self.delegate movieMaker:self didSomething:someObject];
}
...
#end
Then in your controller’s header, declare that it supports the MovieMakerDelegate protocol, like this:
#interface MyController : Whatever <MovieMakerDelegate>
and in your .m, before calling your -detachNewThreadSelector:etc:, call movieMaker.delegate = self;. Implement the -movieMaker:didSomething: method on your controller class and you’re good to go.
You may pass the controller instance to your makeMovie method, with the withObject parameter.
[NSThread detachNewThreadSelector:#selector(makeMovie) toTarget:movieMaker withObject:self];
You can also use a singleton-like pattern, if applicable, to retrieve your controller instance from the thread.
Use performSelectorOnMainThread:withObject:waitUntilDone: (or similar performSelector:... methods), it is the easiest way.

Singleton data out of scope problem

I am trying to pass data between the viewcontrollers of a uitabbarcontroller using a singleton class as below:
#import <Foundation/Foundation.h>
#interface AppSingleton : NSObject {
NSMutableString *selectedStr;
}
#property(nonatomic,retain) NSMutableString *selectedStr;
+(AppSingleton*) sharedAppInstance;
#end
Here is my implementation file:
#import "AppSingleton.h"
#implementation AppSingleton
#synthesize selectedStr;
+(AppSingleton*) sharedAppInstance{
static AppSingleton *sharedAppInstance;
#synchronized(self){
if(!sharedAppInstance){
sharedAppInstance = [[AppSingleton alloc] init];
}
}
return sharedAppInstance;
}
-(void)dealloc{
[selectedStr release];
[super dealloc];
}
#end
I try to set the selectedStr in one of my viewcontrollers as below and print it in the NSLog however I get a null:
AppSingleton *sharedAppInstance;//in the header
sharedAppInstance = [AppSingleton sharedAppInstance];//in viewdidload
[sharedAppInstance setSelectedStr:self.someStr];
NSLog(#"selectedStr is: %#", sharedAppInstance.selectedStr);
When I debug this, the sharedAppInstance.selectedStr seems to be out of scope.
I would like to know where I am making a mistake.
Thank you.
I changed the placing of the setting/getting of my variable within the viewcontroller and it worked..
[sharedAppInstance setSelectedStr:self.someStr];
NSLog(#"selectedStr is: %#", sharedAppInstance.selectedStr);