I am trying to call a method from a NSObject class from my AppDelegate. Usually this works if calling from a UIViewController but not having luck within the AppDelegate. My code:
AppDelegate.m
#import "ACManager.h"
#implementation AppDelegate {
ACManager *acManager;
}
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[acManager login];
}
ACManager.h
#interface ACManager : NSObject
-(void)login;
#end
ACManager.m
+(ACManager*)sharedInstance {
static ACManager *sharedInstance;
#synchronized(self) {
if (!sharedInstance) {
sharedInstance = [[self alloc]init];
}
}
return sharedInstance;
}
-(void)login
{
NSLog(#"login run");
}
#end
Any ideas thank you. Is there a different way around this when calling from the app delegate?
For the singleton you need to use:
[[ACManager sharedInstance] login];
or assign value to your variable:
acManager=[ACManager sharedInstance];
and then, call:
[acManager login];
You are saying:
[acManager login];
Thus, you are sending an instance message to acManager. But acManager is nil! You have forgotten to supply an actual ACManager instance and place it in that slot (assign it to the variable).
Thus, nothing happens.
Related
I have a DataHandler class which acts like a singleton, and it has sharedHandler object method. I use it throughout the whole project, but for some reason, I can't use it in AppDelegate.
DataHandler.h
#import <Foundation/Foundation.h>
#interface DataHandler : NSObject
+ (id)sharedHandler;
- (void)logout;
#end
DataHandler.m
#import "DataHandler.h"
/**
* Singleton static method
* #return singleton instance
*/
+ (id)sharedHandler {
static DataHandler *sharedHandler = nil;
#synchronized (self) {
if (sharedHandler == nil)
sharedHandler = [[self alloc] init];
}
return sharedHandler;
}
-(void) logout {
// ...
}
#end
AppDelegate.m
#import "AppDelegate.h"
#import "DataHandler.h"
#implementation AppDelegate {
- (void)applicationWillResignActive:(UIApplication *)application {
[[DataHandler sharedHandler] logout];
}
#end
I keep getting:
Error: no known class method for selector 'sharedHandler`
Error: no known instance method for selector 'logout'
What is the cause of this behavior?
You have two files named DataHandler.h and the import in AppDelegate.m is picking up the wrong file. Note that it may be picking up a file that's not actually in your project, as long as it's in the folder on disk.
Is it possible to call methods in the extension delegate from a other IntefaceController in general?
Something like:
InterfaceController *interfaceController =[[InterfaceController alloc] init];
interfaceController callMethod
My Interface Controller
#import "InterfaceController.h"
#import "OrdinaryEventRow.h"
#import <UIKit/UIKit.h>
#import <WatchConnectivity/WatchConnectivity.h>
#interface InterfaceController()
#implementation InterfaceController
- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
//Configure interface objects here.
-(void)doSomething {
[self presentControllerWithName:#"goalView" context:nil];
}
#end
ExtensionDelegate:
#import "ExtensionDelegate.h"
#import "InterfaceController.h"
#import <WatchConnectivity/WatchConnectivity.h>
#import "setGoal.h"
#implementation ExtensionDelegate
//Handle Local Notification Actions
-(void)handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UNNotification *)localNotification{
if([identifier isEqualToString:#"action"]){
//Setup WCSession
if ([WCSession isSupported]) {
[[WCSession defaultSession] setDelegate:self];
[[WCSession defaultSession] activateSession];
//Get the value from slider
NSString *someString = [[NSUserDefaults standardUserDefaults]
stringForKey:#"Update"];
NSString *Update = #"Update";
NSDictionary *applicationData = [[NSDictionary alloc] initWithObjects:#[Update] forKeys:#[#"Update"]];
//Send Message to the iPhone (handle over the goal value)
[[WCSession defaultSession] sendMessage:applicationData
replyHandler:^(NSDictionary *reply) {
//handle reply from iPhone app here
}
errorHandler:^(NSError *error) {
//catch any errors here
}
];
}
}
//If Goal Setting was clicked
if([identifier isEqualToString:#"action3"]){
//here I want to call doSomething from InterfaceController
}
}
So I just want to call a method defined in the InterfaceController from ExtensionDelegate.
There is not a way to init a WKInterfaceController from the ExtensionDelegate and call a method on it. If the controller you are trying to call a method is the root controller, you can get the rootController from the WKExtension in the ExtensionDelegate cast it and call a method on it.
// Objective-C
if ([WKExtension shared].rootController isKindOfClass:[InitialInterfaceController class]) {
(InitialInterfaceController *)[WKExtension shared].rootController customMethod];
}
// Swift
if let root = WKExtension.shared().rootInterfaceController as? InitialInterfaceController {
root.customMethod()
}
* My objective-c is a little rusty so if there is a syntax error there please update or let me know in the comments and I can edit.
From your code example, you are trying to do an action based on a local notification so the best thing to do is handle the notification in the Interface Controller itself. Depending on what watchOS you are using
watchOS 3
handleAction(withIdentifier:for:) reference
watchOS 2
handleAction(withIdentifier:for:) reference
Important note here for these methods to be called your extension delegate does not implement the handleAction(withIdentifier:for:) method, WatchKit calls this method on your app’s root interface controller to respond to button taps in your notification interface.
I have one class and one view controller. class has _delegate respondsToSelector:selector. But it is not calling the method(selector). After viewing my code below, would you please tell what am I doing wrong. FYI, This code worked before, but suddenly stopped working.
MyClass.h:
#protocol MyClassDelegate <NSObject>
#optional
-(void) receivedEvent:(TripEvent *) event;
#end
#interface MyClass : NSObject<MyClassEngine>
#property(assign) id<MyClassDelegate> delegate;
#property BOOL delegateOnMainThread;
-(id) initWithDelegate:(id<UbiTripRecorderDelegate>) tripDelegate
onMainThread:(BOOL) onMainThread;
- (void) dispatchDelegate:(SEL)selector
withObject:(id)obj;
MyClass.m contains the following code:
#import "MyClass.h"
#implementation MyClass
....
....
-(void) startPlaying {
[self dispatchDelegate:#selector(receivedEvent:) withObject:newEvent];
}
- (void) dispatchDelegate:(SEL)selector withObject:(id)obj {
#try {
if(_delegate && [_delegate respondsToSelector:selector]) {
NSLog(#"I can't come to this point");
}
}
}
I've also added the following code in my view controller (MyViewController.h):
#interface MyViewController : BaseViewController<MyClassDelegate>
And finally implemented the method in MyViewcontroller.m :
-(void) receivedEvent : (TripEvent *) event {
NSLog(#"I'm called");
}
The problem is that the if(_delegate && [_delegate respondsToSelector:selector]) - logic never return true. Can anybody please check the code and let me know, if anything is wrong with my code?
Make sure your _delegate is not nil, otherwise the if statement is never true.
Also you can simplify
if(_delegate && [_delegate respondsToSelector:selector])
to
if([_delegate respondsToSelector:selector])
because message send to nil always return 0 or NO. In this case [_delegate respondsToSelector:selector] will return NO if _delegate is nil
Also, you did not declare a method in header will not cause any runtime difference. It may have compiler warning/error if such method not found.
VC1.m contains the following code after a process completes.
if (self.iboard>0) {
countIsNil = TRUE;
}
I want another VC, say VC2.m to include the following code.
- (void)viewDidLoad
{
if (countIsNil)
{
countIsNil = FALSE;
count.text=#"1";
return;
}
[super viewDidLoad];
}
How do I construct/manage the BOOL countIsNil so that this works? I suspect the answer involves using static variables, but I have no examples of such.
There are two solutions:
You need to make a property for this variable.
You can maintain using NSUserDefaults class.
Example for NSUserDefaults, written in VC1:
[[NSUserDefaults standardUserDefaults]setBool:YES forKey:#"countIsNil"]
[[NSUserDefaults standardUserDefaults] synchronize];
Write in VC2:
- (void)viewDidLoad
{
if ([NSUserDefaults standardUserDefaults] valueForKey:#"countIsNil"])
{
countIsNil = FALSE;
count.text=#"1";
return;
}
[super viewDidLoad];
}
Just take your BOOL variable globally i mean to say that take it in AppDelegate file, set its properties and synthesize it,
Now you can pass value in this variable from any class and retrieve it from any where.. here is example:
// AppDelegate.h
#interface AppDelegate : UIResponder <UIApplicationDelegate>{
BOOL countIsNil;
}
#property(readwrite)BOOL countIsNil;
#end
// AppDelegate.m
#implementation AppDelegate
#synthesize countIsNil
I have tried using a singleton class in my app delegate but I haven't been able to get that to work. I've also checked out the iAdSuite examples (particularly the containerBanner example because it seemed to be the most relative) but I can't figure it out. If there's a better way to accomplish this without using a singleton class and you can point me in the right direction I'd really appreciate it. Some of my singleton class code is below. Thank you!
#interface App Delegate
#property (assign) iAdController *iadc;
+ (AppDelegate*) sharedApplication;
- (iAdController*)sharedAd;
#end
#implementation AppDelegate
#synthesize iadc;
+ (AppDelegate*) sharedApplication
{
return [[UIApplication sharedApplication] delegate];
}
-(iAdController*)sharedAd
{
if(iadc==nil){
iadc=[iAdController new];
}
return iadc;
}
#interface ViewController
iAdController*iadc=[[AppDelegate sharedApplication] sharedAd];
//here i get an error saying, "initializer element is not a compile-time constant.
Everything is imported correctly. If there's anything else I should post let me know.
try changing your singleton creation to this:
+ (LocationManagerSingleton*)sharedInstance {
static LocationManagerSingleton *_sharedInstance;
if(!_sharedInstance) {
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedInstance = [[super allocWithZone:nil] init];
});
}
return _sharedInstance;
}
+ (id)allocWithZone:(NSZone *)zone {
return [self sharedInstance];
}
- (id)copyWithZone:(NSZone *)zone {
return self;
}
- (id)init
{
self = [super init];
if (self != nil)
{
// PERFORM any custom initialization here
}
return self;
}
Obviously change the name of the class.
Whenever you want to use your singleton in any of your viewcontrollers just call it like this:
locationManager = [LocationManagerSingleton sharedInstance];
Dont forget to add
+ (LocationManagerSingleton*) sharedInstance;
on the header.
EDIT
well it seems i misunderstood your code (forget my answer, you simply want to be able to access your iAdController from everywhere. so just place
Add inside the .m of the ViewController
#interface ViewController()
{
iAdController *iadc;
}
And inside the
-(void)viewDidLoad
{
iadc=[[AppDelegate sharedApplication] sharedAd];
}
but import the app delegate.h on whichever viewcontroller you want to use it in.
#import "AppDelegate.h"
also there shouldnt be a space in the AppDelegate on the #interface