Objective-C frameworks in Swift's world
Published: 2024-04-05 10:45:16

<!-- wp:paragraph -->
<p>In this article I'll take you to a journey of improving <code><a href="https://www.scichart.com/ios-chart-features/">SciChart.framework</a></code> consumption in the <a href="https://swift.org/about/">Swift</a> world. Despite the fact there's plenty of articles about <em><strong>Objective-C to Swift</strong></em> and <em><strong>Swift to Objective-C </strong></em>interoperability, and all of the techniques are well-known – I'm going to share the <a href="http://scichart.com/">SciChart</a> perspective onto this topic. As well as sharing particular use-cases we faced during this process.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Here at <a href="http://scichart.com/">SciChart</a> we have quite a lot of shared C++ code. Our underlying graphics engine is written mostly in <code>C++</code> and that's why we do have quite a lot Objective-C++ files to bridge between languages. This allows us to share this "mission-critical" part of our library across all our platforms - <a href="https://www.scichart.com/ios-chart-features/">iOS/macOS</a>, <a href="https://www.scichart.com/android-chart-features/">Android</a>, <a href="https://www.scichart.com/wpf-chart-features/">WPF/Windows</a> and <a href="https://www.scichart.com/javascript-chart-features/">JavaScript/Web</a>. This gives us top-notch performance as well as ability to easily support OpenGL (which we still do). We also have many customers that are using Objective-C, which with the above means that it's quite unlikely if not impossible to to fully rewrite our Framework in Swift in the foreseeable future.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Despite the fact that out-of-the box <a href="https://developer.apple.com/documentation/swift/objective-c_and_c_code_customization">Objective-C → Swift interoperability</a> is quite good, we decided to go an extra mile here and take care of making our Objective-C API's a top-notch experience from the Swift side, doing the <a href="https://developer.apple.com/videos/play/wwdc2020/10680/">same as Apple does </a>with it's own frameworks. But it's not possible to cover all possible techniques in one article, so I will focus only on the ones listed below:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li><a href="#nullability-annotations">Nullability annotations</a></li><li><a href="#initializers-designation-and-availability">Initializers - designation and availability</a></li><li><a href="#just-for-swift-refinements">Just for Swift refinements</a></li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>If you are not interested in detailed information about improving Swift API's for Objective-C frameworks - feel free to scroll down directly to the <a href="#summary">Summary</a><em><em><strong>.</strong></em></em></p>
<!-- /wp:paragraph -->

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

<!-- wp:heading -->
<h2 id="nullability-annotations">Nullability annotations</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>This one is pretty self explanatory as it allows you to annotate all of your APIs and tell everyone to expect something that <strong>can be</strong> <code>null</code>, or that <strong>will never be</strong> <code>null</code>. So we went through our code and marked all of it with the nullability annotation, either explicitly by hand or using handy macro, which covers block of codes or even files in some cases:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li><code>NS_ASSUME_NONNULL_BEGIN</code></li><li><code>NS_ASSUME_NONNULL_END</code></li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>and now instead of having whole bunch implicitly unwrapped optional:</p>
<!-- /wp:paragraph -->

<!-- wp:scichart/code-snippet {"code":"xAxis.currentInteractivityHelper?.scroll(xAxis.visibleRange, byPixels: 100)nif let yValue = seriesInfo?.formattedYValue {nt// Only now do something with unwrapped valuen}nif let strokeStyle = seriesInfo?.renderableSeries?.strokeStyle { nt// Only now do something with unwrapped valuen}","proglang":"language-swift"} -->
<div class="wp-block-scichart-code-snippet"><pre class="line-numbers code-toolbar language-swift">xAxis.currentInteractivityHelper?.scroll(xAxis.visibleRange, byPixels: 100)
if let yValue = seriesInfo?.formattedYValue {
// Only now do something with unwrapped value
}
if let strokeStyle = seriesInfo?.renderableSeries?.strokeStyle { 
// Only now do something with unwrapped value
}</pre></div>
<!-- /wp:scichart/code-snippet -->

<!-- wp:paragraph -->
<p>we do have nice and clean Swift APIs. Finally, no more <code>if let</code>, <code>guard let</code> and other Swift dances:</p>
<!-- /wp:paragraph -->

<!-- wp:scichart/code-snippet {"code":"xAxis.currentInteractivityHelper.scroll(xAxis.visibleRange, byPixels: 100)nlet yValue = seriesInfo.formattedYValuenlet strokeStyle = seriesInfo.renderableSeries.strokeStyle","proglang":"language-swift"} -->
<div class="wp-block-scichart-code-snippet"><pre class="line-numbers code-toolbar language-swift">xAxis.currentInteractivityHelper.scroll(xAxis.visibleRange, byPixels: 100)
let yValue = seriesInfo.formattedYValue
let strokeStyle = seriesInfo.renderableSeries.strokeStyle</pre></div>
<!-- /wp:scichart/code-snippet -->

