Skip to content

Using the SDK

Meredith Monticello edited this page Mar 16, 2017 · 11 revisions

Using the SDK

The simplest way to get started is to clone and run one of sample apps. We recommend starting with the WOCCatalog sample app, which demonstrates an assortment of iOS and XAML UI controls.

To run the sample:

  1. Clone the repo
  2. Navigate to winobjc/samples/WOCCatalog
  3. Double-click on WOCCatalog-WinStore10.sln to open in VS2015
  4. In VS2015, right-click on the WOCCatalog (Universal Windows) project
  5. Select "Set as start up project"
  6. Use Ctrl-F5 to build and run the app

Looking beyond the samples, there are two ways to use the SDK. The first is to use the vsimporter tool to import your existing Xcode project into a Visual Studio solution and the second is to instead add Objective-C functionality to a new or existing Visual Studio project.

Visual Studio project properties

With the correct NuGet Packages installed, the Properties panel for your project (in Visual Studio) presents you with several new categories of options. Some key options are listed below.

Item type

Right click on a file in the Visual Studio solutions explorer, and click on Properties. Under the General section, you should see a field called Item Type.

FileProperties

This field tells Visual Studio about the type of each file in a project. By default, Visual Studio should automatically set .m and .mm files to be of type Clang source (this ensures that they are built with the correct compiler – clang rather than cl). Similarly, c++/cx files (.cpp extension) should continue to be set as C/C++ compiler type.

Another important item type is Starboard Resource. Items set to this type are copied into the app package, which is useful for application assets.

These types should be set automatically, but you can use the menu to override the default behavior or correct any issues.

Clang

In the Visual Studio solution explorer, right-click on your project and click Properties. You should a set of properties under Clang.

ProjectProperties

This process can be used to see/edit properties related to building .m and .mm files. For example, you can see whether or not ARC is enabled or specify the #include paths that are relevant to building these files.

Using Windows APIs from Objective-C

There are a few different ways to leverage Windows APIs from your Objective-C app. Specifically, you can either add .cpp files to your project and, from there, leverage c++/cx or you can alternatively use Windows APIs directly from Objective-C.

To support direct usage of Windows APIs, the WinObjC.Frameworks.UWP package (included as a dependency of the WinObjC.Frameworks package) contains a set of header files and libraries, which map to each Windows namespace. For example, WSystem.h maps to the Windows::System namespace and this header file contains an Objective-C projection of the APIs in that namespace. Similarly, classes are prefixed with the letters that constitute their containing namespace, so Windows::System::Launcher is presented as an Objective-C @interface named WSLauncher.

To see a detailed example of directly calling Windows APIs in Objective-C, take a look at our WOCCatalog sample app.

Add *.cpp and use cx/Windows APIs

Take a look at the Samples (specifically look for a cpp folder in the appropriate sample) and additional Documentation for Windows App Development.

Async APIs

Asynchronous operations are supported through Objective-C via callbacks to blocks. For example, the Objective-C signature for launchUriAsync is:

+ (void)launchUriAsync:(WFUri *)uri success:(void (^)(BOOL))success failure:(void (^)(NSError*))failure;

The important parts are the success: and failure: parameters, these blocks are invoked with the given parameters when the async operation succeeds or fails respectively. All async APIs are exposed to Objective-C using this same pattern.

Constructors

Looking at the async example again, you can see that it requires a WFUri. This is defined in WFoundation.h and you can create one using the following method in WFUri:

+ (WFUri *)createUri:(NSString *)uri;

In c++ the Uri class has a normal constructor of Uri(String^ uri). However, in Objective-C constructors are mapped to static create methods. When constructors take multiple parameters, the parameter names are hard-coded into the Objective-C function signature:

+ (WFUri *)createWithRelativeUri:(NSString *)baseUri relativeUri:(NSString *)relativeUri;

Type interoperability

Looking again at the createUri constructor, notice that it takes an NSString as a parameter. This usage is possible, because the interop layer allows you treat HSTRINGs as NSStrings and vice versa.

Similarly, looking at the Windows::Networking::Connectivity::ProxyConfiguration class in C++, you can see the ProxyUris property:

