For unknown reasons, AKDevice.serialNumber can sometimes return nil. As a workaround, we just fall back to a hardcoded valid serial number if AKDevice.serialNumber is nil.
Previously we assumed that if there was an error installing the developer disk, it was incompatible with the device’s iOS version. Howevever, sometimes an iOS device needs to be rebooted before it can successfully mount a developer disk.
We now explicitly check for the latter scenario, and present a different error message asking the user to reboot their device if that’s the case.
Bundle(url:) is cached, so even if AltPlugin is deleted Bundle(url:) will still return a non-nil value. Instead, we now directly check whether a directory exists at pluginURL to determine if AltPlugin is installed.
ALTWiredConnection.disconnect() doesn’t do anything if ALTWiredConnection.isConnected == NO. The problem is, we never set .isConnected to YES in the first place…which means disconnect() never actually did anything. Whoops.
WirelessConnection.nwConnection.stateUpdateHandler maintains strong reference to WirelessConnection, resulting in strong reference cycle. To break it, we now explicitly set stateUpdateHandler to nil when disconnecting.
PatreonAPI.fetchAccount() is called by both PatreonAPI.authenticate() and PatreonAPI.refreshPatreonAccount(), so this ensures the keychain is updated via both ways.
Rather than store both the current user’s Patreon account and all cached Friend Zone patrons in the same table, we now store Friend Zone patrons in the new ManagedPatron table. This avoids the need to distinguish between the two at runtime.
The Patreon API doesn’t have a way to fetch just the patrons belonging to our Friend Zone tier. Instead, we need to fetch ALL patrons (including inactive ones) and filter out those not in the tier. This is very inefficient, and takes over a minute to complete as of April 14, 2022, due to the number of patrons we have.
We can’t do much to change this, but AltStore will now at least cache the fetched patrons with Core Data. Additionally, AltStore will only perform this long fetch whenever the Friend Zone list actually changes, rather than every time the Patreon screen appears.
Previously, only the beta version of AltStore could add sources. Now, the public version supports adding explicitly “trusted” sources, while the beta version can continue to add any source.
NSError.sanitizedForCoreData() now sanitizes _all_ user info values (including for underlying errors) to ensure they all conform to NSSecureCoding, rather than just removing “NSCodingPath” value (if it exists).
Eventually, listing permissions will be mandatory so AltStore can verify that apps only require the permissions they declare. Until then, we’ll allow apps to not list their permissions.
We can’t remove all app groups from an App ID once one has been assigned, but we _can_ disable app groups completely for effectively the same result.
This fixes some apps having permanant access to AltStore’s own app group after being (de-)activated.