Cocoa Frequently Asked Questions


How to install a code generation template update?

Code generation template updates are being distributed sometimes to fix some issues before a new products version built. It's easy to install such update which may consist of one or more files with such names as:

  • codegen2
  • template.Obj-C.intf.h_
  • template.Obj-C.intf.m_ Plase follow these steps to install them:
  • locate the rodl2objc application with Finder at `/Developer/RemObjects Software/Tools
  • Ctrl-click the rodl2objc file and execute the Show Package Contents command, the new Finder window will appear
  • Inside that new window navigate to the Contents/Resources path, you will see existing files with the names listed above
  • Drag the new copies of updated files to this window, they will be copied and will replace existing ones.

How to uninstall RO/DA completely from OS X system?

Actually you need to remove two directories, one contains the Xcode project templates and other contains the rest. Execute the following commands from Terminal (need to enter your password):

sudo rm -rf /Library/Developer/Xcode/Templates/Project\ Templates/*
sudo rm -rf /Developer/RemObjects\ Software

Setting ROHTTPClientChannel channel timeout value seems to have no effect on iOS, why?

This happens due to iOS SDK design, all attempts to set the HTTP timeout value lower than some minimum are ignored at the Foundation framework level. The reason of such behavior is that in slow network conditions (such as GSM/EDGE) short timeouts make no sense and lead to unnecessary timeout errors in applications.
If you still need short timeout values the only way to work this around is to use Asynchronous Requests in combination with NSTimer objects. The idea is to start the request together with the timer programmed to fire after necessary timeout period. When the timer fires it will cancel the corresponding asynchronous request. Look into the following sample code.

  • Header:
@interface iOS_HTTP_TimeoutViewController : UIViewController 
{
    // Assume two text fields to enter the request timeout and actual duration
    UITextField *timeoutField;
    UITextField *durationField;

    // Instances necessary to access the remote server
    ROBinMessage *msg;
    ROClientChannel *chan;
    SomeService_AsyncProxy *proxy;
}

@property (assign) IBOutlet UITextField *timeoutField;
@property (assign) IBOutlet UITextField *durationField;

// Will start the remote request in response to a button click
- (IBAction)start:(id)sender;

- (void)displayMessage:(NSString *)aMessage;

@end
  • Implementation:
@implementation iOS_HTTP_TimeoutViewController

@synthesize timeoutField;
@synthesize durationField;

- (IBAction)start:(id)sender
{
    int duration = [[durationField text] intValue];
    int timeout = [[timeoutField text] intValue];
    
    // This prepares the long operation with the specified timeout to start
    // but doesn't start it yet.
    ROAsyncRequest *asyncRequest = [proxy beginLongOp:duration start:NO];
    asyncRequest.delegate = self;
    
    // Notice the async request object passed as user info, will be used inside
    // the 'timer fired' method
    NSTimer *requestTimer = [NSTimer scheduledTimerWithTimeInterval:(double)timeout 
                                                 target:self 
                                   selector:@selector(requestTimerFired:) 
                                   userInfo:asyncRequest 
                                repeats:NO];
    
    // The timer object itself is referenced by the async request for convenience,
    // we have to cancel the timer in case of the operation finishes before the
    // timeout expires.
    asyncRequest.context = requestTimer;
    [asyncRequest start];
}

- (void)requestTimerFired:(NSTimer*)aTimer
{
    // The timeout expired - canceling the async request
    [(ROAsyncRequest *)[aTimer userInfo] cancel];
}

- (void)displayMessage:(NSString *)aMessage
{
    // Not so important ...
}

#pragma mark Async request delegate

- (void)asyncRequestDidComplete:(ROAsyncRequest *)request
{
    // The operation completed - the timer is not needed any more
    [(NSTimer *)request.context invalidate];
    NSString *res = [proxy endLongOp:request];
    [self displayMessage:[NSString stringWithFormat:@"Operation completed. %@", res]];
}

- (void)asyncRequest:(ROAsyncRequest *)request didFailWithException:(NSException *)exception
{
    // The operation completed - the timer is not needed any more
    [(NSTimer *)request.context invalidate];
    [self displayMessage:[NSString stringWithFormat:@"Problem found... %@", [exception reason]]];
}

- (void)asyncRequestWasCanceled:(ROAsyncRequest *)request
{
    [self displayMessage:@"Operation was cancelled by custom timeout"];
}


- (void)viewDidLoad 
{
    [super viewDidLoad];
    msg = [[ROBinMessage alloc] init];
    chan = [[ROHTTPClientChannel alloc] initWithTargetUrl:@"http://192.168.1.10:8099/bin"];
    proxy = [[SomeService_AsyncProxy alloc] initWithMessage:msg channel:chan];
}

// Some not so important code not shown

@end

Why am I getting 'symbol not found' linker errors when building an iOS application?

The answer is also relevant for Data Abstract for Cocoa (iPhone OS version).

Both Remoting SDK for Cocoa and Data Abstract for Cocoa for iPhone OS are implemented as static libraries. Unlike Cocoa frameworks, static libraries contain no linking information inside. When a static library depends on a dynamic library (or framework, this makes no difference to the linker), the compiler generates all required code to call functions from the dynamic library but it doesn't (and should not) know where to get the functions code being called, this is the linker's task. But static libraries are not linked with dynamic ones when being built. That's why the linking information necessary to link an application to a dynamic library is lost when the dynamic library functions are used through static library wrappers.
So we have to provide all necessary linking information to our iPhone application manually.
At the moment two dynamic libraries are used by Remoting SDK:

  • libxml2.dylib
  • Security.framework

For future releases, additional libraries may be required. We are keeping this FAQ section up to date so if you encounter linker errors after Remoting SDK or Data Abstract upgrade please check this section for changes.

Referencing libxml2.dylib

The simplest way to reference libxml2 is to specify additional linker options. To do this navigate to your target Build Settings in Xcode and locate the Other Linker Flags parameter:



This is enough for the linker to locate the required libxml2.dylib copy.

Referencing Security.framework

Go to your project's target settings in Xcode, navigate to Build Phases and add Security.framework to the Link Binary With Libraries list: