iOS

Guide and API to work with the SDK for iOS (Swift & Objective-C)

Download the iOS SDK from https://developers.wakingapp.com/#download

Integration with XCode 10

General information

The WakingApp Viewer SDK for iOS is an arm64 framework (supported by iPhone 5s and newer devices).
This framework contains Bitcode.
Bitcode allows apple to build your app specifically for each device's hardware, delivering each version of the app to its designated device when downloaded from the app store.

Regardless of the SDK's size- once the app is in the Appstore, our framework adds approx. 8MB to your final app's size.

Adding the framework to a new (or existing) XCode project

Step 1: Drag and drop the framework file into your project's folder

Step 2: Add the framework to the list of embedded binaries

Your configuration should look like this:

Additional step for swift based projects

Generate a bridging header to gain access to the framework's headers

If your project does not contain such a header already, you'll need to create a new Header File.

Click on the Build Settings tab and find the "Swift Compiler - General" block. Edit "Objective-C Bridging Header" with a relative path to the newly created header.

The contents of the header file:

#ifndef arproj_bridging_header_h
#define arproj_bridging_header_h

#import <WA3DLib/ARViewController.h>
#import <WA3DLib/WAPublishServerManager.h>

#endif /* arproj_bridging_header_h */

Info.plist

You must edit your Info.plist file to contain the NSCameraUsageDescription key since camera access in mandatory for AR.

Now you're all set up and ready to use the SDK

Initializing the WakingApp Viewer SDK

The Viewer SDK exposes an 'all-in-one' ViewController named ARViewController
Basically, all you need to do in order to get Camera stream & 3D rendering is to set your own ViewController to derive from this class.

Deriving from ARViewController

Swift:

Objective-C:

👍

Build & Run

Install the app on your device.
You should see the camera stream, rendered in the view.

❗️

Simulation

Since Augmented Reality is designed for the actual device's sensors and camera stream, You cannot build your project for a simulator - You can only test it on an actual device!

🚧

ViewController's View must be set up on the entire screen

Your view controller must be set up correctly, so its view is placed on the entire device's screen (This is the default for new apps).

This is crucial for correct camera stream rendering and placement of 3D scenes.

Loading a project

From local storage (Compiled with the app)

Drag and drop your project file onto the app's folder, to include it in the final build. Make sure to mark the app in the "Add to targets" field so it will be copied upon compilation.

📘

An exported project file for testing the integration can be downloaded from here.

Implement the WAEngineDelegate interface in ViewController.h & ViewController.m (Objective-C) or ViewController.swift (Swift) and call loadProject

///////////////////
//ViewController.h:
///////////////////
#import <UIKit/UIKit.h>
#import <WA3DLib/ARViewController.h>
#import <WA3DLib/WAPublishServerManager.h>

@interface ViewController : ARViewController <WAEngineDelegate>

@end
  
///////////////////
//ViewController.m:
///////////////////
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self setDelegate:self]; // so that OnProjectLoaded/OnSceneLoaded will be called
    NSString *path = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"wa"]; // get file path
    [self loadProject:path];
}
- (void)onProjectLoaded:(WAProjectLoadStatus)loadSuccessful :(NSString *)projectName :(NSString *)projectFilepath :(NSString *)trackType{
  if(loadSuccessful == LoadSuccess) {
        NSLog(@"Project %@ loaded successfully", projectName);
    }
}
-(void)onSceneLoaded : (bool)loadSuccessful :(NSData*)targetImageBytes
{
    if(loadSuccessful) {
        NSLog(@"Scene loaded successfully");
    }
}
@end
//  ViewController.swift

import UIKit

class ViewController: ARViewController, WAEngineDelegate {

    func onProjectLoaded(_ loadSuccessful: Bool, _ projectName: String!, _ projectFilepath: String!, _ trackType: String!) {
        if(loadSuccessful) {
        NSLog("Project %@ loaded successfully", projectName);
            }
    }
    