<!-- wp:paragraph -->
<p>So-called <em><a href="https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html#ID334">Implicitly unwrapped optionals</a></em> compiler warnings are easily fixable thanks to the handy <code><a href="https://developer.apple.com/xcode/">XCode</a></code> features:</p>
<!-- /wp:paragraph -->

<!-- wp:image {"id":32986,"sizeSlug":"full","linkDestination":"none"} -->
<figure class="wp-block-image size-full"><img src="https://www.scichart.com/wp-content/uploads/2022/05/fix-optionals-1.gif" alt="" class="wp-image-32986"/></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>even compiler errors are fixable as well:</p>
<!-- /wp:paragraph -->

<!-- wp:image {"id":32988,"sizeSlug":"full","linkDestination":"none"} -->
<figure class="wp-block-image size-full"><img src="https://www.scichart.com/wp-content/uploads/2022/05/fix-implicitly-unwrapped-optionals-1.gif" alt="" class="wp-image-32988"/></figure>
<!-- /wp:image -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Much more information is available in the Apple docs – <a href="https://developer.apple.com/documentation/swift/objective-c_and_c_code_customization/designating_nullability_in_objective-c_apis">Designating Nullability in Objective-C APIs</a></p></blockquote>
<!-- /wp:quote -->

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

<!-- wp:heading -->
<h2 id="initializers-designation-and-availability">Initializers - designation and availability</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>In this section, i'm going to touch 2(3) important macro:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li><code>NS_DESIGNATED_INITIALIZER</code></li><li><code>NS_UNAVAILABLE</code> &amp; <code>NS_SWIFT_UNAVAILABLE</code></li></ul>
<!-- /wp:list -->

<!-- wp:heading {"level":3} -->
<h3 id="ns_unavailable-ns_swift_unavailable">NS_UNAVAILABLE &amp; NS_SWIFT_UNAVAILABLE</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>As we all know, there's, let's say, semi-issue in <code>Objective-C</code> – you have initializers adoption by default. Each and every initializers in your classes are available to your class inheritors. One might say that this is a beneficial thing, but other - that it's not. While developing the <code>SDK</code> you might found that this brings some issues and confusion to consumers of your APIs.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Let's consider a very simple case we have here at <a href="/p/b1a95911-747d-40eb-b545-3fe8e82587e3/SciChart.com">SciChart</a>. We have a fairly simple class <code><a href="https://www.scichart.com/documentation/ios/current/Classes/SCIXyDataSeries.html">SCIXyDataSeries</a></code> which purpose is self-explanatory. There's shouldn't be any questions on how to create an instance of it. But what if you take a closer look at available initialisers, do you see anything eye catching:</p>
<!-- /wp:paragraph -->

<!-- wp:image {"id":32991,"sizeSlug":"full","linkDestination":"none"} -->
<figure class="wp-block-image size-full"><img src="https://www.scichart.com/wp-content/uploads/2022/05/image-2-1-2.png" alt="" class="wp-image-32991"/><figcaption>redundant empty initialiser on SCIXyDataSeries</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>How are we supposed to initialise <code><a href="https://www.scichart.com/documentation/ios/current/Classes/SCIXyDataSeries.html">SCIXyDataSeries</a></code> without knowing the types of <code>X-Data</code> and <code>Y-Data</code>? That's right, you can't! There's few ways of solving this issue, like for example marking this initialiser nullable, adding documentation comments that this initialiser shouldn't be used or just throwing exception with some clear explanation.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Thankfully, there's <code>NS_SWIFT_UNAVAILABLE</code> macro, which makes marked signature unavailable for swift, moreover there's <code>NS_UNAVAILABLE</code> macro, which makes signature unavailable for Objective-C as well, which is exactly what we want in situation like this:</p>
<!-- /wp:paragraph -->

<!-- wp:scichart/code-snippet {"code":"- (instancetype)init NS_UNAVAILABLE;","proglang":"language-csharp"} -->
<div class="wp-block-scichart-code-snippet"><pre class="line-numbers code-toolbar language-csharp">- (instancetype)init NS_UNAVAILABLE;</pre></div>
<!-- /wp:scichart/code-snippet -->

<!-- wp:image {"id":32993,"sizeSlug":"full","linkDestination":"none"} -->
<figure class="wp-block-image size-full"><img src="https://www.scichart.com/wp-content/uploads/2022/05/image-1-1-1024x317-1.png" alt="" class="wp-image-32993"/><figcaption>proper initialisers for the SCIXyDataSeries</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>That's it, no more redundant, misleading initialisers. No more false-positive support requests. No more confusion. Everything works as it should in the first place.</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Much more information is available in the Apple docs – <a href="https://developer.apple.com/documentation/swift/objective-c_and_c_code_customization/making_objective-c_apis_unavailable_in_swift">Making Objective-C APIs Unavailable in Swift</a></p></blockquote>
<!-- /wp:quote -->

