Documentation

Project Setup

There are only a few steps necessary to add the Wikitude SDK to your iOS application. This guide will explain them in detail.

Loading your Xcode project

The first step is to open an existing Xcode project. If there is no project already created, do so using the Xcode project configurator.

Adding the Wikitude SDK Framework

To keep things clear, you should copy the Wikitude Native SDK .framework into your Xcode project structure. Having it somewhere else on your machine might lead to confusion when updating to a newer version of the Wikitude Native SDK.

After the .framework was copied, it can be added as Embedded Binaries.

Addressing multiple architectures in Xcode 12.3

Xcode 12.3 introduced a change that affects all iOS legacy frameworks that include support for multiple architectures. Since our framework includes device support (arm64) and iOS simulator support (x86_64), you will run into this compilation error:

Building for iOS, but the embedded framework 'WikitudeSDK.framework' was built for iOS + iOS Simulator.

We are working on a long-term solution. In the meantime, you can work around this issue by running either of the following commands from your CLI, depending on your use case.

  • To build your app for an iOS device, strip our framework from all architecture support except for arm64:

    lipo -thin arm64 /path/to/WikitudeSDK.framework/WikitudeSDK -output /path/to/WikitudeSDK.framework/WikitudeSDK
    
  • To build your app for the iOS simulator, keep the x86_64 architecture instead:

    lipo -thin x86_64 /path/to/WikitudeSDK.framework/WikitudeSDK -output /path/to/WikitudeSDK.framework/WikitudeSDK
    

If you are going to be building for both, we suggest you make a copy of the original framework file and run the command for each architecture on each framework. In this case, you will need to import in your project only the framework intended for the platform you are targeting before building.

Setting up simulator builds in Xcode 12

Due to the recent changes in Xcode 12, by default, ARM has priority over any other architecture when building for the iOS Simulator.

Our SDK supports ARM and x86, so if you launch a simulator build, Xcode will find ARM support and attempt to build for it instead of x86. This will provoke a linker error. To prevent it, we need to manually specify the x86 architecture for Simulator builds, following these steps:

  1. Select the target you want to build and open its Build Settings. In the Architectures row, select the mode you intend to build for and press its + button.

  2. Click on Any SDK in the new row and select Any iOS Simulator from the dropdown.

  3. Click on the row's value and select Other... to specify the architecture manually.

  4. Replace the existing value with x86_64.

  5. Make sure to repeat the steps above for all the build modes in your project that need to run in the Simulator. Your architecture settings should end up looking somewhat like this:

Using the Wikitude Native SDK in your Application

After the setup step is completed, the Wikitude Native SDK is ready to be used within an iOS application.

The Wikitude Native SDK comes with an umbrella header that has to be included in your corresponding source files. The file is called WikitudeNativeSDK.h and can be imported by calling #import <WikitudeNativeSDK/WikitudeNativeSDK.h>

The main class to work with is WTWikitudeNativeSDK. It's the central point for creating trackers, to obtain an already configured rendering component or to control camera related settings.

The Wikitude Native SDK can be used in trial mode without any paid license, but to remove the watermark, a valid license has to be set using the -setLicenseKey: method.

Application Lifecycle

To integrate the Wikitude Native SDK into the application lifecycle, use the -start:completion: and -stop methods of WTWikitudeNativeSDK. A good place to call them is e.g. a UIViewControllers -viewWillAppear: and -viewWillDisappear:. To refine the startup phase, the WTStartupConfiguration object can be used which is the first arguments in the first block parameter of -start:completion:. The second block parameter can be used to check if the Wikitude Native SDK could actually start with the given configuration on the current device. Use the isRunning parameter to determine the run state and e.g. create tracker in this block. The following listening demonstrates this:

[self.wikitudeSDK start:nil completion:^(BOOL isRunning, NSError * __nonnull error) {
    if ( !isRunning ) {
        NSLog(@"Wikitude SDK is not running. Reason: %@", [error localizedDescription]);
    }
    else
    {
        __weak typeof(self) weakSelf = self;

        NSURL *imageTrackerResourceURL = [[NSBundle mainBundle] URLForResource:@"magazine" withExtension:@"wtc" subdirectory:@"Assets"];
        self.targetCollectionResource = [self.wikitudeSDK.trackerManager createTargetCollectionResourceFromURL:imageTrackerResourceURL completion:^(BOOL success, NSError * _Nullable error) {
            if ( !success )
            {
                NSLog(@"Failed to load URL resource. Reason: %@", [error localizedDescription]);
            }
            else
            {
                weakSelf.imageTracker = [weakSelf.wikitudeSDK.trackerManager createImageTrackerFromTargetCollectionResource:weakSelf.targetCollectionResource delegate:weakSelf configuration:nil];
            }
        }];
    }
}];