       func onSceneLoaded(_ loadSuccessful: Bool,_ targetImageBytes: Data!) {
        if(loadSuccessful) {
        NSLog("Scene loaded successfully");
            }
    }
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setDelegate(self); // so that OnProjectLoaded/OnSceneLoaded will be called
        let projectPath = Bundle.main.path(forResource: "test", ofType: "wa");// get file path
        loadProject(projectPath);
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

If you've used the test project - scan the image below to see a model with animation:

You can unload the project by calling unloadCurrentProject available in ARViewController.

[self unloadCurrentProject];
unloadCurrentProject();

From A Publish server (Downloading at runtime)

Implement WADownloadDelegate interface in ViewController.h & ViewController.m (Objective-C) or ViewController.swift (Swift).

There are several functions that this delegate contains which will be triggered:

+ downloadStarted // triggered when the link is verified as an actual WakingApp AR Studio project link
+ downloadProgress // triggered when download progress is made
+ downloadComplete // triggered when the download is done (or immediately if the file is already cached on this device)
+ downloadError // triggered when there's an error in verifying the project link / the download is corrupt
///////////////////
//ViewController.h:
///////////////////
#import <UIKit/UIKit.h>
#import <WA3DLib/ARViewController.h>
#import <WA3DLib/WAPublishServerManager.h>

@interface ViewController : ARViewController <WAEngineDelegate, WADownloadDelegate>

@end
  
///////////////////
//ViewController.m:
///////////////////
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self setDelegate:self]; // so that OnProjectLoaded/OnSceneLoaded will be called
    [[WAPublishServerManager instance] setDelegate:self]; // so that all download functions will be called
    [[WAPublishServerManager instance] downloadOrLoadProject:@"https://wa.mg/BgQaHt-VV"];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)downloadStarted:(NSString *)url {
    NSLog(@"Download Started");
}
- (void)downloadProgress:(NSString *)url :(float)progress {
    NSLog(@"Download Progress: %f", progress);
}
- (void)downloadComplete:(NSString *)url :(NSString *)localPath :(BOOL)fromCache {
    NSLog(@"Download Completed");
    [self loadProject:localPath];
}

- (void)downloadError:(NSString *)url :(NSString *)errorMessage {
    NSLog(@"Download Error %@", errorMessage);
}

- (void)searchComplete:(NSArray *)results {

}


- (void)onProjectLoaded:(bool)loadSuccessful :(NSString *)projectName :(NSString *)projectFilepath :(NSString *)trackType {
    if(loadSuccessful) {
        NSLog(@"Project %@ loaded successfully", projectName);
        }
}
-(void)onSceneLoaded : (bool)loadSuccessful :(NSData*)targetImageBytes
{
    if(loadSuccessful) {
        NSLog(@"Scene loaded successfully");
    }
}

@end
//  ViewController.swift


import UIKit

class ViewController: ARViewController, WADownloadDelegate, WAEngineDelegate {
    func downloadStarted(_ url: String!) {
        NSLog("Download Started");
    }
    
    func downloadProgress(_ url: String!, _ progress: Float) {
        NSLog("Download Progress: %f", progress);
    }
    
    func downloadComplete(_ url: String!, _ localPath: String!, _ fromCache: Bool) {
        NSLog("Download Completed");
        loadProject(localPath);
    }
    
    func downloadError(_ url: String!, _ errorMessage: String!) {
        NSLog("Error for url: %@ message: %@", url, errorMessage);
    }
    
    func searchComplete(_ results: [Any]!) {
        
    }
    
    //Happens once a project is loaded
    func onProjectLoaded(_ loadSuccessful: Bool, _ projectName: String!, _ projectFilepath: String!, _ trackType: String!) {
        if(loadSuccessful) {
        NSLog("Project %@ loaded successfully", projectName);
            }
    }
    
       func onSceneLoaded(_ loadSuccessful: Bool,_ targetImageBytes: Data!) {
        if(loadSuccessful) {
        NSLog("Scene loaded successfully");
            }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.setDelegate(self); // so that OnProjectLoaded/OnSceneLoaded will be called
        let psManager = WAPublishServerManager.instance() as! WAPublishServerManager;
        psManager.setDelegate(self); // so that all download functions will be called
        psManager.downloadOrLoadProject("https://wa.mg/BgQaHt-VV");
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    
}

The Project link at https://wa.mg/BgQaHt-VV can be downloaded through the SDK.
It is a SLAM based project with some logic in it.
Move your devices slowly, in order to scan a surface - upon tapping the device's screen the model will 'snap' to the found surface, tapping it again will cause it to move along the found surfaces.

The WAPublishServerManager class automatically manages any download, caches it on the device (like web browsers do) and uses a checksum validation in order to test whether to download the file or load it from cache the next time the a request to the same link is made.

You're able to delete the cache by calling WAPublishServerManager's deleteCache method:

[[WAPublishServerManager instance] deleteCache];
(WAPublishServerManager.instance() as! WAPublishServerManager).deleteCache();