-4

I'm trying to create global function in Objective-C. I created new .m and h. file with subclass of viewcontroller.

This is Connection.m

#import "Connection.h"
@interface ViewController () <NSStreamDelegate>

@property (strong,nonatomic) NSInputStream * inputStream;
@property (strong,nonatomic) NSOutputStream * outputStream;

@end

@implementation ViewController(Connection)
-(void)initNetworkCommunication {
    CFReadStreamRef readStream;
    CFWriteStreamRef writeStream;
    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"192.168.0.10", 35000, &readStream, &writeStream);
    self.inputStream = objc_unretainedObject(readStream);
    self.outputStream = objc_unretainedObject(writeStream);
    [self.inputStream setDelegate:self];
    [self.outputStream setDelegate:self];
    [self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [self.outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

    [self.inputStream open];
    [self.outputStream open];
}

Connection.h

#import "ViewController.h"

@interface ViewController(Connection)

-(void)initNetworkCommunication;

@end

ViewController.m

#import "ViewController.h"
#import "Connection.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
- (IBAction)ConnectionButton:(id)sender {
    [self initNetworkCommunication];
}

@end

I tryed 3 methods mentioned in How to create global functions in Objective-C but no one of this 3 works. First two(create a class method in a static class and declare a global function instead of class) don't work because when I change "-(void)... to +(void).. every "self..." gets error and same in second method. Only third one works for me (adding a category to NSObject for your methods) but when I'm trying to call [self initNetworkCommunication] function program crashesh with signal SIGABRT and I can't solve that problem. Any ideas how I can call this function?

UPDATE: @gronzzz

Connection.m

@interface ViewController () <NSStreamDelegate>

@property (strong,nonatomic) NSInputStream * inputStream;
@property (strong,nonatomic) NSOutputStream * outputStream;

@end

@implementation Connection

-(void)initNetworkCommunication 
Connection.h

#import "ViewController.h"

@interface Connection : ViewController

-(void)initNetworkCommunication;
@end
ViewController.h

#import "ViewController.h"
#import "Connection.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
- (void)callMethod
{
    Connection *detailVC = [[Connection alloc] init];
    [detailVC initNetworkCommunication];
}
- (IBAction)ConnectionButton:(id)sender {
    [self callMethod];

}

@end

And Signal SIGABRT show when [self callMethod] is called.

Community
  • 1
  • 1
Mateusz Tylman
  • 271
  • 1
  • 2
  • 17
  • post more code please – gronzzz Dec 06 '14 at 00:19
  • you needn't categories and 2 classes at that case, make all your code in one ViewController class without connection and category and read a couple of manuals to understand what's going on with classes first of all, and only them with extensions and categories. – gronzzz Dec 06 '14 at 00:36
  • You unfortunately don't understand some of the basic principles involved here. `self` refers to the current object instance, and a class method (one with `+` instead of `-`) doesn't have an object instance. And I suspect you've got numerous other misunderstandings as well. – Hot Licks Dec 06 '14 at 00:36
  • @HotLicks obviously they don't understand, that is why they are asking for help... – Kris Gellci Dec 06 '14 at 00:40
  • And where you are now you should not try either of the second two schemes discussed in the referenced question. You don't understand them well enough to use them, even if they were the "right" answer (which they aren't). – Hot Licks Dec 06 '14 at 00:40
  • It would be a lot easier to answer your question if you gave us an example of a "global function" you wish to write. – Hot Licks Dec 06 '14 at 00:42
  • I just want create separated .m file with -(void)initNetworkCommunication function and use/call it anywhere i want. – Mateusz Tylman Dec 06 '14 at 00:48

3 Answers3

0

To call one instance method from another class, you just need to initialize this class and them call. Calling method must be inside @interface brackets. Also don't understand why did you call "[self initNetworkCommunication]", for that you needn't category or something else.

DetailViewController.h

@interface DetailViewController : UIViewController

-(void)initNetworkCommunication;
@end

DetailViewController.m

@implementation DetailViewController
-(void)initNetworkCommunication
{
     // do something
}
@end

MasterViewController.h

@implementation MasterViewController
- (void)callMethod
{
    DetailViewController *detailVC = [[DetailViewController alloc] init];
    [detailVC initNetworkCommunication];
}
@end

UPDATE

in .h file you are making interface category, in .m file you are making class extension and then implementation of class, but you still doesn't makes interface for your class.

gronzzz
  • 617
  • 6
  • 15
  • You confused things by saying "class instance method". You should use "class method" for methods starting with `+` and "instance method" for methods starting with `-`. – Hot Licks Dec 06 '14 at 00:38
  • show us full code with method calling and when did error is happen. – gronzzz Dec 06 '14 at 00:48
0

I am trying to figure out what exactly you are trying to accomplish based on your code. It seems as though you want one of two things. You either want a global function which will initialize an input and output stream given to it by an object, or you want something called a singleton which will itself hold the input and output stream and can be initialized by anywhere.

Based on your example, I will assume that you want the function, if it is in fact the singleton pattern that sounds more correct, feel free to search for objective-c singleton pattern.

+(void)initNetworkCommunicationWithInputStream:(NSInputStream *)inputStream outputStream:(NSOutputStream *)outputStream delegate:(id < NSStreamDelegate >)delegate {
    CFReadStreamRef readStream;
    CFWriteStreamRef writeStream;
    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"192.168.0.10", 35000, &readStream, &writeStream);
    inputStream = objc_unretainedObject(readStream);
    outputStream = objc_unretainedObject(writeStream);
    [inputStream setDelegate:delegate];
    [outputStream setDelegate:delegate];
    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

    [inputStream open];
    [outputStream open];
}

You can have this method exist in some class and then you can call it without initializing that class and passing in the params you want setup:

[someClass initNetworkCommunicationWithInputStream:iStream outputStream:oStream delegate:self];
Kris Gellci
  • 9,539
  • 6
  • 40
  • 47
0

Assuming that you want a method named callMethod inside ViewController to be your "global" method:

+ (void)callMethod
{
    Connection *detailVC = [[Connection alloc] init];
    [detailVC initNetworkCommunication];
}

Invoked with:

[ViewController callMethod];

But do note that your callMethod implementation does not return anything, and the Connection object created within it will be deleted on exit from the method (unless the call to initNetworkCommunication somehow preserves it).

Hot Licks
  • 47,103
  • 17
  • 93
  • 151
  • To be honest I'm confused. Normal methods works fine but that with stream just always crash when I'm trying to call it from other place than main ViewController. I just wanted to have that connection code outside ViewController to make code more visible for me. It still crashes when I'm trying to call it. I'm not sure but as @Kris Gellci mentioned above maybe I need to use singleton. As you can see I'm total beginner in Objective-C and I jumped into depth water instead of learn everything from scrach – Mateusz Tylman Dec 06 '14 at 01:40
  • @MateuszTylman - Well, I'm not going to try to dig into the rest of your logic. The above is a way to do a very simple "class method" that does not require an object instance to call it. What logic you put into that method is up to you. – Hot Licks Dec 06 '14 at 01:50
  • It is simple but still I can't get it work. I'm still getting signal SIGABRT after using [Connection callMethod] with will call my method initNetworkCommunication]. Anyway thank you for help. – Mateusz Tylman Dec 06 '14 at 02:01
  • It sounds like you just need to learn how to debug. Study up on how to find and examine the exception stack. – Hot Licks Dec 06 '14 at 02:06