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
Related
Following is my code, there is no error but selector is not responding.
Code in ExampleTableviewSubProductDetail.h
#protocol EnterAmountDelegate <NSObject>
-(void)titlechange:(NSInteger)amount;
#end
#class ASIFormDataRequest;
#interface ExampleTableviewSubProductDetail : UIViewController<UIScrollViewDelegate>
{
}
#property (nonatomic, strong) id <EnterAmountDelegate>delegate;
Code in ExampleTableviewSubProductDetail.m
#implementation ExampleTableviewSubProductDetail
#synthesize delegate;
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if([delegate respondsToSelector:#selector(titlechange:)])
{
//send the delegate function with the amount entered by the user
[delegate titlechange:20];
}
code in HostProductdetailViewController.h
#import "ViewPagerController.h"
#import "ExampleTableviewSubProductDetail.h"
#interface HostProductdetailViewController : ViewPagerController <ViewPagerDataSource, ViewPagerDelegate, EnterAmountDelegate>
{
}
code in HostProductdetailViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.dataSource = self;
self.delegate = self;
}
-(void)titlechange:(NSInteger)amount
{
NSLog(#"sdfsf");
}
In the viewwillapper following Line always return false
if([delegate respondsToSelector:#selector(titlechange:)])
Please let me know if i am missing anything.
Thanks
When pushing from HostProductdetailViewController to ExampleTableviewSubProductDetail you need to set the exampleTableviewSubProductDetail.delegate = self
As I see some other potentially dangerous things in your code try checking this example. It consists of 2 simple classes which are connected via delegate. Watch out for strong references on delegates as this code of yours will produce a retain cycle and cause a memory leak.
Protocol:
// defining a custom protocol
#protocol PingProtocol <NSObject>
- (void)didPing;
#end
Ping class:
//
// This class will be able to send notifications via delegate for the protocol PingProtocol
// Any object that implements PingProtocol will be able to assign itself to the delegate property and will be notified to all protocol methods
//
#interface PingClass : NSObject
// The listener object that implements PingProtocol
// Note this should be weak or there will a retain cycle
#property (nonatomic, weak) id<PingProtocol> delegate;
#end
#implementation PingClass
// Some event that happens will check if the delegate actually implements this method and call it.
// The respondsToSelector is not necessary in this case since the method is not optional though.
- (void)onEvent:(id)sender
{
if([self.delegate respondsToSelector:#selector(didPing)])
{
[self.delegate didPing];
}
}
// Will create a timer which will call onEvent: every second.
// Note there should be some way to invalidate the timer as this will cause a memory leak for the PingClass
- (void)startPing
{
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(onEvent:) userInfo:nil repeats:YES];
}
#end
Listener:
//
// This class will listen to PingProtocol methods.
// It will need to implement all non-optional methods defined by PingProtocol
//
#interface ListenerClass : NSObject<PingProtocol>
#property (nonatomic, strong) PingClass *someClass;
#end
#implementation ListenerClass
// will create a PingClass object and asign itself as a delegate to start listening to delegate methods
- (void)startListening
{
self.someClass = [[PingClass alloc] init];
self.someClass.delegate = self;
[self.someClass startPing];
}
// A protocol method
- (void)didPing
{
NSLog(#"Ping");
}
#end
Most likely you are missing self:
if([self.delegate respondsToSelector:#selector(titlechange:)])
You need to watch out for these things. The delegate in your case is closer to a function pointer then an actual object. You might also be able access it via _delegate as well.
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.
I have a procedure that I'll need in a lot (if not all) of my view controllers. I want to know how I can put it in one place (for code cleanliness and maintenance) and utilize it elsewhere.
There are more ways on how to approach this - depending on what exactly you would like to achieve.
If this methods are tied with UIViewController's life and data you would probably want to subclass UIViewController or make an UIViewController category.
A: Subclassing (you want to add some custom properties, variables, methods or you want to override a method):
MySubclassedViewController.h
#import <UIKit/UIKit.h>
#interface MySubclassedViewController : UIViewController
#property (copy) NSString *myVerySpecialString;
-(void) myVerySpecialMethod;
#end
MySubclassedViewController.m
#import "MySubclassedViewController.h"
#implementation MySubclassedViewController
-(void) initialization
{
self.myVerySpecialString = #"initialized";
}
- (id)initWithCoder:(NSCoder*)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
[self initialization];
}
return self;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
[self initialization];
}
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
[self initialization];
}
return self;
}
-(void) viewDidLoad
{
[super viewDidLoad];
[self myVerySpecialMethod];
}
-(void) myVerySpecialMethod
{
if ([self.myVerySpecialString isEqualToString: #"initialized"])
{
self.backgroundColor = [UIColor yellowColor];
}
}
#end
B: Category (you just want to add some extra method to a class):
UIViewController+SpecialCatrgory.h
#import <UIKit/UIKit.h>
#interface UIViewController (SpecialCategory)
-(void) myVerySpecialMethod;
#end
UIViewController+SpecialCatrgory.m
#import "UIViewController+SpecialCatrgory.h"
#implementation UIViewController (SpecialCategory)
-(void) myVerySpecialMethod
{
self.backgroundColor = [UIColor yellowColor];
}
#end
C: Dedicated helper class
On the other hand if you find yourself using some independent method on more than one place you might
want to consider writing up a helper class and use it as a singleton.
MyHelperClass.h
#interface MyHelperClass : NSObject
+ (instancetype)sharedHelper;
-(NSString *) myVerySpecialMethod;
#end
MyHelperClass.m
#import "MyHelperClass.h"
#implementation MyHelperClass
+ (instancetype)sharedHelper
{
static MyHelperClass *_sharedHelper = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedHelper = [[MAConnectionClient alloc] init];
});
return _sharedHelper;
}
-(NSString *) myVerySpecialMethod
{
return #"a result from your very special method";
}
#end
You use it simply by importing MyHelperClass.h (or putting it in -Prefix.pch), without explicitly creating an instance. For example:
NSString *someString = [[MyHelperClass sharedHelper] myVerySpecialMethod];
There are many ways to achieve this.
Create a base viewcontroller and add your procedure. Subclass this in all your view controller.
Create a common utility class and add your procedure and make it as a class method.
Add your procedure in .pch file.
We have many ways to do it but in general create one global class, import it in YourProjectName-Prefix.pch file.
We can also go for another way i.e create any class method and you can call it anywhere through it's Class Name.
One example, you might have seen many times in your code-
:
In appDelegate.h file, if we make this method and implement it in appDelegate.m file then
+ (NSString *)applicationDocumentDir
{
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
then we can access it from anywhere in the code like :
NSString *strTemp = [AppDelegate applicationDocumentDir];
To know more better way have a look here.
Use of a singleton for creating a basic style helper class
If you're not sure that the method will be used in all Controllers, I'd recommend creating a category for the functionality you're adding. You can find a good intro to categories here.
If you're sure you'll need it in all UIViewControllers, creating a base Controller and subclassing should be the better approach.
All other methods of implementing (Placing a class method in a utility / Adding to *-Prefix.pch) will work, but might not be ideal solutions (assuming the functionality your're adding is only applicable to UIViewController).
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
I think that I am a bit confused about iOS #property getter and setters. I am trying to set an NSString iVar in my AppDelegate.h file from another class so that it can be used by all of the classes in the project?
For example, I am working on an iPhone project that stores an iVar NSString *currentUser in AppDelegate.h. I need to be able to set this through one method in a ViewController.m and then get it through another method in a second ViewController?
Maybe Getter and Setter is the wrong direction of attack all together? I understand that i don't want to alloc init the AppDelegate as the iVar will only exist in that object and I want it accessible to ALL objects in ALL classes?
Please someone set me straight.
All the best,
Darren
Here's the setup for the app delegate.
#interface AppDelegate
{
NSString *__currentUser;
}
#property (monatomic, copy) NSString* currentUser;
#end
#implementation AppDelegate
#synthesize currentUser = __currentUser;
- (void) dealloc
{
[__currentUser release];
[super dealloc];
}
#end
From one view controller, you could set a value for the current user, and from a subsequent view controller, get that value for some nefarious purpose.
#implementation LoginController
- (void) viewDidLoad
{
...
AppDelegate *bob = [[UIApplication sharedApplication] delegate];
[bob setCurrentUser: #"Jim Kirk"];
...
}
#end
In some other view controller that appears later, the value of the current user can be accessed.
#implementation ProfileViewController
- (void) viewDidLoad
{
...
AppDelegate *bob = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSString * user = [bob currentUser];
// insert nefarious purpose for current user value here
...
}
#end