property IVectorView<Uri^>^ ProxyUris {
    IVectorView<Uri^>^ get();}

This property is used to access a list (an IVectorView) of ProxyUris. When projected into Objective-C, the property appears as follows:

@property (readonly) NSArray * /*WFUri*/ proxyUris;

The IVectorView is mapped into an NSArray and, therefore, this API may be used from Objective-C by using the built in NSArray type.

Interoperability for other types (enumerators, maps, etc.) is still under development.

Event registration

Similarly to async functionality, event handlers can be provided using Objective-C blocks. For an example of this, see winobjc/samples/WOCCatalog:

[xamlWebView addLoadCompletedEvent: ^void(RTObject * sender, WUXNNavigationEventArgs * e)
{
    _welcomeLabel.text = e.uri.rawUri;
}];

XAML interoperability

Even though your app might be using UIKit, WinObjC uses the XAML compositor to manage your views and perform animations on them. This functionality is implemented by tying CALayers to XAML elements. For most standard use cases, such as getting your iOS/UIKit/OpenGL app running, this implementation detail doesn't really matter. You can continue to use UIKit and CoreAnimation as you’re used to.

However, when combined with Windows API interoperability, this approach makes certain use cases, such as mixing-and-matching UIKit and XAML components, simple and straight forward. You can, for example, create a XAML webview and place it in your UIKit based application:

// Create the Windows::Xaml::Control::WebView and set the destination URL
WXCWebView *xamlWebView = [WXCWebView create];
[xamlWebView navigate: [WFUri createUri: @"http://www.bing.ca"]];

// Create a CALayer and add the Xaml control to that layer
CALayer *nativeLayer = [CALayer new];
nativeLayer.masksToBounds = TRUE;
[nativeLayer setBackgroundColor: [UIColor greenColor]];
[nativeLayer setFrame: CGRectMake(80, 200, 450, 250)];

//  Set contents of the CALayer to be a native Xaml Element
[nativeLayer setContentsElement: xamlWebView];

xamlWebView.Width = 850;
xamlWebView.Height = 550;

// Add the layer to the containing window
[[_mainWindow layer] addSublayer: nativeLayer];

See winobjc/samples/WOCCatalog for more extensive use of this functionality.

Usage of STUB_METHOD/STUB_PROPERTY macros

We introduced a large number of framework stubs in the 160218 release which contain headers that match the iOS 9.1 SDK. These framework stubs have stub implementations that typically return stub values (usually 0).

Reasoning We want app developers to be able to compile, link and run their iOS apps on Windows 10 as quickly and easily as possible. Stubbing the iOS framework surface area allows developers to see where degraded functionality lies and focus their attention on the areas that need work. This is the approach we have taken internally to support apps using the Islandwood platform.

How it works The methods and properties that are stubs have the STUB_METHOD and STUB_PROERTY macros respectively after them. For example:

GAMEPLAYKIT_EXPORT_CLASS
@interface GKNSPredicateRule : GKRule
- (instancetype)initWithPredicate:(NSPredicate*)predicate STUB_METHOD;
@property (readonly, retain, nonatomic) NSPredicate* predicate STUB_PROPERTY;
- (BOOL)evaluatePredicateWithSystem:(GKRuleSystem*)sys STUB_METHOD;
@end

If your app uses any of these methods or properties, you will get a build time warning that will give you an idea of the missing APIs you may be using. The warning will be of the sort:

Warning: method x is deprecated: it is not implemented

How to turn the warnings off Define NO_WARN_STUBS in your project file.

How to cause build errors instead of warnings Define NO_STUBS in your project file.

Known issues Frameworks foundation and UIKit have some incorrect STUB_* macros in them. We are working on cleaning them up.

Testing with the Microsoft Emulator for Windows 10 Mobile

Even without a Windows Phone, you can test the look and feel of your application with the Microsoft Emulator for Windows 10 Mobile.

Installing the Microsoft Emulator for Windows 10 Mobile

First, make sure you have downloaded and installed the emulator. If you have already installed Visual Studio 2015 Update 2, the emulator should also have been installed as part of the Windows Software Development Kit (SDK) for Windows 10. If that’s not the case, get the standalone SDK here. Once the download is complete, double click the SDK setup executable and follow the installation wizard.

