Sending dictionary from a VC to another VC through Custom delegtes - objective-c

I have a class in which response from server is coming as responseDictionary.I want to use this responseDictionary in another VC but not able to send the dictionary through delegates.Kindly explain with code in objective c that how this can be achieved.

sample project, it is simply for demo, u can refer it
first we will create a class names WebService it will request the data, and as a response it will get a dictionary, and also it defines a delegate to notify that data is received and sent to the VC (in your case)
in WebService.h
#import <Foundation/Foundation.h>
#protocol WebServiceDelegate;
#interface WebService : NSObject
{
}
#property(nonatomic, assign) id<WebServiceDelegate>webServiceDelegate;
- (void)webserviceRequestData; //initiates the data request
#end
#protocol WebServiceDelegate <NSObject>
- (void)webService:(WebService *)aWebService didReceievResponseData:(NSDictionary *)dataDictionary;
#end
in WebService.m
#import "WebService.h"
#implementation WebService
- (instancetype)init
{
self = [super init];
if(self)
{
}
return self;
}
- (void)webserviceRequestData
{
sleep(5); //for demo
[self makeWebserviceToGetSomeData];
}
- (void)makeWebserviceToGetSomeData
{
NSDictionary *data = [NSDictionary dictionaryWithObjectsAndKeys:#"Data_1",#"Key_1",#"Data_2",#"Key_2",#"Data_3",#"Key_3", nil];
[self receievedSomeData:data];
}
//finally data is received as dictionary and send it to VC
- (void)receievedSomeData:(NSDictionary *)dataDictionary
{
if([self.webServiceDelegate respondsToSelector:#selector(webService:didReceievResponseData:)])
[self.webServiceDelegate webService:self didReceievResponseData:dataDictionary];
}
#end
and in the view controller class ViewController.h
#import <UIKit/UIKit.h>
#import "WebService.h"
#interface ViewController : UIViewController<WebServiceDelegate>
#property(nonatomic, strong) WebService *myWebService;
#end
and in ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_myWebService = [[WebService alloc] init];
_myWebService.webServiceDelegate = self; //this is call back to this class
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[_myWebService webserviceRequestData];
}
- (void)webService:(WebService *)aWebService didReceievResponseData:(NSDictionary *)dataDictionary
{
NSLog(#"web data:%#",dataDictionary.description);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
after 5 seconds we made to call the method makeWebserviceToGetSomeData and it will send the call the another method receievedSomeData: method in this we are checking weather caller implemented the method or not to avoid crash(unrecognised selector sent to object), and we are passing the data (dictionary) to view controller
and also u can call web service from any class (any viewcontroller) and set it as a delegate

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.

Problems linking NSTableView handler class

I have a strange problem in my Cocoa-app. I have a main window with an NSTableView in it with a controller class (PropValTableHandler). I have made the connections between my NSTableView and the PropValTableHandler, but when the 'numberOfRowsInTableView' method is called it looks like not the 'PropValTableHandler' initialized in 'AddDelegate' is used, since the 'propMan' field is not initialized (it is like the normal init is used, so it has to be another instance of this class).
Am I doing something wrong? I have another NSTableView handler in another window, that works, but it does not have a custom init method.
Source codes:
AppDelegate
#import "AppDelegate.h"
#implementation AppDelegate
#synthesize propValTableController = _propValTableController;
-(id) init
{
self = [super init];
if (self)
{
_propMan = [[OCPropertyManager alloc]initWithPath:"./data/"];
_propValTableController = [[PropValTableHandler alloc]
[initWithPropManager:_propMan];
}
return self;
}
PropValTableHandler
#interface PropValTableHandler : NSObject <NSTableViewDataSource>
#property IBOutlet NSTableView * constants;
#property OCPropertyManager * propMan;
-(id) initWithPropManager:(OCPropertyManager*)pm;
-(NSInteger) numberOfRowsInTableView:(NSTableView *)tableView;
#end
#import "PropValTableHandler.h"
#implementation PropValTableHandler
-(id) initWithPropManager:(OCPropertyManager*)pm
{
self = [super self];
if (self)
{
self.propMan = pm;
}
return self;
}
/*********** TABLEVIEW DATASOURCE ******************/
-(NSInteger) numberOfRowsInTableView:(NSTableView *)tableView
{
NSInteger count = [_propMan.consts count];
return count;
}
/**************************************************/
#end
I have solved the problem by adding a
#property IBOutlet AppDelegate *parent;
for the PropValTableHandler class and making the connections.
This way I can use:
parent.propMan
where ever I need it without passing a reference to it in the init method.

Should I "Pull Up" Refactor

I have some very small classes that I feel should be "pulled up" but the methods are so small I'm not sure. For example, the only thing that's meaningfully different is the body of the buildFromJSON: selector.
I acknowledge that this is similar to:
Pull-up refactoring, Objective-C
but I feel my question is specific to refactoring very small classes/methods.
Also, not sure it relates to my particular code example, but I'm wondering if a child class says it conforms to a protocol, whether it's enough that it's parent actually supply the implementation of required selector(s)?
#implementation AsyncFoo
-(void)dealloc {
[clientDelegate release];
[super dealloc];
}
- (id)initWithDelegate: (id <ServiceClientProtocol>) delegate {
if((self = [super init])) {
clientDelegate = [delegate retain];
}
return self;
}
- (void)buildFromJSON:(NSString*)jsonResponseString {
[clientDelegate serviceComplete:[RestAdapter buildFooArray: jsonResponseString]];
}
#end
#implementation AsyncBar
-(void)dealloc {
[clientDelegate release];
[super dealloc];
}
- (id)initWithDelegate: (id <ServiceClientProtocol>) delegate {
if((self = [super init])) {
clientDelegate = [delegate retain];
}
return self;
}
- (void)buildFromJSON:(NSString*)jsonResponseString {
[clientDelegate serviceComplete:[RestAdapter buildBarArray:jsonResponseString]];
}
#end
Answers including code example would be great.
EDIT: Post accepted answer I'd like to add that since I was able to subclass, the derived classes did not need to declare that they conformed to protocol:
#interface Async : NSObject <ModelBuilderProtocol> {
id <ServiceClientProtocol> clientDelegate;
}
- (void)buildFromJSON:(NSString*)jsonResponseString;
#end
#interface AsyncArtistById : Async
#end
You don't normally retain your delegates as this can cause a retain cycle.
Knowing what I know from looking at your example I would probably implement like this:
The super class
// Async.h
#interface Async : NSObject
#property (nonatomic, assign) id<ServiceClientProtocol> delegate;
- (void)buildFromJSON:(NSString *)jsonResponseString;
#end
// Async.m
#implementation Async
#synthesize delegate = _delegate;
- (id)initWithDelegate:(id<ServiceClientProtocol>)delegate
{
self = [super init];
if(self) {
_delegate = delegate;
}
return self;
}
- (void)buildFromJSON:(NSString *)jsonResponseString
{
// This will ensure that we over ride this method in a sub class
[NSException raise:NSInternalInconsistencyException
format:#"You must override %# in a subclass", NSStringFromSelector(_cmd)];
}
#end
Concrete subclass AsyncFoo
// AsyncFoo.h
#interface AsyncFoo : Async
#end
// AsyncFoo.m
#implementation AsyncFoo
- (void)buildFromJSON:(NSString *)jsonResponseString
{
[self.delegate serviceComplete:[RestAdapter buildFooArray: jsonResponseString]];
}
#end
Concrete subclass AsyncBar
// AsyncBar.h
#interface AsyncBar : Async
#end
// AsyncBar.m
#implementation AsyncBar
- (void)buildFromJSON:(NSString *)jsonResponseString {
[self.delegate serviceComplete:[RestAdapter buildBarArray:jsonResponseString]];
}
#end

How to assert a UILabel.text property is equal to an instance of NSString in objective-c

I'm new to objective-c and I'm finding that I don't know how to correctly assert that a text property on some given label is equal to a raw string value. I'm not sure if I just need to cast the label as NSString or if I need to modify my assert statement directly.
#interface MoreTest : SenTestCase {
MagiczzTestingViewController* controller;
}
- (void) testObj;
#end
#implementation MoreTest
- (void) setUp
{
controller = [[MagiczzTestingViewController alloc] init];
}
- (void) tearDown
{
[controller release];
}
- (void) testObj
{
controller.doMagic;
STAssertEquals(#"hehe", controller.label.text, #"should be hehe, was %d instead", valtxt);
}
#end
The implementation of my doMagic method is below
#interface MagiczzTestingViewController : UIViewController {
IBOutlet UILabel *label;
}
#property (nonatomic, retain) UILabel *label;
- (void) doMagic;
#end
#implementation MagiczzTestingViewController
#synthesize label;
- (void) doMagic
{
label.text = #"hehe";
}
- (void)dealloc {
[label release];
[super dealloc];
}
#end
The build is fine when I modify the assert to compare a raw NSString to another but when I try to capture the text value (assuming it's of type NSString) it fails. Any help would be much appreciated!
STAssertEquals() checks for identity of the two values provided, so it's equivalent to doing this:
STAssertTrue(#"hehe" == controller.label.text, ...);
Instead, you want STAssertEqualObjects(), which will actually run an isEqual: check like the following:
STAssertTrue([#"hehe" isEqual:controller.label.text], ...);
You need to load the nib of the view controller. Otherwise there won't be any objects for the label outlet to be hooked up to.
One way to do this is to add an ivar for the view controller's view to your test case:
#interface MoreTest : SenTestCase {
MagiczzTestingViewController *controller;
UIView *view;
}
#end
#implementation MoreTest
- (void)setUp
{
[super setUp];
controller = [[MagiczzTestingViewController alloc] init];
view = controller.view; // owned by controller
}
- (void)tearDown
{
view = nil; // owned by controller
[controller release];
[super tearDown];
}
- (void)testViewExists
{
STAssertNotNil(view,
#"The view controller should have an associated view.");
}
- (void)testObj
{
[controller doMagic];
STAssertEqualObjects(#"hehe", controller.label.text,
#"The label should contain the appropriate text after magic.");
}
#end
Note that you also need to invoke super's -setUp and -tearDown methods appropriately from within yours.
Finally, do not use dot syntax for method invocation, it is not a generic replacement for bracket syntax in message expressions. Use dot syntax only for getting and setting object state.

Why This Class <Not Responding>

Hi
i dont know why i call a function in "msg" class
it has no respond:(
this is the "msg" class:
msg.h :
#import <UIKit/UIKit.h>
#interface msg : NSObject {
}
-(void) Print;
#end
msg.m :
#import "msg.h"
#implementation msg
-(void) Print {
NSLog(#"Hello World");
}
#end
viewController.h :
#import <UIKit/UIKit.h>
#import "msg.h"
#class msg;
#interface ClassMod4ViewController : UIViewController {
msg *object;
}
#property (nonatomic,retain) msg *object;
#end
viewController.m :
#import "ClassMod4ViewController.h"
#implementation ClassMod4ViewController
#synthesize object;
- (void)viewDidLoad {
[object Print];
[super viewDidLoad];
}
Thanks
Was the object initialized in the designated initializer (usually initWithNibName:bundle: for UIViewController subclasses) prior to viewDidLoad being invoked?
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
// ...
object = [[Msg alloc] init];
// ...
return self;
}
If the object has not been initialized, then it's nil. Remember that it's okay to send nil objects messages in Objective-C (nothing will happen as a result).
have you tried:
- (void)viewDidLoad {
assert(object);
[object Print];
[super viewDidLoad];
}
?
if the assertion fails, then the pointer to object is 0 (or nil). you must create the object before you use it. this is typically performed in the initializer (in your case, of the class that contains the instance of object):
- (id)init {
self = [super init];
if (0 != self) {
object = [[msg alloc] init];
}
return self;
}
but sometimes you'll want to create the object later on.
if you are initializing it, then you may want to set breakpoints where the object is accessed in order to determine where the object is set to 0.