1

I have multiple views where I need to handle the network connection of socket.io, so I created singleton class namely MC_SocketHandler. Below is the code of the MC_SocketHandler class.

//    MC_SocketHandler.h

#import <Foundation/Foundation.h>
#import "SocketIO.h"


@interface MC_SocketHandler : NSObject <SocketIODelegate>

// SocketIO
//@property (nonatomic) SocketIO *socketConnection;

+ (MC_SocketHandler *) sharedSocketHanderObj;
+ (SocketIO *) initHandShake;
+ (SocketIO *) getSocketConnection;

-(bool) isConnected;
-(void) disConnect;
-(void) fireAgentLeftChat;

@end

//  MC_SocketHandler.m

#import "MC_SocketHandler.h"
#import "MC_APIUtility.h"

@implementation MC_SocketHandler

SocketIO *socketConnection = nil;
static MC_SocketHandler *sharedSocketObj = nil;

+ (MC_SocketHandler *) sharedSocketHanderObj {
    if (sharedSocketObj == nil)
        sharedSocketObj = [[MC_SocketHandler alloc] init];

    return sharedSocketObj;
}

+(SocketIO*) initHandShake {

    if (socketConnection == nil) {
        NSDictionary *headers = [NSDictionary dictionaryWithObjectsAndKeys:[MC_APIUtility getApiToken], @"token", nil];
        socketConnection = [[SocketIO alloc] initWithDelegate:(id)self ];
        [socketConnection connectToHost:domain onPort:447 withParams:headers];
    }
    return  socketConnection;
}

+ (SocketIO *) getSocketConnection {
    return socketConnection;
}

-(bool) isConnected {
    if (socketConnection == nil)
        return socketConnection.isConnected;

    return false;
}

-(void) disConnect {
    if (socketConnection != nil && socketConnection.isConnected)
        [socketConnection disconnect];

    NSLog(@"Disconnected --- %hhd", socketConnection.isConnected );
    return;
}


// SocketIO Delegate
-(void) socketIODidConnect:(SocketIO *)socket {
    NSLog(@"Socket has Connected....");
}

-(void) socketIO:(SocketIO *)socket didReceiveEvent:(SocketIOPacket *)packet {

    NSString *data = packet.data;
    NSLog(@"---- didReceoveEvent - data - %@", data);

    // Grab data from packet
    NSDictionary *dict = packet.dataAsJSON;
    NSLog(@"EVENT DATA :- %@   DICT :- %@", data, dict);

    /*
     EVENTS To Listen
     onSuccessInit
     visitor_info
     new_visitor
     agent_online
     agent_offline
     agent_logout

     */
    dict = nil;

    // Pull out args fro mdict
    //NSArray *args = dict[@"args"];
}

-(void) socketIO:(SocketIO *)socket didReceiveMessage:(SocketIOPacket *)packet {
    NSLog(@"Rcvd Message - %@", packet.data);
}

-(void) socketIO:(SocketIO *)socket didSendMessage:(SocketIOPacket *)packet {
    NSLog(@"Send Msg - %@", packet.dataAsJSON);
}

-(void) socketIO:(SocketIO *)socket onError:(NSError *)error {
    NSLog(@"Error - %@", error);
}

-(void) socketIODidDisconnect:(SocketIO *)socket disconnectedWithError:(NSError *)error {
    NSLog(@"Disconnected With Error - %@", error);
}

-(void) fireAgentLeftChat {

    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    [dict setObject:[MainAppDataObject sharedAppDataObject].activeAgentChatItem.chatSessionId forKey:@"chat_session_id"];


    [socketConnection sendEvent:@"agentLeftChat" withData:dict];

    return;
}

- (void)dealloc {
    socketConnection = nil;
}



@end

Code that I use it in 1 of my views :

// Init SocketIO

SocketIO *socket = [MC_SocketHandler initHandShake];

// Fire Agent Online event
[socket sendEvent:@"setAgentOnline" withData:nil];