<!-- wp:heading {"level":3} -->
<h3 id="ns_designated_initializer">NS_DESIGNATED_INITIALIZER</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p><em>Designated initialisers</em> explained fairly extensively in <a href="https://docs.swift.org/swift-book/LanguageGuide/Initialization.html#ID217">Swift documentation</a>. In short - designated initializer guarantees that the object is fully initialised by sending an initialization message to the superclass. When you inherit a class - the implementation detail becomes important. As described in Swift docs the rules for designated initializer are:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>A <em><strong>designated</strong></em> initializer <strong><em>must call</em></strong> a designated initializer from its immediate superclass.</li><li>A <strong><em>convenience</em></strong> initializer <strong><em>must call</em></strong> another initializer from the <em>same</em> class.</li><li>A <strong><em>convenience</em></strong> initializer <em><strong>must </strong></em><strong>ultimately</strong><em><strong> call</strong></em> a designated initializer.</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>A simple way to remember this is:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li><strong><em>Designated</em></strong> initializers must always <strong>delegate <em>up</em></strong>.</li><li><em><strong>Convenience</strong></em> initializers must always <strong><em>delegate across</em></strong>.</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>In <code>Objective-C</code> if your class has a designated initializer and rules are not met - you'll get a friendly warning. <code>Swift</code> on the other hand is much more strict and will give you the compilation error. So marking the designated <code>Objective-C</code> initializers helps the compiler to enforce the rules and make less mistake while do custom work with <code>SciChart.framework</code></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Consider a simple case of creating a custom labels for your <code><a href="https://www.scichart.com/documentation/ios/current/Classes/SCINumericAxis.html">SCINumericAxis</a></code>. You'd better read <a href="https://www.scichart.com/documentation/ios/current/axis-labels---labelprovider-api.html#axis-labels-labelprovider-api">the documentation</a> on this topic, but even after that I assume you would start with something like the following:</p>
<!-- /wp:paragraph -->

<!-- wp:scichart/code-snippet {"code":"class CustomLabelProvider: SCILabelProviderBaseu003cISCINumericAxisu003e {n    override func formatLabel(_ dataValue: ISCIComparable!) -u003e ISCIString! {nttreturn super.formatLabel(dataValue)nt}n}","proglang":"language-swift"} -->
<div class="wp-block-scichart-code-snippet"><pre class="line-numbers code-toolbar language-swift">class CustomLabelProvider: SCILabelProviderBase&lt;ISCINumericAxis> {
    override func formatLabel(_ dataValue: ISCIComparable!) -> ISCIString! {
return super.formatLabel(dataValue)
}
}</pre></div>
<!-- /wp:scichart/code-snippet -->

<!-- wp:paragraph -->
<p>After applying it to your <em>Axis</em> - it will crash with an exception : <em>&lt; Parameterless initializer of CustomLabelProvider class shouldn't be used. Please use one of the designated initializers instead &gt;.</em></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Let's assume you wan't to pass some string format through the initialiser to be used during label formatting, so you would add something like below:</p>
<!-- /wp:paragraph -->

<!-- wp:scichart/code-snippet {"code":"let format: Stringninit(format: String) {ntself.format = formatn}nnoverride func formatLabel(_ dataValue: ISCIComparable) -u003e ISCIString {ntlet formattedString = String(format: format, dataValue.toDouble())ntreturn NSString(string: formattedString)n}","proglang":"language-swift"} -->
<div class="wp-block-scichart-code-snippet"><pre class="line-numbers code-toolbar language-swift">let format: String
init(format: String) {
self.format = format
}

override func formatLabel(_ dataValue: ISCIComparable) -> ISCIString {
let formattedString = String(format: format, dataValue.toDouble())
return NSString(string: formattedString)
}</pre></div>
<!-- /wp:scichart/code-snippet -->

<!-- wp:paragraph -->
<p>which also will fail. Which initialiser to call - nobody knows, no hint from compiler whatsoever. All you would get is - &lt; <em>'super.init' isn't called on all paths before returning from initializer &gt;</em>, which isn't much of help.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>This brings a lot of confusion, support requests for such a simple use-case and other pain in the ... Thankfully that's easily fixable using <strong><em>designated initializers</em></strong> (in conjunction with marking some initializers unavailable) so it's fairly clear which initializer to call from an inheritor. Now if you want to add new initializer, and just call <code>super.init()</code> you will got two errors:</p>
<!-- /wp:paragraph -->