Using the Microsoft Emulator for Windows 10 Mobile

Once the emulator is installed, open the application project you want to test in Visual Studio. Then, select x86 or Win32 as the solution platform and choose the desired emulator as the target from the drop-down list next to the Start Debugging button.

Finally, just click on the Start Debugging button and the emulator will launch. For more information on the Microsoft Emulator for Windows 10 Mobile, check the emulator documentation on the Windows Dev Center.

Known Issues of the Microsoft Emulator for Windows 10 Mobile

  • ARM emulation is not supported by the emulator. However, the applications will behave the same way since ARM and x86 Windows 10 Mobile images are put together using the same code base. If you want to test for ARM, you’ll need a physical Windows Phone.
  • Even if the emulator was designed to provide a comparable performance to an actual device, its performance will not exactly match the one of a physical device since the emulator uses the processor and GPU of your development machine. For performance testing, we recommend that you test your app on a physical device before publishing to the Windows Store.

##Modifying an iOS app for Windows While the Windows Bridge for iOS provides support for Objective-C within a UWP app, there are some differences between the iOS and Windows platform that might necessitate code modifications or additions.

###Screen size and resolution Windows supports a wide variety of form factors and screen sizes. For a good user experience, your app should be aware of and respond to the configuration on which it's run. That means, at startup your app needs to specify:

  • How large (width/height) it should be
  • What magnification it should render at
  • How window resize should be handled

To specify these behaviors, simply create a Category for your UIApplication in your AppDelegate called UIApplicationInitialStartupMode

@interface UIApplication(UIApplicationInitialStartupMode)

You can then add a method setStartupDisplayMode that is called at startup and define the appropriate settings using a WOCDisplayMode object.

+(void) setStartupDisplayMode: (WOCDisplayMode*) mode { ... }

There are a number of properties exposed by the WOCDisplayMode object, but for simplicity the DisplayPreset property can be used to set behavior to several predefined configurations.

  • WOCDisplayPresetPhone320x480: Configures a phone app with 320x480 resolution
  • WOCDisplayPresetTablet768x1024: Configures a tablet app at 768x1024
  • WOCDisplayPresetNative: Configures app to use the size and aspect ratio of the containing window
  • WOCDisplayPresetNative2x: Configures app to use the size and aspect ratio of the containing window, as well as apply a 2x magnification

If you'd like to instead manually configure properties of the WOCDisplayMode object, the following are available.

  • autoMagnification: This property can be used, along with a fixedWidth and fixedHeight, to handle window size changes by simply "zooming" in/out. The pixel width/height of your app will remain constant (as specified below) but the magnification will change with window size.

  • sizeUIWindowToFit: This property resizes the application windows along with the containing window. If this is set to FALSE then the application will remain at the specified (original) size irrespective of its containing window.

  • fixedWidth: This property specifies the width, in pixels, of the application. If set to "0" then the width of the application will follow the width of the containing window.

  • fixedHeight: This property specifies the height, in pixels, of the application. If set to "0" then the height of the application will follow the height of the containing window.

  • fixedAspectRatio: If this property is set to 0 then the app has no fixed aspect ratio. However, if it has a non-zero value, then the provided aspect ratio will be maintained throughout any resizing operations.

  • magnification: If this property is set to 0 then the application may zoom in/out as the window is resized. However, if set to a non-zero value then the magnification is fixed and this may be used to increase app size on high resolution displays.

For example, add the following code to AppDelegate.m to create an app with a window of a fixed size:

#ifdef WINOBJC
@implementation UIApplication(UIApplicationInitialStartupMode)
+(void) setStartupDisplayMode: (WOCDisplayMode *) mode {
    mode.autoMagnification = FALSE;
    mode.sizeUIWindowToFit = TRUE;
    mode.fixedWidth = 1024;
    mode.fixedHeight = 768;
    mode.magnification = 1.0;
}
@end
#endif

For a detailed walkthrough of handling screen resolution, take a look at DisplayModeViewController.m and AppDelegate.m in the WOCCatalog sample. To see the complete interface, you can view include/UIKit/UIApplication.h.

Clone this wiki locally