I have class A, B and C with 2 methods in all 3 classes.
class A
- (void)onSuccess {
}
- (void)onFailure {
}
Then one CommonClass is there in which I’ll be doing some task. If class A is presenting CommonClass and after performing all the tasks I have to call either onSuccess() or onFailure() implemented in class A.
Which is the best way to do this, and how? In Java it's done by extend or abstract I guess.
You can create a protocol class like this. This has only a .h file
#protocol RequestProtocolDelegate <NSObject>
#optional
- (void)onSuccess;
- (void)onFailure;
#end
and to use it in your class like this
file .h
#include "RequestProtocolDelegate.h"
#interface CommonClass : NSObject <RequestProtocolDelegate> {
}
#end
file .m
- (void)onSuccess {
}
- (void)onFailure {
}
Now you can use in your CommonClass this protocol
If I understood you correctly then it should be done with delegation. For exam:
//CommonClass.h
#protocol CommonDelegate <NSObject>
// list protocol methods...
- (void)onSuccess;
- (void)onFailure;
#optional
#interface CommonClass : NSObject
#property (nonatomic, strong) id delegate;
-(void)Task;
#end
//CommonClass.m
#import "CommonClass.h"
#synthesize delegate;
-(void)Task
{
if(do smth task){
[delegate onSuccess];
}
else{
[delegate onFailure]
}
}
// ClassA.h
#import "CommonClass.h"
#interface ClassA : NSObject <CommonClassDelegate>
#end
// ClassA.m
-(void)init
{
CommonClass *common = [[CommonClass alloc] init];
common.delegate = self;
[common Task];
}
- (void)onSuccess
{
// do smth
}
- (void)onFailure
{
// do smth
}
... Do the same for class B and C
Related
Suppose I am creating a static library and in which I have two NSObject Classes Named as ClassA and ClassB, User can Access ClassA.h to execute the functions inside library. Now I've some functions defined into ClassB and I want user to execute these functions from their ViewController as per their need but I don't want to give ClassB.h to user so how user can access it using ClassA.
ClassA.h
#import <Foundation/Foundation.h>
#interface ClassA : NSObject
+ (void) method_1;
+ (void) method_2;
+ (void) method_3;
// Tried to pass Instance of ClassB to user ViewController
+ (id) getClassBInstanceObject;
#end
ClassA.m
#import "ClassA.h"
#import "ClassB.h"
#implementation ClassA
+ (void) method_1 {
//Some Stuffs Done Here !!
}
+ (void) method_2 {
//Some Stuffs Done Here !!
}
+ (void) method_3 {
//Some Stuffs Done Here !!
}
// Tried to pass Instance of ClassB to user ViewController
+ (id) getClassBInstanceObject {
id objB = [ClassB sharedInstance];
return objB;
}
#end
ClassB.h
#import <Foundation/Foundation.h>
#interface ClassB : NSObject
+ (id)sharedInstance;
-(void)Test_ClassB_function;
#end
ClassB.m
#import "ClassB.h"
#implementation ClassB
+ (id)sharedInstance {
static ClassB *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
});
return instance;
}
-(void)Test_ClassB_function {
NSLog(#"this is the method called from ClassB !!!!");
}
#end
Now User Have a Static library FAT (lib.a) file and ClassA.h File Which He'll include in his project and then he can import ClassA.h into his ViewController Class to execute library functions and user wants to execute Test_ClassB_function using ClassA.
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#end
ViewController.m
#import "ViewController.h"
#import "ClassA.h"
#interface ViewController ()
#end
#implementation ViewController
override func viewDidLoad() {
super.viewDidLoad()
[ClassA method_1];
[ClassA method_2];
[ClassA method_3];
}
- (IBAction)Button1:(id)sender {
id class_B_Object = [ClassA getClassBInstanceObject];
[class_B_Object Test_ClassB_function];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Can anybody tell me how to achieve this goal in Objective-C.
Maybe try
In ClassA.h
+ (void) testClassBFunctionFromClassA;
In ClassA.m
+ (void) testClassBFunctionFromClassA{
[[ClassB sharedInstance] Test_ClassB_function];
}
In ViewController.m
- (IBAction)Button1:(id)sender {
[ClassA testClassBFunctionFromClassA];
}
I understand how to make a class conform to several protocols, but where and how do I define a protocol that will be called by several classes, i.e.
_delegate.doStuff
could appear in several classes.
In xcode,
File-> New File-> Objective-c Protocol
#protocol myProtocolName
- (void) doStuff;
#end
then in classes you want to implement this protocol
...
#import "myProtocol.h"
#interface aClass <myProtocolName>
...
You can add this to any number of classes.
Just make a new protocol definition -- usually in a nicely #import'able .h file. In Xcode, this is under File, New, "Objective-C Protocol".
Here's a fun little example of two protocols, and some required and optional methods and properties. Note that properties on protocols must be synthesized in classes that conform to the protocol if the property is #required (#required is the default, so it can be left out if there is not #optional section).
// AnimalMinionType.h
#protocol AnimalMinionType <NSObject>
#required
#property (nonatomic, getter = isHerbivore) BOOL herbivore;
- (NSString *)genus;
- (NSString *)species;
- (NSString *)nickname;
- (void)doPet;
#optional
- (NSString *)subspecies;
#end
// IdiotType.h
#protocol IdiotType <NSObject>
#optional
- (void)pet:(id<AnimalMinionType>)pet didScratch:(BOOL)scratchy;
#end
// FluffyCat.h
#interface FluffyCat : NSObject <AnimalType>
#end
// FluffyCat.m
#implementation FluffyCat
#synthesize herbivore;
- (NSString *)genus { return #"felis"; }
- (NSString *)species { return #"catus"; }
- (NSString *)nickname { return #"damn cat"; }
- (void)doPet:(id<IdiotType>)anyoneOrAnything
{
NSLog(#"meow");
if ([anyoneOrAnything respondsToSelector:#selector(pet:didScratch:)])
[anyoneOrAnything pet:self didScratch:#YES];
}
#end
// Owner.h
#interface Owner : NSObject <IdiotType>
#property id<AnimalMinionType> housepet;
#end
// Owner.m
#implementation Owner
- (id)init
{
self = [super init];
if (self)
{
self.housepet = [FluffyCat new];
[self.housepet setHerbivore:#NO];
}
return self;
}
- (NSString *)ohACuteAnimalWhatKindIsIt
{
return [NSString stringWithFormat:#"%# %#",[self.housepet genus], [self.housepet species]];
}
- (void)haveALongDayAtWorkAndJustNeedAFriend
{
if (self.housepet) [self.housepet doPet:self];
}
- (void)pet:(id<AnimalMinionType>)pet didScratch:(BOOL)scratchy
{
if ((scratchy) && (pet == self.housepet))
{
NSLog(#"I HATE THAT %#", [[self.housepet nickname] uppercaseString]);
self.housepet = nil;
}
}
#end
I hope that helps. :-)
I have this delegate that is not working out as planned, I have it setup like so. I want to call the function NSLog(show); I am not too sure why this isn't work, but works with my other viewcontroller. I must be missing some small detail.
AccountViewController.h
#protocol AccountViewControllerDelegate;
#interface AccountViewController : UIViewController{
}
#property (nonatomic, assign) id <AccountViewControllerDelegate> accountViewDelegate;
#end
#protocol AccountViewControllerDelegate <NSObject>
- (void)showLabel;
#end
AccountViewController.m
-(IBAction)save:(id)sender {
[self showLabel];
}
- (void)showLabel {
if (self.accountViewDelegate) {
NSLog(#"showlabel");
[self.accountViewDelegate showLabel];
}
}
MapViewController.m
-(void)showLabel {
NSLog(#"SHOW");
}
you haven't shown where you assign the MapViewController to be the delegate of the AccountViewController. Perhaps thats what you are missing
//(from somewhere in the MapViewController)
AccountViewController *accountVC = //however you instantiate it (segue, storyboard etc
accountVC.accountViewDelegate = self;
Kindly note that delegate should not have strong reference.
So use
#property (unsafe_unretained) id <AccountViewControllerDelegate> accountViewDelegate;
Now in MapViewController.m or MapViewController.h conform to this protocol as
#interface MapViewController : UIViewController <AccountViewControllerDelegate>{
}
Then in MapViewController.m please do
AccountViewController *accountVC = [[AccountViewController alloc]init]; // initialize it with whatever be like storyboard or nib
accountVC.accountViewDelegate = self;
Your AccountViewController.h file should look like this
#protocol AccountViewControllerDelegate <NSObject>
- (void)showLabel;
#end
#interface AccountViewController : UIViewController{
}
#property (unsafe_unretained) id <AccountViewControllerDelegate> accountViewDelegate;
#end
Here what you should have in your different files:
AccountViewController.h
Note that "assign" is mainly for primitives like NSInteger, CGFloat, BOOL (that is, for properties that are not objects). Use "weak" to keep a pointer toward your delegate without incrementing his retain count.
#protocol AccountViewControllerDelegate;
#interface AccountViewController : UIViewController
#property (nonatomic, weak) id <AccountViewControllerDelegate> accountViewDelegate;
#end
#protocol AccountViewControllerDelegate <NSObject>
- (void)showLabel;
#end
AccountViewController.m
Here, it is usually good practice to check if the delegate isn't nil and if it has the method you want to call implemented. Use respondToSelector for that.
-(IBAction)save:(id)sender {
[self showLabel];
}
- (void)showLabel {
if (self.accountViewDelegate && [self.accountViewDelegate respondsToSelector:#selector(showLabel)]) {
NSLog(#"showlabel");
[self.accountViewDelegate showLabel];
}
}
MapViewController.h
Be sure to import "AccountViewController.h" here.
#import "AccountViewController.h"
#interface MapViewController : UIViewController <AccountViewControllerDelegate>
#end
MapViewController.m
Put the following where you were instantiating your AccountViewController object:
//Somewhere
AccountViewController *accountViewController = [[AccountViewController alloc] init];
accountViewController.accountViewDelegate = self;
and this is your delegate's method implementation:
- (void)showLabel {
NSLog(#"SHOW");
}
I have a protocol in one class:
#protocol DataStorageManager
- (void) saveFile;
#end
#interface DataManager : NSObject
{
id <DataStorageManager> delegate;
}
#property (nonatomic, assign) id<DataStorageManager> delegate;
//methods
#end
and its implementation:
#implementation DataManager
#synthesize delegate;
#end
and I have another class which is the adapter between the first and the third one:
#import "DataManager.h"
#import "DataPlistManager.h"
#interface DataAdapter : NSObject <DataStorageManager>
#property (nonatomic,strong) DataPlistManager *plistManager;
- (void) saveFile;
#end
and its implementation
#import "DataAdapter.h"
#implementation DataAdapter
-(id) initWithDataPlistManager:(DataPlistManager *) manager
{
self = [super init];
self.plistManager = manager;
return self;
}
- (void) saveFile
{
[self.plistManager savePlist];
}
#end
So when I in first method try to call my delegate method like this
[delegate saveFile];
Nothing happened. I don't understand what's wrong with the realization - it's a simple adapter pattern realization. So I need to use the delegate which will call the methods from the third class. Any help?
You are not setting the delegate property. You need to do this,
-(id) initWithDataPlistManager:(DataPlistManager *) manager
{
self = [super init];
self.plistManager = manager;
self.plistManager.delegate = self;
return self;
}
Also, in DataManager class remove the ivar declaration, just declaring property is sufficient, the ivar gets automatically created. Call the delegate method as below,
if([self.delegate respondsToSelector:#selector(saveFile)] {
[self.delegate saveFile];
}
Hope that helps!
In your case you forget to set your protocol delegate and also need to call protocol method
by self.delegate....
I just Give Basic Idea for how to Create Protocol
Also Read This Question
#DetailViewController.h
#import <UIKit/UIKit.h>
#protocol MasterDelegate <NSObject>
-(void) getButtonTitile:(NSString *)btnTitle;
#end
#interface DetailViewController : MasterViewController
#property (nonatomic, assign) id<MasterDelegate> customDelegate;
#DetailViewController.m
if([self.customDelegate respondsToSelector:#selector(getButtonTitile:)])
{
[self.customDelegate getButtonTitile:button.currentTitle];
}
#MasterViewController.m
create obj of DetailViewController
DetailViewController *obj = [[DetailViewController alloc] init];
obj.customDelegate = self;
[self.navigationController pushViewController:reportTypeVC animated:YES];
and add delegate method in MasterViewController.m for get button title.
#pragma mark -
#pragma mark - Custom Delegate Method
-(void) getButtonTitile:(NSString *)btnTitle;
{
NSLog(#"%#", btnTitle);
}
I have a test case and a helper class. In the helper class I want to use asserts too like here:
MainTests.h
#import <SenTestingKit/SenTestingKit.h>
#interface MainTests : SenTestCase
#end
MainTests.m
#import "MainTests.h"
#import "HelperClass.h"
#implementation MainTests
- (void)testExample {
HelperClass *helperClass = [[HelperClass alloc] init];
[helperClass fail];
}
#end
HelperClass.h
#import <SenTestingKit/SenTestingKit.h>
#interface HelperClass : SenTestCase
- (void)fail;
#end
HelperClass.m
#import "HelperClass.h"
#implementation HelperClass
- (void)fail {
STFail(#"This should fail");
}
#end
Sidenote: I had to make the helper class a subclass from SenTestCase to being able to access the assertion macros.
The assertion from the helper class is ignored. Any ideas why? How can I use assertions in helper classes?
I had this same problem today and came up with a hack that worked for my purposes. Poking into the SenTestCase macros, I noticed that they call [self ...] on the helper but didn't trigger the asserts. So, wiring up the source class to the helper got it working for me. Changes to your question classes would look like:
MainTests.h
#import <SenTestingKit/SenTestingKit.h>
#interface MainTests : SenTestCase
#end
MainTests.m
#import "MainTests.h"
#import "HelperClass.h"
#implementation MainTests
- (void)testExample {
// Changed init call to pass self to helper
HelperClass *helperClass = [[HelperClass alloc] initFrom:self];
[helperClass fail];
}
#end
HelperClass.h
#import <SenTestingKit/SenTestingKit.h>
#interface HelperClass : SenTestCase
- (id)initFrom:(SenTestCase *)elsewhere;
- (void)fail;
#property (nonatomic, strong) SenTestCase* from;
#end
HelperClass.m
#import "HelperClass.h"
#implementation HelperClass
#synthesize from;
- (id)initFrom:(SenTestCase *)elsewhere
{
self = [super init];
if (self) {
self.from = elsewhere;
}
return self;
}
- (void)fail {
STFail(#"This should fail");
}
// Override failWithException: to use the source test and not self
- (void) failWithException:(NSException *) anException {
[self.from failWithException:anException];
}
#end
It is entirely possible that additional overrides are needed for more advanced functionality, but this did the trick for me.