<!-- wp:image {"id":32995,"sizeSlug":"full","linkDestination":"none"} -->
<figure class="wp-block-image size-full"><img src="https://www.scichart.com/wp-content/uploads/2022/05/image-3-1.png" alt="" class="wp-image-32995"/><figcaption>'init()' is unavailable / Must call a designated initializer of the superclass</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>and if you try to call initializer on super, there's only proper and valid initializers are available:</p>
<!-- /wp:paragraph -->

<!-- wp:image {"id":32997,"sizeSlug":"full","linkDestination":"none"} -->
<figure class="wp-block-image size-full"><img src="https://www.scichart.com/wp-content/uploads/2022/05/image-2-1-1-1.png" alt="" class="wp-image-32997"/><figcaption>designated initializers</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>everything now clear and simple without any confusion.</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Much more information is available in the Apple docs – <a href="https://docs.swift.org/swift-book/LanguageGuide/Initialization.html#ID217">Designated Initializers and Convenience Initializers</a></p></blockquote>
<!-- /wp:quote -->

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

<!-- wp:heading -->
<h2 id="just-for-swift-refinements">Just for Swift refinements</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>As mentioned at the top of this article – <a href="https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Introduction/Introduction.html" rel="noopener">Objective-C</a> to <a href="https://swift.org/" rel="noopener">Swift</a> interoperability is outstanding by default, but at times it's a little bit awkward. All of that is possible thanks to the Swift's <a href="https://github.com/apple/swift/tree/main/lib/ClangImporter">ClangImporter</a>, which is used to import Objective-C (and C) code into Swift. Here is some of the tricks we used to improve importer behaviour and emit better and cleaner Swift API:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>Grouping Related Objective-C Constants</li><li><code>NS_SWIFT_NAME</code> a.k.a. <code>swift_name</code> attribute</li><li><code>NS_REFINED_FOR_SWIFT</code> a.k.a. <code>swift_private</code> attribute</li></ul>
<!-- /wp:list -->

<!-- wp:heading {"level":3} -->
<h3 id="grouping-related-objective-c-constants">Grouping Related Objective-C Constants</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>As per <a href="https://developer.apple.com/documentation/swift/objective-c_and_c_code_customization/grouping_related_objective-c_constants">Apple Documentation</a> there's a bunch of macros to Objective-C types to group their values in Swift, such as:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li><code>NS_ENUM</code> – simple enumerations</li><li><code>NS_CLOSED_ENUM</code> – simple enumerations that can never gain new cases</li><li><code>NS_OPTIONS</code> – enumerations whose cases can be grouped into sets of options</li><li><code>NS_TYPED_ENUM</code> – enumerations with a raw value type that you specify</li><li><code>NS_TYPED_EXTENSIBLE_ENUM</code> – enumerations that you expect might gain more cases</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>Those are pretty self explanatory and I want to emphasise on the last one only.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Since a regular <code>NS_ENUM</code> isn't an extensible type, we often use constants to provide list of possible values, which might be extended by a framework consumer. As an example here's what we used to have in our <code><a href="https://www.scichart.com/documentation/ios/current/Classes/SCIThemeManager.html">SCIThemeManager</a></code>:</p>
<!-- /wp:paragraph -->

<!-- wp:scichart/code-snippet {"code":"static NSString * _Nonnull const SCIChart_BlackSteelStyleKey = @u0022SCIChart_BlackSteelStyleKeyu0022;nstatic NSString * _Nonnull const SCIChart_SciChartv4DarkStyleKey = @u0022SCIChart_SciChartv4DarkStyleKeyu0022;nstatic NSString * _Nonnull const SCIChart_Bright_SparkStyleKey = @u0022SCIChart_Bright_SparkStyleKeyu0022;nstatic NSString * _Nonnull const SCIChart_ChromeStyleKey = @u0022SCIChart_ChromeStyleKeyu0022;nstatic NSString * _Nonnull const SCIChart_ElectricStyleKey = @u0022SCIChart_ElectricStyleKeyu0022;nstatic NSString * _Nonnull const SCIChart_ExpressionLightStyleKey = @u0022SCIChart_ExpressionLightStyleKeyu0022;nstatic NSString * _Nonnull const SCIChart_OscilloscopeStyleKey = @u0022SCIChart_OscilloscopeStyleKeyu0022;nstatic NSString * _Nonnull const SCIChart_ExpressionDarkStyleKey = @u0022SCIChart_ExpressionDarkStyleKeyu0022;nstatic NSString * _Nonnull const SCIChart_DefaultThemeKey = @u0022SCIChart_DefaultThemeKeyu0022;","proglang":"language-csharp"} -->
<div class="wp-block-scichart-code-snippet"><pre class="line-numbers code-toolbar language-csharp">static NSString * _Nonnull const SCIChart_BlackSteelStyleKey = @"SCIChart_BlackSteelStyleKey";
static NSString * _Nonnull const SCIChart_SciChartv4DarkStyleKey = @"SCIChart_SciChartv4DarkStyleKey";
static NSString * _Nonnull const SCIChart_Bright_SparkStyleKey = @"SCIChart_Bright_SparkStyleKey";
static NSString * _Nonnull const SCIChart_ChromeStyleKey = @"SCIChart_ChromeStyleKey";
static NSString * _Nonnull const SCIChart_ElectricStyleKey = @"SCIChart_ElectricStyleKey";
static NSString * _Nonnull const SCIChart_ExpressionLightStyleKey = @"SCIChart_ExpressionLightStyleKey";
static NSString * _Nonnull const SCIChart_OscilloscopeStyleKey = @"SCIChart_OscilloscopeStyleKey";
static NSString * _Nonnull const SCIChart_ExpressionDarkStyleKey = @"SCIChart_ExpressionDarkStyleKey";
static NSString * _Nonnull const SCIChart_DefaultThemeKey = @"SCIChart_DefaultThemeKey";</pre></div>
<!-- /wp:scichart/code-snippet -->

