How can I call the one method in all the view controllers? - iphone

How can I call the one method in all the view controllers?
One method in viewcontroller1 like,
- (void)doSearch
{
NSLog(#"Search..!");
}
I want to call doSearch method from viewcontroller2, viewcontroller3, viewcontroller4, viewcontroller5, etc.
How to do this?

You can declare it in separate class and instantiate that class in all viewControllers, or you could define this method in your AppDelegate and call in all your viewController. you could access the AppDelegate in your ViewControllers by getting its instance like this
self.appDelegate=(AppDelegate*)[[UIApplication sharedApplication]delegate];
and finally call the method like this
[self.appDelegate doSearch];
Generally it is preferable to declare all your methods or data which is shared through the application in a separate class and use this class. I usually use singelton Object class in my application, define all the shared data in that and finally access in all classes
here is example of singelton class
MyData.h
#interface MyData : NSObject
+(MyData*)getInstance;
-(void)search;
#end
MyData.m
#import "MyData.h"
#implementation MyData
static MyData *instance =nil;
+(MyData *)getInstance
{
#synchronized(self)
{
if(instance==nil)
{
instance= [[MyData alloc]init];
}
}
return instance;
}
-(void)search {
NSLog(#"search");
}
#end
finally in your viewController
MyData *myData=[MyData getInstance];
[myData search];

You can declare this method in AppDelegate.h. like
- (void)doSearch;
And Implement it in AppDelegate.m like
- (void)doSearch
{
//Your Search Logic
}
Then, Create AppDelegate instance like
appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
Make Your Project's .pch file look like following:
#ifdef __OBJC__
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
AppDelegate *appDelegate;
#endif
Now, From Any ViewController, You can call method like:
[appDelegate doSearch];
Happy Coding.
NOTE: Personally, I avoid this kind of implementation in AppDelegate Class.
I use Singleton Object Pattern for this kind of purpose. But, Given is the quickest way.
___________EDIT____________
Add a New Class file of NSObject type: Name it CommonMethod (or whatever you want)
in CommonMethod.h
#interface CommonMethods : NSObject
+ (CommonMethods *)sharedObject;
+ (void)doSearch;
in CommonMethod.m
#import "CommonMethods.h"
#implementation CommonMethods
+ (CommonMethods *)sharedObject
{
static dispatch_once_t once;
static CommonMethods *sharedObject;
dispatch_once(&once, ^ { sharedObject = [[CommonMethods alloc] init]; });
return sharedObject;
}
+ (BOOL)doSearch
{
// Your Search Logic.
}
Now, Add #import "CommonMethods.h" to your project's .pch file.
And You are all set to go...!!!
Method Call (in any of your viewController): [CommonMethods doSearch];

Put all controllers in an NSArray *, lets say it is called controllerArray.
Then you can make all controllers perform selector with:
[controllerArray makeObjectsPerformSelector:#selector(doSearch)];

Add your method to AppDelegate.m file
- (void)doSearch
{
NSLog(#"Search..!");
}
And Add #import "AppDelegate.h" In UIViewController that you want to call :
You can call method by,
AppDelegate *del = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[del performSelector:#selector(doSearch) withObject:nil afterDelay:0];
From Any UIViewController

You may like to read below tutorial
Global functions and variables in Objective C
or You can create methods in the appDelegate class that you can access through all your app. For example, in your AppDelegate.h you have declared this method as follow:
-(void)myMethod;
In your AppDelegate.m, you define it as:
-(void)myMethod
{
NSLog(#"myMethod is getting called");
}
From any other classes (Master or Detail, etc.), you access myMethod by:
#import "AppDelegate.h"
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate myMethod];

The best way to make AbstractViewController and inside it add all your common behaviors or methods. Any ViewController will inherits from the Abstract and can call any common Method

The best way is to make a separate header file make this method a class method and you can call this anywhere in the project by importing the class.And you can include this class into your pch file so that import can be avoided from all VCs
class.h
+ (void)doSearch
{
NSLog(#"Search..!");
}
in ViewControllers
#import "class.h"
-(void)someMethod
{
[class doSearch];
}

Related

Objective-C: Change an image from a separate class

I have looked around for an answer to this with no avail, so I hope I am not asking an answered question.
I have two classes (ClassA and ClassB), both connected to UIViewControllers that are linked via a segue. ClassA contains a UIImage named backgroundImage. My goal is to change ClassA's background image from within ClassB.
In ClassB.h I have tried:
#property (nonatomic, retain) ClassA *mainView;
And in ClassB.m I tried changing the background image via:
#synthesize mainView;
//Then inside button click I tried:
[mainView.backgroundImage setImage:[UIImage imageNamed:#"newImage.jpg"]];
Obviously this did not work since I am not setting the image to the same ClassA that is being used in the app.
I know I'm missing something obvious, thanks in advance!
Please use the Protocol mechanism to satisfy your requirements
Implementation is as bellow
In AppDelegate.h file of project
#protocol ImageChangeDelegate <NSObject>
#optional
-(void)ChangeImage;
#end
#interface AppDelegate : UIResponder <UIApplicationDelegate>
{
}
#property (nonatomic,strong) id<ImageChangeDelegate> delegateImageChange;
In AppDelegate.m file of project
#synthesize delegateImageChange;
Now In .h file of Class B
#import "AppDelegate.h"
#interface EventGuestListViewController : UIViewController
{
AppDelegate* appDelegate;
}
-(void)ChangeBackgroundOfClassA;
Now In .m file of Class B
- (void)viewDidLoad
{
[super viewDidLoad];
appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
}
Now in method of changing BGs
-(void)ChangeBackgroundOfClassA
{
[appDelegate.delegateImageChange ChangeImage];
}
Now Implements the Protocol in Class A to change the Background.
Now In .h file of Class A
#import "AppDelegate.h"
#interface EventGuestListViewController : UIViewController <ImageChangeDelegate>
{
IBOutlet UIImageView* imageBGClassA;
AppDelegate* appDelegate;
}
Now In .m file of Class A
- (void)viewDidLoad
{
[super viewDidLoad];
appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.delegateImageChange = self; //Here you need to set the delegate to 'self' to call then Custom Protocol method
}
-(void)ChangeImage
{
imageBGClassA.image = [UIImage imageNamed:#"newImage.jpg"];
}
In Class B once -(void)ChangeBackgroundOfClassA call the delegate method call which is implement on Class A and the background Image will surly change
This is work with me
It may help you !!!
Use the same "mainView" instance of ClassA to navigate to ClassA View Controller.
Should try out delegate mechanism.It will allow you to call a method in classA from classB.
In that method change the background image of classA from classB's call to delegate
You can try any of two ways:
1) Using the delegation. Passing the delegate while loading ClassB.
2) Using the NotificationCenter and change the mainView Image by calling the notification from Class B.
Harry.
You can do this task easily using Custom Delegates or Notifications . I will explain it to you using Notification . Let there be two classes - Class-A & Class-B
In the Class-A add a Notification like this
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(changeImage)
name:#"ImageChangeNotification"
object:nil];
also create the selector in the Class-A
-(void)changeImage
{
[yourImageView setImage:[UIImage imageNamed:#"YouImageName.png"]];
}
What left is just to post this Notification from anywhere within the whole project . In our case let it be Class-B
[[NSNotificationCenter defaultCenter] postNotificationName:#"ImageChangeNotification" object:nil];

Does categories allow to use dot syntax when accessing chained methods?

I need to attach a method to all my UIViewControllers. The method just returns a pointer to my main app delegate class object. However, xcode 4 throws an error "parse issue expected a type" in header file at the declaration of output parameter type MyAppDelegate. If I change it to the other type, for example id, then the error goes away. But I'm using a dot syntax to access main app delegate properties and if I will change the type to id then xcode4 not recognize my main app delegate properties. I have included the definition file of category to those UIViewController class files where I'm accessing this method. Here is definition of my category:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "MyAppDelegate.h"
#interface UIViewController (MyCategory)
-(MyAppDelegate *) appDelegate; // xcode 4 complains about MyAppDelegate type, though it autocompletes it and show even in green color.
#end
Here is an implementation:
#import "MyCategory.h"
#implementation UIViewController (MyCategory)
-(MyAppDelegate *)appDelegate{
MyAppDelegate *delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
return delegate;
}
EDIT: The reason why I'm implementing this category is that I need to have handy shortcut for accessing my main app delegate from any place of the code (in my case from UIViewControler objects):
// handy shortcut :)
self.appDelegate.someMethod;
//not so handy shortcut :(
MyAppDelegate *delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
I think you have a dependency cycle in your header files. If MyAppDelegate.h imports MyCategory.h either directly or indirectly, the first time the category declaration is compiled the compiler won't know what a MyAppDelegate is. You should remove the import of MyAppDelegate.h from the MyCategory.h header and replace it with a forward class declaration:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#class MyAppDelegate
#interface UIViewController (MyCategory)
-(MyAppDelegate *) appDelegate;
#end
Then put the import in the .m file instead. This is actually a good general principle. Where possible, use forward class declarations in the headers and put imports in the implementation file.
-(id)appDelegate{
return [[UIApplication sharedApplication] delegate];
}
//Calling code
MyAppDelegate* delegate = (MyAppDelegate*)[self appDelegate];
Add #class MyAppDelegate; to the top of your category header to let the compiler know that this class exists or #import its header.
Generally, it might be a better idea to have a class method in MyAppDelegate that does the same thing. Conceptually, appDelegate is not a property of an individual view controller which your method implies.

sharing Data between a UIViewController and a UIViewController in UITabBarController xcode

I know how to do for share data between 2 views. But if I want to share data using a tabBarController I'm lost.
This is my IBAction to move to my tabBar.
-(IBAction)goToPage2:(id)sender
{
tabController.modalTransitionStyle=UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:tabController animated:YES];
}
i need to share my NSString *dataStr in my IBAction in the first view of my tabBar.
firstView *first = [[firstView alloc] initWithNibName:#"firstView" bundle:nil];
first.dataStr = name.text;
[tabController presentModalViewController:first animated:YES];
this code doesn't work.
thx
Declare a #property in your app delegate. And you can access your app delegate from any point of your app.
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication ]delegate]
I agree with what Terente suggested. But I recommend you should use a Data Class in this case. Using a property in Appdelegate is not a good practice. You should always use Data Class for this.
You create a Data class as follows:
You need to create a Data class where you can set the properties of variables or in your case arrays (for displaying data in UITableView). Implement a class method in data class which checks that object has been instantiated or not. If not, it does that. It is something like this :
//DataClass.h
#interface DataClass : NSObject {
NSMutableArray *nameArray;
NSMutableArray *placeArray;
}
#property(nonatomic,retain)NSMutableArray *nameArray;
#property(nonatomic,retain)NSMutableArray *placeArray;
+(DataClass*)getInstance;
#end
//DataClass.m
#implementation DataClass
#synthesize nameArray;
#synthesize placeArray;
static DataClass *instance =nil;
+(DataClass *)getInstance
{
#synchronized(self)
{
if(instance==nil)
{
instance= [DataClass new];
}
}
return instance;
}
Now in your view controller you need to call this method as :
DataClass *obj=[DataClass getInstance];
And use the arrays.
This way you can assign data without disturbing AppDelegate, which is a good practice.
I wrote a lengthy tutorial about such issues on my blog: http://www.hollance.com/2011/04/making-your-classes-talk-to-each-other-part-1/
You need to figure out a clean way to let your controllers communicate with each other. My tutorial explains several ways to do this and what the advantages and downsides are of each approach. It's worth learning how to do this, because this issue comes up in almost any app you will write.

need to define a "modifiable" global variable in objective-c

I have the following issue. I have two classes that manipulate information but they are completely disconnected, i.e. I can't reach the other class.
I need both classes to use a certain value. For example, class A sets the value foo = A and class B needs to be able to read that value and rest foo to nil.
I thought about creating the variable in the main app delegate, but can't figure out how.
Ideas?!!
Global variables are generally bad idea. Based on your description i think you can use KVO to inform class B about the changes in 'foo'.
But if you relly need a global variable you can do this:
#interface YourAppDelegate : NSObject <UIApplicationDelegate> {
}
#property (nonatomic) NSString *foo;
#end
#implementation YourAppDelegate
#synthesize foo;
...
#end
#implementation ClassA
...
- (void)someMethod {
YourAppDelegate *appDelegate = (YourAppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.foo = #"NewValueOfFoo";
}
...
#end
#implementation ClassB
...
- (void)otherMethod {
YourAppDelegate *appDelegate = (YourAppDelegate *)[[UIApplication sharedApplication] delegate];
NSLog(#"Value of foo: %#", appDelegate.foo); //This will print: "Value of foo: NewValueOfFoo"
}
...
#end
I'm not sure what you mean by "completely disconnected". Depending on what you're trying to do, you could use NSUserDefaults
http://developer.apple.com/library/ios/#documentation/cocoa/reference/foundation/Classes/NSUserDefaults_Class/Reference/Reference.html
or NSNotifications
http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSNotification_Class/Reference/Reference.html
If class A doesn't need to know about class B, you could consider delegation as well.
Why can't he just do this?
A. Add 2 new files to your project: GlobalValues.h and GloblaValues.m.
B. Open GlobalValues.h, and declare all your needed variables.
extern NSString *MyServiceName; // name of the 'service':
C. Open GlobalValues.m, and start the new file by importing GlobalValues.h, and assign values to the variables you declared in the header file:
#import "GlobalValues.h"
NSString *MyServiceName = #"MyService is called THIS";
D. In the implementation files of the classes that need to use these variables, you would put - at the very beginning:
#import "GlobalValues.h"

Short hand for [[UIApplication sharedApplication] delegate]?

I stored global variables in my AppDelegate and access them by:
AppDelegate *d = [[UIApplication sharedApplication] delegate];
d.someString = ...
What's the recommend way to save some typing and so I don't need to AppDelegate *d = [[UIApplication sharedApplication] delegate]; again and again? Thanks!
As Shaggy Frog said, define a macro in your YourAppDelegate.h file, an example like this:
#define AppDelegate (YourAppDelegate *)[[UIApplication sharedApplication] delegate]
Then you can get the app delegate in your code like this:
[AppDelegate ......];
Since your app delegate never really changes, you can create an external that you define in the app delegate code, very similar to the NSApp external for Mac OS X Cocoa applications.
So, define the external in your AppDelegate header (or something else that you would include everywhere):
extern AppDelegate* appDelegate;
Then create it and set it in your implementation file:
AppDelegate* appDelegate = nil;
// later -- i can't recall the actual method name, but you get the idea
- (BOOL)applicationDidFinishLaunchingWithOptions:(NSDictionary*)options
{
appDelegate = self;
// do other stuff
return YES;
}
Then other classes can just access it:
#import "AppDelegate.h"
// later
- (void)doSomethingGreat
{
NSDictionary* mySettings = [appDelegate settings];
if( [[mySettings objectForKey:#"stupidOptionSet"] boolValue] ) {
// do something stupid
}
}
You could just create a C-style macro and put it in a header file somewhere.
(As for using your app delegate as a giant global variable catch-all, that's another rant for another day.)
I create a category called UIApplication+delegate with some convenience messages in it. Getting my specific delegate being one of the convenience messages. So, for instance, if my app delegate was called MyAppDelegate, it would look like this:
UIApplication+delegate.h
#import "MyAppDelegate.h"
#interface UIApplication(delegate)
+ (MyAppDelegate *)thisApp;
#end
and UIApplication+delegate.m
#import "UIApplication+delegate.h"
#implementation UIApplication(delegate)
+ (MyAppDelegate *)thisApp {
return (MyAppDelegate*)[[UIApplication sharedApplication] delegate];
}
#end
In a class that needs the delegate, I do this:
#import "UIApplication+delegate.h"
...
- (void)doStuff {
MyAppDelegate *app = [UIApplication thisApp];
// use "app"
}
I also created a category, except that I applied mine to NSObject so any object in the application can easily get to the delegate.
#import "MyAppDelegate.h"
#interface NSObject(delegate)
- (MyAppDelegate *) appDelegate;
#end
#import "NSObject+delegate.h"
#implementation UIApplication(delegate)
- (MyAppDelegate *)appDelegate {
return (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
}
#end