Handshake is being done properly, setAgentOnline event is send properly. Other events that I fire are also done properly. BUT, when socket gets connected thru initHandshake, I believe "Socket has Connected...." should be seen in logs as that is written in socketIODidConnect delegate method. Similarly, I receive event (I see logs of socket.m class), but my delegate method didReceiveEvent is never called. Same way I don't see any logs of any delegate methods. In initHandShake method only I have set the delegate also : socketConnection = [[SocketIO alloc] initWithDelegate:(id)self ]; yet why these methods aren't called.

I was also wondering, when I receive events, on different events I got to perform different actions. How will I transfer to particular view (View's obj won't be shared with this to call his method) ? And If I create delegate, then I will have to handle all delegate methods in all views. What's will be the best method to work out with this ? And why this Singleton & delegate methods aren't being linked & called when I have set the delegate. Where am I going wrong ?

Any help, guidance is highly appreciative. Thanks alot.

Tvd
  • 4,463
  • 18
  • 79
  • 125
  • Purely FWIW. here's a general VERY SIMPLE WAY to use singletons, correct and easily, via a macro. http://stackoverflow.com/a/23978596/294884 it's possible this will help, and I hope it does cheers! – Fattie Jun 03 '14 at 09:53
  • Thanks @JoeBlow. To handle out with receiving events and managing that, I created a delegate class as worked here - http://stackoverflow.com/questions/15994066/delegate-not-working-in-singleton . So for this, in my all views I got to set delegate = self , so I can write SOCKIO.delegate = self; in all views. Will it be safe to work like this or MC_SocketHandler *IOConnection = [MC_SocketHandler sharedSocketHanderObj]; IOConnection.delegate = self; in all views be safe & better. I believe results will be same, but am just concerned about safety & proper usage. – Tvd Jun 03 '14 at 10:23
  • @JoeBlow, I will definetly implement this prefix.pch idea with my other singleton class used. – Tvd Jun 03 '14 at 10:24
  • ok it's likely that **ONLY THE CLASS MC_SocketHandler ITSELF would be the delegate of sockio**. so, INSIDE MC_SocketHandler you would say something like SOCKIO.delegate = self. you WOULD NOT set the delegate of SOCKIO in other places. indeed it looks like you would not even "mention" SOCKIO in other places, you would now only use your singleton. – Fattie Jun 03 '14 at 10:43
  • I'm afraid I'm not fresh with SOCKIO, so you will have to wait for someone else to help. it could be you are more trying to just SUBCLASS sockio?? let's wait for an expert on the subject :) – Fattie Jun 03 '14 at 10:44
  • In my prefix.pch file, I added this line - #define SOCKIO [MC_SocketHandler sharedSocketHanderObj] . That's how I got to SOCKIO. If I set .delegate = self inside MC_SocketHandler (as it is shown in above code), then it's not calling the delegate methods that I am pointing out. Hence I created a delegate class, a property of it in MC_SocketHandler class & set that delegate in my view's class to the viewController's class. – Tvd Jun 03 '14 at 10:49
  • (1) you would make it #define MCSOCKETHANDLER, or if you prefer MC_SOCKETHANDLER. do not use SOCKIO. you'll have to change all that! – Fattie Jun 03 '14 at 10:51
  • (2) if your singleton class MC_SocketHandler (ie, MC_SOCKETHANDLER) is the delegate -- then you should be able to, and you must, set the delegate there inside that class. it's that easy! – Fattie Jun 03 '14 at 10:55

1 Answers1

2

In SocketIO, you create a SocketIO

Is that right?

In fact called "socketConnection". Am i right?

AT THAT TIME...

you must set the delegate !!!

Essentially, your code must look like this,

socketConnection =  make one of these.
socketConnection.delegate = self;

It's possible this is your fundamental problem. I hope it helps!

PS you should, almost certainly, use only properties in iOS development. get rid of your "traditional" variables and use only properties.

Community
  • 1
  • 1
Fattie
  • 27,874
  • 70
  • 431
  • 719