<!-- wp:paragraph -->
<p>At the moment in Swift 5 it's just going to be simply imported as public constants:</p>
<!-- /wp:paragraph -->

<!-- wp:scichart/code-snippet {"code":"public let SCIChart_BlackSteelStyleKey: Stringnpublic let SCIChart_SciChartv4DarkStyleKey: Stringnpublic let SCIChart_Bright_SparkStyleKey: Stringnpublic let SCIChart_ChromeStyleKey: Stringnpublic let SCIChart_ElectricStyleKey: Stringnpublic let SCIChart_ExpressionLightStyleKey: Stringnpublic let SCIChart_OscilloscopeStyleKey: Stringnpublic let SCIChart_ExpressionDarkStyleKey: Stringnpublic let SCIChart_DefaultThemeKey: String","proglang":"language-swift"} -->
<div class="wp-block-scichart-code-snippet"><pre class="line-numbers code-toolbar language-swift">public let SCIChart_BlackSteelStyleKey: String
public let SCIChart_SciChartv4DarkStyleKey: String
public let SCIChart_Bright_SparkStyleKey: String
public let SCIChart_ChromeStyleKey: String
public let SCIChart_ElectricStyleKey: String
public let SCIChart_ExpressionLightStyleKey: String
public let SCIChart_OscilloscopeStyleKey: String
public let SCIChart_ExpressionDarkStyleKey: String
public let SCIChart_DefaultThemeKey: String</pre></div>
<!-- /wp:scichart/code-snippet -->

<!-- wp:paragraph -->
<p>But if we add the typedef for a theme with a <code>NS_TYPED_EXTENSIBLE_ENUM</code> macro to it and use if with our constants:</p>
<!-- /wp:paragraph -->

<!-- wp:scichart/code-snippet {"code":"typedef NSString * _Nonnull SCIChartTheme NS_TYPED_EXTENSIBLE_ENUM;nstatic SCIChartTheme const SCIChartThemeBlackSteel = @u0022SCIChartThemeBlackSteelu0022;","proglang":"language-csharp"} -->
<div class="wp-block-scichart-code-snippet"><pre class="line-numbers code-toolbar language-csharp">typedef NSString * _Nonnull SCIChartTheme NS_TYPED_EXTENSIBLE_ENUM;
static SCIChartTheme const SCIChartThemeBlackSteel = @"SCIChartThemeBlackSteel";</pre></div>
<!-- /wp:scichart/code-snippet -->

<!-- wp:paragraph -->
<p>magic happens:</p>
<!-- /wp:paragraph -->

<!-- wp:scichart/code-snippet {"code":"public struct SCIChartTheme : Hashable, Equatable, RawRepresentable {n    public init(_ rawValue: String)n    public init(rawValue: String)n}nextension SCIChartTheme {n    public static let blackSteel: SCIChartThemen    public static let v4Dark: SCIChartThemen    public static let brightSpark: SCIChartThemen    public static let chrome: SCIChartThemen    public static let electric: SCIChartThemen    public static let expressionLight: SCIChartThemen    public static let oscilloscope: SCIChartThemen    public static let expressionDark: SCIChartThemen    public static let `default`: SCIChartThemen}","proglang":"language-swift"} -->
<div class="wp-block-scichart-code-snippet"><pre class="line-numbers code-toolbar language-swift">public struct SCIChartTheme : Hashable, Equatable, RawRepresentable {
    public init(_ rawValue: String)
    public init(rawValue: String)
}
extension SCIChartTheme {
    public static let blackSteel: SCIChartTheme
    public static let v4Dark: SCIChartTheme
    public static let brightSpark: SCIChartTheme
    public static let chrome: SCIChartTheme
    public static let electric: SCIChartTheme
    public static let expressionLight: SCIChartTheme
    public static let oscilloscope: SCIChartTheme
    public static let expressionDark: SCIChartTheme
    public static let `default`: SCIChartTheme
}</pre></div>
<!-- /wp:scichart/code-snippet -->

