Search code examples
c++objective-cnsurlconnectionnsurlnsurlrequest

Pure C++ equivalent for NSURLConnection and NSURLRequest


I am porting a game using native C++ for Android. I need to know which method I should use to achieve the same functionality as NSURLConnection and NSURLRequest in only C++. Also how to get all the following delegate functions implemented for C++.

-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error

-(void)connectionDidFinishLoading:(NSURLConnection *)connection

Please advise.


Solution

  • There is no way to implement Objective-C delegate methods in C++ directly. The best you can really hope to do is to use Objective-C++ to make a C++ object with an instance variable that is an Objective-C object whose sole purpose is to be the NSURLConnection delegate and forward those method calls to the owning C++ object. The C++ object should own/retain the Objective-C object, and be responsible for plugging it in as the delegate of the NSURLConnection object.

    An extremely naive implementation of the above described pattern might look like this:

    URLConnection.h

    #ifndef __Cplusplus__URLConnection__
    #define __Cplusplus__URLConnection__
    
    #include <string>
    
    class URLConnection
    {
    public:
        URLConnection(std::string url);
        ~URLConnection();
    
        void DidReceiveResponse(const void* response);
        void DidReceiveData(const void* data);
        void DidFailWithError(std::string error);
        void DidFinishLoading();
    
        void* mNSURLConnection;
        void* mDelegate;
    };
    
    #endif /* defined(__Cplusplus__URLConnection__) */
    

    URLConnection.mm

    #include "URLConnection.h"
    
    @interface PrivateNSURLConnectionDelegate : NSObject <NSURLConnectionDelegate>
    {
        URLConnection* mParent;
    }
    - (id)initWithParent: (URLConnection*) parent;
    @end
    
    @implementation PrivateNSURLConnectionDelegate
    
    - (id)initWithParent: (URLConnection*) parent
    {
        if (self = [super init])
        {
            mParent = parent;
        }
        return self;
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
    {
        mParent->DidReceiveResponse(response);
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    {
        mParent->DidReceiveResponse(data.bytes);
    }
    
    - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
    {
        mParent->DidFailWithError(std::string([[error description]UTF8String]));
    }
    
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection
    {
        mParent->DidFinishLoading();
    }
    
    @end
    
    
    URLConnection::URLConnection(std::string url)
    {
        this->mDelegate = [[PrivateNSURLConnectionDelegate alloc] initWithParent: this];
        NSURLRequest* req = [NSURLRequest requestWithURL: [NSURL URLWithString: [NSString stringWithUTF8String: url.c_str()]]];
        this->mNSURLConnection = [[NSURLConnection alloc] initWithRequest: req delegate: (id)this->mDelegate];
    }
    
    URLConnection::~URLConnection()
    {
        [(NSObject*)this->mNSURLConnection release];
        [(NSObject*)this->mDelegate release];
    }
    
    void URLConnection::DidReceiveResponse(const void* response)
    {
        // Do something...
    }
    void URLConnection::DidReceiveData(const void* data)
    {
        // Do something...
    
    }
    void URLConnection::DidFailWithError(std::string error)
    {
        // Do something...
    }
    
    void URLConnection::DidFinishLoading()
    {
        // Do something...
    }
    

    At the end of the day, NSURLConnection is an Objective-C object. There's no way to interact with it without using Objective-C.