Authorization requesting

In order to use features involving camera or location usage, you will need to declare the following items in your Info.plist file:

Then you should request camera and/or location access.

In addition to the standard way of requesting authorizations from the user, we also provide an authorization request manager to make the process easier for developers.

You only need to import it:

#import <WikitudeNativeSDK/WTAuthorizationRequestManager.h>

Then declare it as a variable:

@property (nonatomic, strong) WTAuthorizationRequestManager *authorizationRequestManager;

Take somewhere like -viewDidLoad: to initialize it:

if ( !_authorizationRequestManager )
{
    self.authorizationRequestManager = [[WTAuthorizationRequestManager alloc] init];
}

And use it whenever you need to request authorizations:

if ( !_authorizationRequestManager.isRequestingRestrictedAppleiOSSDKAPIAuthorization ) {
    WTFeatures requiredFeatures = WTFeature_ImageTracking;
    NSOrderedSet<NSNumber *> *restrictedAppleiOSSDKAPIs = [WTAuthorizationRequestManager restrictedAppleiOSSDKAPIAuthorizationsForRequiredFeatures:requiredFeatures];

    [_authorizationRequestManager requestRestrictedAppleiOSSDKAPIAuthorization:restrictedAppleiOSSDKAPIs completion:^(BOOL success, NSError * _Nonnull error) {
        if (success) {
            [self authorizationSuccessful];
        } else {
            [self authorizationFailed];
        }
    }];
}

WTFeatures is an NSUInteger that represents the SDK features you need, which in this case is only image tracking. You can add multiple features with the OR bitwise operator, such as WTFeatures requiredFeatures = WTFeature_ImageTracking | WTFeature_Geo;

Error Handling

The Wikitude Native SDK calls the WTWikitudeNativeSDK delegate method -wikitudeNativeSDK: didEncounterInternalError: as soon as an internally inconsistent state was detected and parts of the SDK might stop working as expected. This is especially helpful while developing the application and not so much for end user notifications.

Trackers, Camera and Rendering

How trackers, the camera controls and rendering can be used, will be explained in the example part of this documentation. Each feature will be explained in detail through a real usage example.

Using the Wikitude Native SDK in Swift

The Wikitude Native SDK is written in Objective-C and is thereby naturally compatible with Apple's Swift programming language. To use the Wikitude Native SDK in Swift, create a bridging header by creating some new empty Objective-C file with Xcode. Xcode will ask you if you want to create a bridging header, so please confirm that and the header will be created. You can delete the empty Objective-C file. After that simply add the following line to the bridging header:

#import <WikitudeNativeSDK/WikitudeNativeSDK.h>

You can now call all the interfaces of the Wikitude Native SDK from Swift. Add all the additional Objective-C headers you need to the bridging header in order to expose their classes to Swift. Xcode automatically generates Swift-interfaces for them.

Swift and Input Plugins

Swift can call Objective-C and Objective-C++ code naturally, but does not have the capability to call C++ code. In order to get input plugins running, you have to create Objective-C++ wrapper classes as intermediates to enable the Swift-C++ communication. Don't forget to expose the wrapper classes to Swift by importing them in the bridging header.

This is the implementation of one of the wrapper classes from our Swift examples, in which we add a C++ barcode reader into our app:

@implementation BarcodePluginWrapper
{
    std::shared_ptr<wikitude::sdk::Plugin> _plugin;
}

- (id)initWithCameraWidth:(int)cameraWidth :(int)cameraHeight :(UIViewController *) viewController
{
    self = [super init];
    if (self)
    {
        _plugin = std::make_shared<BarcodePlugin>(cameraWidth, cameraHeight, viewController);
    }
    return self;
}

- (void)registerPluginWithSDK:(WTWikitudeNativeSDK *)sdk;
{
    NSError *error = nil;

    BOOL pluginRegistered = [sdk registerPlugin:_plugin error:&error];
    if ( !pluginRegistered )
    {
        NSLog(@"Unable to register plugin '%@'. Error: %@", [NSString stringWithUTF8String:_plugin->getIdentifier().c_str()], [error localizedDescription]);
    }
}

- (void)removePluginFromSDK:(WTWikitudeNativeSDK *)sdk
{
    [sdk removePlugin:_plugin];
}

@end

Swift can't handle the std::shared_ptr that points to the plugin, so we're storing it in our Objective-C++ wrapper. For the initialization of this plugin we need two integer values as well as a UIViewController. Change your init method accordingly depending on which parameters you need for your own plugin. Every input plugin needs to be able to register to and unregister from the Wikitude Native SDK, so we create methods for both purposes.