Search code examples
iosxamarin.iosxamarinios-simulatorquickblox

Xamarin iOS project with reference to binding launches on sim but not on device


I am creating the monotouch bindings to the Quickblox chat service. I successfully did this on a previous version (1.9.x) but on the 2.0.2 library, having problems getting the new binding to launch on the device. It launches on the simulator fine. Guessing it is a problem with linker flags, but have run out of ideas.

The binding project compiles fine. The DLL is created and I can reference it in my host project. Running the host project in the simulator works fine. On an actual device, the app launches but the process crashes before getting past the black screen. No output in the Xamarin Studio "Application Output" window. Just nothing. Any way I can insert some debug info to figure out what is going wrong?

Quickblox provides an iOS sample project with the following settings:

Other Linker Flags: -lstdc++ -ObjC -lxml2

Link Binary With Libraries:

libxml2.2.dylib libresolv.9.dylib libz.1.2.5.dylib
AVFoundation.framework CoreVideo.framework Quickblox.framework Accelerate.framework CoreMedia.framework AudioToolbox.framework CoreLocation.framework CoreDate.framework CoreGraphics.framework MobileCoreServices.framework SystemConfiguration.framework CFNetwork.framework UIKit.framework Foundation.framework

Here is my "linkwith.cs" file in my binding project:

using System;
using MonoTouch.ObjCRuntime;

[assembly: LinkWith ("libQuickblox.a", LinkTarget.ArmV7 | LinkTarget.ArmV7s | LinkTarget.Simulator, ForceLoad = true, Frameworks = "CFNetwork SystemConfiguration MobileCoreServices CoreGraphics CoreLocation CoreData AudioToolbox CoreMedia Accelerate CoreVideo AVFoundation Security", LinkerFlags = "-lxml2 -lz -lresolv -ObjC -lstdc++")]

I have tried this on two iPhone 5 devices, both running iOS 7.1

If I comment out this particular class (QBRequest.h) in the binding, the project will launch on the device. It tells me there is something with binding to that particular class. That class inherits from NSObject and does not import any other libraries, so there is nothing that raises any obvious concerns.

#import <Foundation/Foundation.h>

@class QBRequest;
@class QBResponse;
@class QBRequestStatus;

@protocol QBResponseSerialisationProtocol;
@protocol QBRequestSerialisationProtocol;
@class QBHTTPRequestSerialiser;

extern const struct QBRequestMethod {
    __unsafe_unretained NSString *POST;
    __unsafe_unretained NSString *GET;
    __unsafe_unretained NSString *HEAD;
    __unsafe_unretained NSString *PUT;
    __unsafe_unretained NSString *DELETE;
} QBRequestMethod;

typedef void (^QBRequestStatusUpdateBlock)(QBRequest *request, QBRequestStatus *status);
typedef void (^QBRequestCompletionBlock)(QBRequest *request, QBResponse *response, NSDictionary *objects);

typedef void (^QBRequestErrorBlock)(QBResponse *response);


@interface QBRequest : NSObject

@property (nonatomic, getter=isCancelled, readonly) BOOL canceled;

@property (nonatomic, copy) QBRequestCompletionBlock completionBlock;
@property (nonatomic, copy) QBRequestStatusUpdateBlock updateBlock;

@property (nonatomic, strong) QBHTTPRequestSerialiser<QBRequestSerialisationProtocol> *requestSerialisator;

// QBHTTPResponseSerialiser<QBResponseSerialisationProtocol>
@property (nonatomic, strong) NSArray *responseSerialisators;

@property (nonatomic, copy) NSDictionary *headers;
@property (nonatomic, copy) NSDictionary *parameters;
@property (nonatomic, copy) NSData *body;

@property (nonatomic) NSStringEncoding encoding;

- (instancetype)initWithCompletionBlock:(QBRequestCompletionBlock)completionBlock;
- (instancetype)initWithUpdateBlock:(QBRequestStatusUpdateBlock)updateBlock completionBlock:(QBRequestCompletionBlock)completionBlock;

- (void)cancel;

@end

The binding entry in my ApiDefinition.cs file is this:

[BaseType (typeof (NSObject))]
public partial interface QBRequest {

    [Export ("canceled")]
    bool Canceled { [Bind ("isCancelled")] get; }

    [Export ("completionBlock", ArgumentSemantic.Copy)]
    RequestCompletionDelegate CompletionBlock { get; set; }

    [Export ("updateBlock", ArgumentSemantic.Copy)]
    RequestCompletionDelegate UpdateBlock { get; set; }

    [Export ("headers", ArgumentSemantic.Copy)]
    NSDictionary Headers { get; set; }

    [Export ("parameters", ArgumentSemantic.Copy)]
    NSDictionary Parameters { get; set; }

    [Export ("body", ArgumentSemantic.Copy)]
    NSData Body { get; set; }

    [Export ("encoding")]
    NSStringEncoding Encoding { get; set; }

    [Export ("initWithCompletionBlock:")]
    IntPtr CreateWithCompletionDelegate (RequestCompletionDelegate completionBlock);

    [Export ("initWithUpdateBlock:completionBlock:")]
    IntPtr CreateWithStatusUpdateDelegate (RequestStatusUpdateDelegate updateBlock, RequestCompletionDelegate completionBlock);

    [Export ("cancel")]
    void Cancel ();
}

Thanks for your ideas!!


Solution

  • Check the device console logs (hints just before the crash) and the crash report itself.

    Problem is that there are no crash logs being generated

    You should see something (every app that starts logs something) in the device console logs.

    Also check the device logs it's possible there's not enough space left to save new crash reports.

    Device console logs reveals some truth. The exception is being thrown by the QBRequest static initializer.

    Exactly.. the crash logs were full. The device console revealed that too.