<!-- wp:paragraph -->
<p>Now, <code>SCIChartTheme</code> itself become <code>RawRepresentable</code>. It has an associated type, and every single constant with the same type in Objective-C will now become <code>SCIChartTheme</code>. So now Swift can enforce type safety, and use only type he needs comparing to any other <code>NSString</code> like hundreds of notification constants/default keys. This is now consumed by Swift - much, much much more cleaner:</p>
<!-- /wp:paragraph -->

<!-- wp:scichart/code-snippet {"code":"SCIThemeManager.applyTheme(.v4Dark, to: self.surface)n// as opposed tonSCIThemeManager.applyTheme(to: self.surface, withThemeKey: SCIChart_SciChartv4DarkStyleKey)n","proglang":"language-swift"} -->
<div class="wp-block-scichart-code-snippet"><pre class="line-numbers code-toolbar language-swift">SCIThemeManager.applyTheme(.v4Dark, to: self.surface)
// as opposed to
SCIThemeManager.applyTheme(to: self.surface, withThemeKey: SCIChart_SciChartv4DarkStyleKey)
</pre></div>
<!-- /wp:scichart/code-snippet -->

<!-- wp:paragraph -->
<p>In addition - you can easily extend this on the Swift side like so:</p>
<!-- /wp:paragraph -->

<!-- wp:scichart/code-snippet {"code":"extension SCIChartTheme {n     static let berryBlue: SCIChartTheme = SCIChartTheme(rawValue: u0022SciChart_BerryBlueu0022)n}","proglang":"language-swift"} -->
<div class="wp-block-scichart-code-snippet"><pre class="line-numbers code-toolbar language-swift">extension SCIChartTheme {
     static let berryBlue: SCIChartTheme = SCIChartTheme(rawValue: "SciChart_BerryBlue")
}</pre></div>
<!-- /wp:scichart/code-snippet -->

<!-- wp:paragraph -->
<p>As a bonus point, it works also for the Objective-C side, so we not only have better Swift API, but better API for the both worlds:</p>
<!-- /wp:paragraph -->

<!-- wp:scichart/code-snippet {"code":"[SCIThemeManager applyTheme:SCIChartThemeBlackSteel toThemeable:self.surface];n// as opposed ton[SCIThemeManager applyThemeToThemeable:self.surface withThemeKey:SCIChart_BlackSteelStyleKey];","proglang":"language-csharp"} -->
<div class="wp-block-scichart-code-snippet"><pre class="line-numbers code-toolbar language-csharp">[SCIThemeManager applyTheme:SCIChartThemeBlackSteel toThemeable:self.surface];
// as opposed to
[SCIThemeManager applyThemeToThemeable:self.surface withThemeKey:SCIChart_BlackSteelStyleKey];</pre></div>
<!-- /wp:scichart/code-snippet -->

<!-- wp:spacer {"height":"20px"} -->
<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>
<!-- /wp:spacer -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Much more information is available in the Apple docs – <a href="https://developer.apple.com/documentation/swift/objective-c_and_c_code_customization/grouping_related_objective-c_constants">Grouping Related Objective-C Constants</a></p></blockquote>
<!-- /wp:quote -->

<!-- wp:heading {"level":3} -->
<h3 id="ns_swift_name-a-k-a-swift_name-attribute">NS_SWIFT_NAME a.k.a. <code>swift_name</code> attribute &nbsp;</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>The <code>NS_SWIFT_NAME</code> macro allow you to customize how the Objective-C declarations are imported. Effectively it gives you an ability to provide a <strong>full blown new signature </strong>specially for Swift. You can mark any declaration with it - <em>enum</em>, <em>class</em>, <em>constant</em> or <em>function</em>. You just pass the desired Swift name for selector you want to import, e.g.:</p>
<!-- /wp:paragraph -->

<!-- wp:scichart/code-snippet {"code":"- (instancetype)initWithDefaultRange:(idu003cISCIRangeu003e)defaultNonZeroRange andAxisModifierSurface:(idu003cISCIAxisModifierSurfaceu003e)axisModifierSurface;n// mark the above initializer with the following macronNS_SWIFT_NAME(init(defaultNonZeroRange:axisModifierSurface:))","proglang":"language-csharp"} -->
<div class="wp-block-scichart-code-snippet"><pre class="line-numbers code-toolbar language-csharp">- (instancetype)initWithDefaultRange:(id&lt;ISCIRange>)defaultNonZeroRange andAxisModifierSurface:(id&lt;ISCIAxisModifierSurface>)axisModifierSurface;
// mark the above initializer with the following macro
NS_SWIFT_NAME(init(defaultNonZeroRange:axisModifierSurface:))</pre></div>
<!-- /wp:scichart/code-snippet -->

