views:

392

answers:

5

Objective C on iPhone: I am attempting to declare the following object at class level so that i do not have to re-connect this socket every time I write something to it. (Writing things multiple times a second) whenever i am writing a steady stream of live data, about every 2 seconds it freezes. I don't know why, but it does.

Code:

Socket *socket = [Socket socket];
[socket connectToHostName:@"10.0.2.3" port:1220];

I have tried declaring the variable in the instance data, then initializing it in +initialize and viewdidload, with no success or with errors. I have search for hours trying to find a way for this to work and after about 20 different solutions, I have found none that work. The socket, by the way, is an object from the smallsockets pack for objective-c.

Small sockets: http://smallsockets.sourceforge.net/

It works great, except for the live data freezing every few seconds. I have narrowed down parts of the code to those two lines. I know that creating and then connecting the socket is what is causing the delay.

Any help is much, much appreciated.

Thanks!!

[Edit]

Here is some sample code of my attempts: instance declaration:

Socket *socket;

viewDidLoad:

socket = [Socket socket]; //Throws error on compile

Alternate Viewdidload:

Socket *tempSocket = [Socket socket];
socket = tempSocket;
//This compiles fine, however it doesn't work when trying to use it
+2  A: 

Don't create socket in +initailize, that's way early.

Add some debug logging (NSLog()) to your code in viewDidLoad, and log the socket to see if it's getting created. Then put a breakpoint on it in gdb, and see if it's valid.

-W

Wil Shipley
When logging it, I have created the variable "Socket * socket" in the instance data and it works smoothly until it attempts the following line: "socket = [Socket socket]"Another idea I had of creating it as a seperate object and then trying to save the new pointer to the instance data pointer works, however it crashes whenever data is trying to be written to it.
Brendan Lee
You should probably post some example code.
Wil Shipley
added two of the attempts into original post
Brendan Lee
A: 

You might want to use AsyncSocket which offers asynchronous operations with sockets (on top of CFSocket and CFStream).

I found it in this StackOverflow answer.

Jean Regisser
+1  A: 

The code for +socket would be interesting to see. My guess is that this is a convenience method, i.e. the results of this, a socket, are autoReleased. Now I don't know if you are retaining this or not in your socket property, but you should, otherwise after the runloop is done, socket gets released. i.e. you need a

@property (retain) Socket *socket;

in your interface file.

mahboudz
Thanks, I'll try that now. Here is the code for +socket.[CODE]+ (Socket*)socket{ return [[[Socket alloc] init] autorelease];}[/CODE]
Brendan Lee
As I expected, it is imperative that the return value from `[Socket socket]` be retained or else it will not last beyond viewDidLoad.
mahboudz
I am also concerned about the compiler error you mention above and why it goes away with the change. The first attempt is actually preferred when using convenience methods. What is the compiler error? (One way to format code for comments is to use the back-single-quotes around your code. Or indent the code in 4 spaces when on a new line)
mahboudz
A: 

So what happens if your destination is unreachable or some other network problem causes delay? How about if your remote socket is expecting some kind of acknowledgement but your iPhone is buys at the time it is supposed to be sending ACK? If you are not using some select()-like mechanism you should at least be doing all of your synchronous network stuff in another thread. NSThread is worth a look.

Adam Eberbach
If destination is unreachable, it simply fails. However, you are exactly right. It was network congestion. The wifi network i was using involved using a mac mini to broadcast a wifi network to connect my laptop and iPhone. When i directly connect the laptop and phone it works perfectly. My mac mini internet sharing solution for my dorm has always been a bit slow, but i never thought it would be this bad for local network connections too! I would still like to find a way to not have to recreate and connect the socket each time, however for now the network congestion seems to be the problem.
Brendan Lee
A: 

Attempting to declare at class level?

Do you mean, you want "socket" to be a class-scoped global variable that you initialize for the whole class, not an instance? If so, you can't declare socket as an instance variable. Instance variables only exist for instances (i.e. allocated objects). Instead, you must declare it outside the class. Globals are normally declared just under the #import lines in the .m file.

Then you can initialize it anywhere you want. I recommend a class method that you invoke from applicationDidFinishLaunching:

#import "Socket.h"

Socket *globalSocket = nil;

@implementation Socket

+ (void)connectGlobalSocket
{
    if (!globalSocket)
    {
        globalSocket = [[Socket socket] retain];
        [globalSocket connectToHostName:@"10.0.2.3" port:1220];
    }
}

....
Matt Gallagher