# v2.1.1 to v2.2.0

## Runtime compatibility

Appfigurate app 2.2.0 is backwardly runtime compatible with apps and app extensions linked against Appfigurate library 2.1.1.

## Source compatibility

Appfigurate 2.2.0 is mostly source compatible with 2.1.1. Some minor changes are required:

## Info.plist changes

* Remove the `APLConfigurationClass` key/value pair. In order to improve reliability and startup time of your app, Appfigurate Library no longer uses the `APLConfigurationClass` key/value pair to instantiate your `APLConfiguration` subclass. Instead it calls the `APLConfigurationClass` function that you implement (see Objective-C/Swift changes below):

## Objective-C/Swift changes

* Add a new C function `APLConfigurationClass` to the bottom of your APLConfiguration subclass:

> Objective-C example

```objectivec
Class APLConfigurationClass(void) {
    return [ExampleConfiguration class];
}
```

> Swift example

```swift
@_cdecl("APLConfigurationClass")
func APLConfigurationClass() -> AnyClass {
    return ExampleConfiguration.self
}
```

### Upgrading your APLConfiguration subclass from Objective-C ‣ Swift

One of the key features of Appfigurate 2.2.0 is support for Swift 5.3 using property wrappers. It is relatively simple to upgrade your `APLConfiguration` subclass from Objective-C to Swift:

#### Output Swift implementation

Using Appfigurate tap ≡ ‣ *App* ‣ Output Implementation under the SWIFT LIBRARY INTEGRATION section. The output will be similar to the following:

```swift
import Foundation
import AppfigurateLibrary

@objcMembers class Configuration: APLConfiguration {

    @BoolProperty(description: "Log debug output to console", restart: false)
    var debugLogging: Bool

    @StringPropertyListEdit(regex: #"https://[\w\.-]+\.yourappserver.com/.*"#, description: "Application server url", restart: false, values: ["Dev":"https://dev.yourappserver.com/api", "Prod":"https://www.yourappserver.com/api"])
    var serverURL: String

    override func allowInvalidSignatures() -> Bool {
        return !ENCRYPTED()
    }

    override func publicKey() -> String {
        // 41 36 87 71 0D 05
	return "-----BEGIN PUBLIC KEY-----\n" +
            "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4TZnKfGeXttN7Rr3eiAZ\n" +
            "PMEPsZvbo7lgIpMh6OjgBsoqkJJP0yXXLtpqsBCv8vm7RYqCn5+yfkiCQiXvkJBz\n" +
            "FSKmLF9EPR9l1H+32Id82dDuseD70D66puPUHjciEgmU18DpW2NVvTAykMwTEsiR\n" +
            "0h/ExBEhUe75qtwlVno8cMFbEfVtiGbKECvWIr122ED71T0Jt2Bcxqx1a7c1hPIV\n" +
            "RwLxIfWfE0+2rB9nJVPBgsTVPywibDvjio82FousyMDmvkAbMq5iyuyvJ0+5bATz\n" +
            "o12GEt5lSiQlCMzfmkWYBROMDCh27qGFVVo1XAUCVsMfsW9n4iQcoLAdUp/LI3B3\n" +
            "ywIDAQAB\n" +
            "-----END PUBLIC KEY-----\n"
    }

    override func reset() {
        debugLogging = true
        serverURL = "https://www.yourappserver.com/api"
    }
}

@_cdecl("APLConfigurationClass")
func APLConfigurationClass() -> AnyClass {
    return ExampleConfiguration.self
}
```

Delete the `debugLogging` and `serverURL` properties and port your Objective-C properties across one-by-one as per the following [Macros ‣ Property wrappers](#macros-property-wrappers) section below.

#### Macros ‣ Property wrappers

Appfigurate's swift property wrappers are named the same as the Objective-C macros making it easy to port:

<table><thead><tr><th width="383">Objective-C macro</th><th>Swift property wrapper</th></tr></thead><tbody><tr><td>BOOL_PROPERTY</td><td>@BoolProperty</td></tr><tr><td>STRING_PROPERTY_EDIT</td><td>@StringPropertyEdit</td></tr><tr><td>STRING_PROPERTY_LIST</td><td>@StringPropertyList</td></tr><tr><td>STRING_PROPERTY_LIST_EDIT</td><td>@StringPropertyListEdit</td></tr><tr><td>ENCRYPTED_STRING_PROPERTY_LIST_EDIT</td><td>@EncryptedStringPropertyListEdit</td></tr><tr><td>INT_PROPERTY_SLIDER</td><td>@IntPropertySlider</td></tr><tr><td>INT_PROPERTY_EDIT</td><td>@IntPropertyEdit</td></tr><tr><td>INT_PROPERTY_LIST</td><td>@IntPropertyList</td></tr><tr><td>INT_PROPERTY_LIST_EDIT</td><td>@IntPropertyListEdit</td></tr><tr><td>FLOAT_PROPERTY_SLIDER</td><td>@FloatPropertySlider</td></tr><tr><td>FLOAT_PROPERTY_EDIT</td><td>@FloatPropertyEdit</td></tr><tr><td>FLOAT_PROPERTY_LIST</td><td>@FloatPropertyList</td></tr><tr><td>FLOAT_PROPERTY_LIST_EDIT</td><td>@FloatPropertyListEdit</td></tr><tr><td>DOUBLE_PROPERTY_SLIDER</td><td>@DoublePropertySlider</td></tr><tr><td>DOUBLE_PROPERTY_EDIT</td><td>@DoublePropertyEdit</td></tr><tr><td>DOUBLE_PROPERTY_LIST</td><td>@DoublePropertyList</td></tr><tr><td>DOUBLE_PROPERTY_LIST_EDIT</td><td>@DoublePropertyListEdit</td></tr><tr><td>ACTION_METHOD</td><td>No Swift equivalent</td></tr></tbody></table>

> Objective-C Example

```objectivec
@interface Configuration : APLConfiguration
@property(nonatomic, assign) BOOL logging;
@end

@implementation Configuration
BOOL_PROPERTY(logging, @"Enable debug logging to console", NO);
...
```

> Swift Example

```swift
@objcMembers class Configuration: APLConfiguration {
    @BoolProperty(description: "Enable debug logging to console", restart: false)
    var logging: Bool
    ...
```

#### @objcMembers/@objc

You must either mark the entire `APLConfiguration` subclass with `@objcMembers` (recommended approach) or mark each configuration property individually with `@objc`. Omitting these markers will cause the properties to be unavailable for access by Appfigurate Library.

> @objcMembers Example

```swift
@objcMembers class Configuration: APLConfiguration {
    @BoolProperty(description: "Enable debug logging to console", restart: false)
    var logging: Bool
    ...
```

> @objc Example

```swift
class Configuration: APLConfiguration {
    @BoolProperty(description: "Enable debug logging to console", restart: false)
    @objc var logging: Bool
    ...
```