<!-- wp:paragraph -->
<p>Here is the before/after of the Swift API:</p>
<!-- /wp:paragraph -->

<!-- wp:scichart/code-snippet {"code":"// beforeninit(defaultRange defaultNonZeroRange: ISCIRange, andAxisModifierSurface axisModifierSurface: ISCIAxisModifierSurface)n// afterninit(defaultNonZeroRange: ISCIRange, axisModifierSurface: ISCIAxisModifierSurface)","proglang":"language-swift"} -->
<div class="wp-block-scichart-code-snippet"><pre class="line-numbers code-toolbar language-swift">// before
init(defaultRange defaultNonZeroRange: ISCIRange, andAxisModifierSurface axisModifierSurface: ISCIAxisModifierSurface)
// after
init(defaultNonZeroRange: ISCIRange, axisModifierSurface: ISCIAxisModifierSurface)</pre></div>
<!-- /wp:scichart/code-snippet -->

<!-- wp:paragraph -->
<p>which is fixed by a one click thanks to the XCode:</p>
<!-- /wp:paragraph -->

<!-- wp:image {"id":32999,"sizeSlug":"full","linkDestination":"none"} -->
<figure class="wp-block-image size-full"><img src="https://www.scichart.com/wp-content/uploads/2022/05/image-3-1-1024x81-1.png" alt="" class="wp-image-32999"/><figcaption>XCode automatically can fix API changes made for Swift</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>Most of the time <strong>XCode</strong> helps you automatically fix the change - as above or below:</p>
<!-- /wp:paragraph -->

<!-- wp:image {"id":33001,"sizeSlug":"full","linkDestination":"none"} -->
<figure class="wp-block-image size-full"><img src="https://www.scichart.com/wp-content/uploads/2022/05/fix-swift-name-1.gif" alt="" class="wp-image-33001"/></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>but sometimes doesn't - as with function below:</p>
<!-- /wp:paragraph -->

<!-- wp:scichart/code-snippet {"code":"// beforenfunc `is`(ofValidType dataSeries: ISCIDataSeries) -u003e Booln// afternfunc isOfValidType(dataSeries: ISCIDataSeries) -u003e Bool","proglang":"language-swift"} -->
<div class="wp-block-scichart-code-snippet"><pre class="line-numbers code-toolbar language-swift">// before
func `is`(ofValidType dataSeries: ISCIDataSeries) -> Bool
// after
func isOfValidType(dataSeries: ISCIDataSeries) -> Bool</pre></div>
<!-- /wp:scichart/code-snippet -->

<!-- wp:paragraph -->
<p>so you have to do that manually:</p>
<!-- /wp:paragraph -->

<!-- wp:image {"id":33003,"sizeSlug":"full","linkDestination":"none"} -->
<figure class="wp-block-image size-full"><img src="https://www.scichart.com/wp-content/uploads/2022/05/fix-isofvalidtype-swift-1024x216-1.gif" alt="" class="wp-image-33003"/></figure>
<!-- /wp:image -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Much more information is available in the Apple docs – <a href="https://developer.apple.com/documentation/swift/objective-c_and_c_code_customization/renaming_objective-c_apis_for_swift">Renaming Objective-C APIs for Swift</a></p></blockquote>
<!-- /wp:quote -->

<!-- wp:heading {"level":3} -->
<h3 id="ns_refined_for_swift-a-k-a-swift_private-attribute">NS_REFINED_FOR_SWIFT a.k.a. <code>swift_private</code> attribute</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p><code>NS_REFINED_FOR_SWIFT</code> macro on the other hand modifies the declaration adding a <em>double underscore prefix</em>, making it effectively private in Swift. But since double underscores are there, you can create a new function and call the private one from inside. This gives the opportunity of making clean Swift API where it can't be achieved via simple renames.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Consider simple <code><a href="https://www.scichart.com/documentation/ios/current/Classes/SCIIntegerValues.html">SCIIntegerValues</a></code> <a href="https://www.scichart.com/documentation/ios/current/Classes/SCIIntegerValues.html#/c:objc(cs)SCIIntegerValues(im)initWithItems:count:">initializer</a> example which accepts c-style array &nbsp;and count:</p>
<!-- /wp:paragraph -->

<!-- wp:scichart/code-snippet {"code":"- (instancetype)initWithItems:(int *)items count:(NSInteger)count","proglang":"language-csharp"} -->
<div class="wp-block-scichart-code-snippet"><pre class="line-numbers code-toolbar language-csharp">- (instancetype)initWithItems:(int *)items count:(NSInteger)count</pre></div>
<!-- /wp:scichart/code-snippet -->

<!-- wp:paragraph -->
<p>The above gets imported to swift as follows:</p>
<!-- /wp:paragraph -->

<!-- wp:scichart/code-snippet {"code":"public convenience init(items: UnsafeMutablePointeru003cInt32u003e, count: Int)","proglang":"language-swift"} -->
<div class="wp-block-scichart-code-snippet"><pre class="line-numbers code-toolbar language-swift">public convenience init(items: UnsafeMutablePointer&lt;Int32>, count: Int)</pre></div>
<!-- /wp:scichart/code-snippet -->

<!-- wp:paragraph -->
<p>This API is not that convenient on the swift side:</p>
<!-- /wp:paragraph -->

<!-- wp:image {"id":33005,"sizeSlug":"full","linkDestination":"none"} -->
<figure class="wp-block-image size-full"><img src="https://www.scichart.com/wp-content/uploads/2022/05/image-4-1-1024x338-1.png" alt="" class="wp-image-33005"/><figcaption>Inconvenient <code>SCIIntegerValues</code> initializer</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>Rename can't help with <code><a href="https://developer.apple.com/documentation/swift/unsafemutablepointer">UnsafeMutablePointer</a></code>, so here is when <code>NS_REFINED_FOR_SWIFT</code> comes in very handy. Instead of just changing parameter names, we can change method signature in an extension, making it accept a Swift <code><a href="https://developer.apple.com/documentation/swift/sequence">Sequence</a></code>:</p>
<!-- /wp:paragraph -->

<!-- wp:scichart/code-snippet {"code":"convenience initu003cS: Sequenceu003e(_ s: S) where S.Element == Int {n    let array = Array(s.map { Int32($0) })n    self.init(__items: array, count: array.count)n}","proglang":"language-swift"} -->
<div class="wp-block-scichart-code-snippet"><pre class="line-numbers code-toolbar language-swift">convenience init&lt;S: Sequence>(_ s: S) where S.Element == Int {
    let array = Array(s.map { Int32($0) })
    self.init(__items: array, count: array.count)
}</pre></div>
<!-- /wp:scichart/code-snippet -->

<!-- wp:paragraph -->
<p>Now instead of hassling with pointers we have a <strong><em>super convenient API</em></strong> on the Swift side:</p>
<!-- /wp:paragraph -->

<!-- wp:scichart/code-snippet {"code":"let val2 = SCIIntegerValues([1, 2, 3, 4, 5])n// or evennlet val1 = SCIIntegerValues(1...5)","proglang":"language-swift"} -->
<div class="wp-block-scichart-code-snippet"><pre class="line-numbers code-toolbar language-swift">let val2 = SCIIntegerValues([1, 2, 3, 4, 5])
// or even
let val1 = SCIIntegerValues(1...5)</pre></div>
<!-- /wp:scichart/code-snippet -->

<!-- wp:spacer {"height":"20px"} -->
<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>
<!-- /wp:spacer -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Much more information is available in the Apple docs – <a href="https://developer.apple.com/documentation/swift/objective-c_and_c_code_customization/improving_objective-c_api_declarations_for_swift">Improving Objective-C API Declarations for Swift</a></p></blockquote>
<!-- /wp:quote -->

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

<!-- wp:heading -->
<h2 id="summary">Summary</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Building an SDK on Apples platforms still means using Objective-C. Even if out-of-the box <a href="https://developer.apple.com/documentation/swift/objective-c_and_c_code_customization">Objective-C → Swift interoperability</a> is outstanding – you'll still need to go an extra mile. Yes, interoperability is hard, and building bridges is not as easy as you might think it is. But if youto provide an excellent experience for consumers of your APIs – you might found this article helpful. Otherwise you can leave everything as it is or just build everything in Swift.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>As a conclusion I'd recommend using the following techniques:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>nullability annotations - by adding type safety to the Swift API you also improve your Objective-C code.</li><li>designated initializers - in conjunction with <code>NS_UNAVAILABLE</code> on your initializers you make them stupidly clear and eliminate mistakes upfront.</li><li>lightweight generics - same as above. Here's more info in <a href="https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/using_imported_lightweight_generics_in_swift">documentation</a></li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>And <em>the most important </em>do the <strong><em>4R</em></strong>'s:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>Rename - <code>NS_SWIFT_NAME</code></li><li>Refine - <code>NS_REFINED_FOR_SWIFT</code></li><li>Rinse - <code>NS_UNAVAILABLE</code> and <code>NS_SWIFT_UNAVAILABLE</code></li><li>Repeat</li></ul>
<!-- /wp:list -->

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

<!-- wp:paragraph -->
<p>All of the above were just simple examples on how available approaches can be used in real-world scenarios. This and much more subtle improvements to <code><a href="https://www.scichart.com/ios-chart-features/">SciChart.framework</a></code> will be available in our next release <a href="https://www.scichart.com/scichart-ios-macos-android-sdk-v4-3-released/">SciChart iOS/macOS SDK v4.3</a>.</p>
<!-- /wp:paragraph -->