- Export All Collections Data - Added the documentation how to export all environment collections data
See how your iOS platform is evolving.
Cartfile.resolved
kinvey appenv apply
--org <org>
(--app <app>
is no longer valid):flex init
flex create
flex list
service create
website create
app create
flex job
commandUIWebView
was removed. (#370)--app
) matches more than one entitywebsite deploy
command:--force
flagnode12
(Node.js v.12) to flex
commands that support Node.js runtime selectionpendingSyncCount()
, pendingSyncEntities()
and clearSync()
to match with other platforms. Auto DataStore
tests and changes around it. (#356)Client
instance usage for aggregate functions on DataStore
(#357)DataStore.syncCount()
deprecated in favor of DataStore.pendingSyncCount()
(#356)website
command namespaceflex status
command outputs statuses using upper case lettersClient.userChangedListener
public
so changes to the logged in user can be listened to (#352)DataStore
type .auto
that prioritizes network requests and if they fail for network reasons, returns local cache data without calling the callback twice (#337)DataStore
type .cache
is now deprecated in favor of .auto
flex deploy --set-vars <env variables>
--runtime
app create
command now supports the --org
optionkinvey <namespace>
XCGLogger
in favor of SwiftyBeaver
and OSLog
(#325)compactCacheOnLaunch
for the Client.initialize()
method with the default value true
(#327)Codable
support for Social Identities (#323)User.refresh(anotherUser: refreshCustomProperties:)
method in your User
subclass if you have non-objc properties in your subclass (#326)env
namespace to appenv
profile login
if requiredprofile login
if requiredError()
instead of fatalError()
everywhere to allow for recovery (#305)DataStore.removeAll()
(#304)ObjectMapper
is now deprecated in favor of Swift.Codable
Entity.CodingKeys
renamed to Entity.EntityCodingKeys
to avoid confusion when subclassing Entity
DataStore<MyEntity>.collection()
can now throw errors, so a try
is now required, for example: try DataStore<MyEntity>.collection()
Options()
constructor can now throw erros, so a try
is now required, for example: try Options(timeout: 120)
CustomEndpoint
calls now require you to implement the JSONDecodable
protocolFlex-sdk 3.x contains several breaking changes as well as new features. To upgrade your service from Flex-sdk 2.x to 3.x:
skipBl
and useMasterSecret
have been removed and no longer function. Use useBl
and useUserContext
instead.Open the Flex SDK GitHub repo for more information and source code.
Client.initialize(appKey:appSecret:accessGroup:apiHostName:authHostName:encrypted:schema:completionHandler:)
Client.initialize(appKey:appSecret:accessGroup:apiHostName:authHostName:encryptionKey:schema:completionHandler:)
CustomEndpoint.CompletionHandler
CustomEndpoint.execute(_:params:client:completionHandler:)
DataStore.pull(_:deltaSetCompletionHandler:deltaSet:completionHandler:)
DataStore.purge(_:completionHandler:)
DataStore.push(timeout:completionHandler:)
DataStore.sync(_:deltaSetCompletionHandler:deltaSet:completionHandler:)
Entity.Key.acl
Entity.Key.entityId
Entity.Key.metadata
FileStore.download(_:storeType:ttl:completionHandler:)
FileStore.download(_:ttl:completionHandler:)
FileStore.find(_:ttl:completionHandler:)
FileStore.refresh(_:ttl:completionHandler:)
FileStore.remove(_:completionHandler:)
FileStore.upload(_:data:ttl:completionHandler:)
FileStore.upload(_:image:imageRepresentation:ttl:completionHandler:)
FileStore.upload(_:path:ttl:completionHandler:)
FileStore.upload(_:stream:ttl:completionHandler:)
Metadata.Key.authtoken
Metadata.Key.entityCreationTime
Metadata.Key.lastModifiedTime
User.PersistableUsernameKey
User.changePassword(newPassword:completionHandler:)
User.exists(username:client:completionHandler:)
User.forgotUsername(email:client:completionHandler:)
User.get(userId:client:completionHandler:)
User.login(authSource:_:createIfNotExists:authServiceId:client:completionHandler:)
User.lookup(_:completionHandler:)
User.resetPassword(usernameOrEmail:client:completionHandler:)
User.save(newPassword:completionHandler:)
User.sendEmailConfirmation(forUsername:client:completionHandler:)
User.signup(username:password:user:client:completionHandler:)
fields
is used in the query (#293)User.login(redirectURI:username:password:)
. Use User.login(username:password:provider:options:completionHandler:)
insteadflex create
.flex delete
. Note that this command name was used to clear Node.js project setting in previous versions.flex delete
command available in previous versions has a new name: flex clear
. It keeps its behavior.--no-prompt
flag (available only for delete commands).X-Kinvey-Device-Info
is a new header that includes more information about the device (#282).warning
(#283)ValidationStrategy
work as intended (#285)DataStore.find()
requests not working in some situations (#288)kinveyEntity
moduledataStore
entityId
s for dataStore
, groupStore
, and userStore
request
module to 2.85.0code-task-receiver
to 2.2.3 to add response object parsing for FlexFunctionsOpen the Flex SDK GitHub repo for more information and source code.
profile login
command updates the token only.scope
parameter to all MIC versions (#273)let person: Person = <#...#>
let notificationToken = person.observe { (objectChange: Kinvey.ObjectChange<Person>) in
switch objectChange {
case .change(let person):
print("person object changed")
case .deleted:
print("person object deleted")
case .error(let error):
print("\(error)")
}
}
let dataStore = DataStore<Person>.collection(.sync)
let notificationToken = dataStore.observe {
switch $0 {
case .initial(let results):
print("initial results")
case .update(let results, let deletions, let insertions, let modifications):
print("dataStore changed")
case .error(let error):
print("\(error)")
}
}
authServiceID
for MIC calls (#277)User
and Entity
now conforms to Hashable
and Equatable
(#279)DataStore.removeAll()
request was wrong (#274)Acl
for example (#278)--2fa
global option.kinvey profile login
.kinvey init
.kinvey profile delete
.Open the Kinvey CLI GitHub repo for full documentation and source code.
User-Agent
now includes the Swift version (#270)instanceID
(#267)Kinvey.sharedClient.initialize(appKey: "myAppKey", appSecret: "myAppSecret", instanceId: "my-instance-id") {
switch $0 {
case .success(let user):
print("\(user?.userId ?? "nil")")
case .failure(let error):
print("\(error)")
}
}
DataStore<T>.find()
calls (#268)FileStore
now returns the proper result types for sync wait calls (#266)Client.timeout
is now a shortcut for Client.options.timeout
(#271)v3
(#269)flex deploy
command now accepts --serviceId
flex init
command now requires a profile and ignores the --email
, --password
, and --host
options--no-color
flag for disabling colors in outputOpen the Kinvey CLI GitHub repo for full documentation and source code.
Install the latest beta using npm install -g kinvey-cli@next
.
status
becomes flex status
)init
—Initializes Kinvey CLI by prompting for credentials and configurations optionsflex init
—Configures Kinvey CLI to work with a specific Flex Serviceinit
) can now take credentials as command-line options or ENV variablesconfig
logout
flex
namespaceRealm 3.x
, ObjectMapper 3.x
and XCGLogger 6.x
.User.socialIdentity
was not being persisted. (#255)status
command now reports the email address (plus first/last name, if set) of deployer and the date/time at which service was deployedValidationStrategy
. A ValidationStrategy
allows you to validate data from the backend before it is parsed into your client-side model. You can choose from predefined options: .all
, .randomSample(percentage:)
or define your own strategy with .custom(validationBlock: (Array<Dictionary<String, Any>>) -> Swift.Error?)
. By default, the SDK does not validate individual entities before they are parsed. Please see Reference Docs for details on using ValidationStrategy
. (#248)let dataStore = DataStore<Person>.collection(.network, validationStrategy: .all)
Date
objects for example (#250)status
command now reports the version of the most recently-deployed servicelogs
command enhancements--from
and --to
flags-n
(--number
) and --page
flags-n
flag is suppliedFileStore.create()
creates a file entry in the server so the fileId
can be used to perform resumable uploads (#239)URLSession
for each call using Options
(#244)SFAuthenticationSession
for iOS 11, otherwise use SFSafariViewController
(#246)dynamic
not being used in the property declaration on Entity
subclasses (#243)DataStore.syncCount()
and DataStore.sync()
considering entities that are not the generic class specified on DataStore
(#247)_id
is required (#234)DataStore<T>.collection(autoPagination: true)
enables auto pagination, so no need to do it manually. This feature is disabled by default, so DataStore<T>.collection()
means DataStore<T>.collection(autoPagination: false)
(#231)User.logout()
is now async since it performs a network request to invalidate the token in the backend (#237)File.mapping()
was not open
(#233)save()
the cache implementation now performs deletes on nested objects (#229)~/Documents/<kinvey app key>
, but should be ~/Library/Application Support/<bundle id>/<kinvey app key>
(#236)clientId
parameter was renamed to authServiceId
in User.presentMICViewController()
, User.login()
and Options()
(#238)Kinvey.Error.unauthorized
also includes a debug
property. So now a switch
case
should look like case .unauthorized(let httpResponse, let data, let error, let debug, let description):
(#235)List<T>
(https://github.com/Kinvey/swift-sdk/pull/228)LiveStreamAcl
constructor missing (https://github.com/Kinvey/swift-sdk/pull/232)find()
, pull()
and sync()
that now has a Result<AnyRandomAccessCollection<T>, Swift.Error>
as the result for the completion handler.DataStore.count()
pull()
has now a new (optional) parameter called deltaSetCompletionHandler
which is a completion block that returns only the results that have changed during the delta set computation. The regular completionHandler
parameter will continue to return all the results (including the unchanged results)Options
is introduced to hold custom optional values such as client
, clientId
, ttl
, deltaSet
, readPolicy
, writePolicy
, timeout
, clientAppVersion
and customRequestProperties
. Maybe more to be added in the future.count()
were not translating queries when alias were usedDataStore
class that takes a Client
instance, ReadPolicy
, WritePolicy
, deltaSet
and timeout
values as optional parameters are now deprecated in favor of the Options
new struct.Client.clientAppVersion
and Client.customRequestProperties
were removed in favor of Client.options
which contains both clientAppVersion
and customRequestProperties
.User.refresh()
was losing authenticationQuery
objects with values containing the character +
were causing a wrong URL encodinginstance
param was not respected when running config [instance]
in a fresh environmentFile
class and specifying when create your FileStore
instance, for example: let fileStore = FileStore<MyFileSubclass>()
Push.unRegisterDeviceToken()
now returns an error instead of crash if the device token was not foundclientId
parameter when called MIC.urlForLogin()
or User.presentMICViewController()
Query
using dates were being misconstructed when sent to the backendFileStore.getInstance()
in favor of the usage of constructors FileStore<File>()
PersistableIdKey
, PersistableAclKey
and PersistableMetadataKey
in favor of Entity.Key.entityId
, Entity.Key.acl
and Entity.Key.metadata
respectivelyMetadata.LmtKey
, Metadata.EctKey
and Metadata.AuthTokenKey
in favor of Metadata.Key.lastModifiedTime
, Metadata.Key.entityCreationTime
and Metadata.Key.authToken
respectivelyconfig
against the default instance (under certain scenarios)User.socialIdentity
properties were not public
User
custom type was not properly loaded after a relaunchClient
class now have a new method ping()
to test if the client was initialized correctly.Kinvey.sharedClient.ping() { (result: Result<EnvironmentInfo, Swift.Error>) in
switch result {
case .success(let envInfo):
//succeed
case .failure(let error):
//failed
}
}
DataStore.group()
is a set of new methods that allows group / aggregation functions. You can write your own reduce function using JavaScript
or use pre-defined functions like count
, sum
, avg
(average), min
(minimum) and max
(maximum).dataStore.group(keys: ["country"], avg: "age") { (result: Result<[AggregationAvgResult<Person, Int>], Swift.Error>) in
switch result {
case .success(let array):
//succeed
case .failure(let error):
//failed
}
}
User.refresh()
will reload the user's data. Also applies for Client.activeUser
which will refresh and persist the new user's data.Kinvey.sharedClient.activeUser?.refresh() { result in
switch result {
case .success:
//succeed
case .failure(let error):
//failed
}
}
Improvement: a new pattern for all completionHandler
s in the library was introduced. All methods containing completionHandler
s has now overloaded versions which returns a Result<SuccessType, FailureType>
instance where you can use a switch
statement to figure if the call succeed (case .success(let successObject):
) or failed (case .failure(let error):
)
Bugfix: User.lookup()
now returns the correct User
type if a custom user type was set.
Breaking Change: User.destroy()
, User.sendEmailConfirmation()
, User.resetPassword()
and User.forgotUsername()
were changed to have the completionHandler
block following the Result
enumeration pattern described above.
user.sendEmailConfirmation() { result in
switch result {
case .success:
//succeed
case .failure:
//failed
}
}
DataStore.push()
and DataStore.sync()
Push.unRegisterDeviceToken()
Error
case for situations when there's some missing configuration in the console3.3.8
and 3.3.9
DataStore.removeById()
method is now deprecatedfileId
@objc
is used inside of an Entity
subclassFileStore
FileStore.download(_ file: inout File)
is now deprecated. Please use FileStore.download(_ file: File)
. The download
method does not require you to pass the file reference anymore.Acl
and Metadata
fixed for File
objectsGeoPoint
class to store geolocation coordinates (latitude, longitude)class Vehicle: Entity {
dynamic var name: String?
dynamic var geolocation: GeoPoint?
override class func collectionName() -> String {
return "Vehicle"
}
override func propertyMapping(_ map: Map) {
super.propertyMapping(map)
name <- ("name", map["name"])
geolocation <- ("geolocation", map["geolocation"])
}
}
let deliveryTruck = Person()
deliveryTruck.name = "Package Delivery Truck"
deliveryTruck.geolocation = GeoPoint(latitude: 42.3133521, longitude: -71.1271963)
String
, Int
, Float
, Double
and Bool
import Kinvey
class Book: Entity {
dynamic var title: String?
let authorNames = List<StringValue>()
override class func collectionName() -> String {
return "Book"
}
override func propertyMapping(_ map: Map) {
super.propertyMapping(map)
title <- ("title", map["title"])
authorNames <- ("authorNames", map["authorNames"])
}
}
let book = Book()
book.title = "Swift for the win!"
book.authorNames.append("Victor Barros")
Kinvey.Error
objects now conforms to LocalizedError
CustomEndpoint
now supports arrays and custom typesKinveyDateTransform
missing a public constructorUserMetadata
properties FileStore.getInstance()
if invoked before the creation of a DataStore
instanceKinveyDateTransform
missing a public constructorUserMetadata
properties without a public accesskinvey config
targets the default Kinvey instance for data link selection if a host is not provided (even if the CLI was previously configured with a custom host)super.propertyMapping()
was not called inside of the propertyMapping()
method for a Entity
subclassPush
now supports the new Push API in iOS 10. A new method was added for apps to register for push: Push.registerForNotifications()
(all parameters optional). The previous method Push.registerForPush()
is now deprecated for iOS 10 and above.Kinvey.sharedClient.push.registerForNotifications { granted, error in
if granted {
//registered successfully
} else {
//failed to register
}
}
nil
after MIC login succeedsKinvey.Error
now implements CustomStringConvertible
and CustomDebugStringConvertible
which means you can now print()
and debugPrint()
errors. Also, errors now have the httpResponse
and data
properties, which allows you to check http status codes and the response body.User.resetPassword(email:)
and User.resetPassword(username:)
are now deprecated. Please use the class method User.resetPassword(usernameOrEmail:)
instead._ids
values are being sent to the backend.Content-Length
header was not present in the response.Kinvey.Error
now implements CustomStringConvertible
and CustomDebugStringConvertible
which means you can now print()
and debugPrint()
errors. Also errors now also have the httpResponse
and data
properties allowing you to check things like http status codes and the response body for example.client.userType = MyUser.self
let user = MyUser()
user.foo = "bar"
User.signup(user: user) { user, error in
if let user = user {
//success
} else {
//failure
}
}
User-Agent
X-Kinvey-Client-App-Version
X-Kinvey-Device-Information
X-Kinvey-Client-App-Version
request header.Kinvey.sharedClient.clientAppVersion = "1.0.0"
// Version 1
class Person: Entity {
dynamic var firstName: String?
dynamic var lastName: String?
override class func collectionName() -> String {
return "Person"
}
override func propertyMapping(_ map: Map) {
super.propertyMapping(map)
firstName <- map["firstName"]
lastName <- map["lastName"]
}
}
// Version 2
class Person: Entity {
dynamic var fullName: String?
override class func collectionName() -> String {
return "Person"
}
override func propertyMapping(_ map: Map) {
super.propertyMapping(map)
fullName <- map["fullName"]
}
}
// Migrating your data during client initialization
Kinvey.sharedClient.initialize(appKey: "<#appKey#>", appSecret: "<#appSecret#>", schemaVersion: 2) { migration, oldSchemaVersion in
migration.execute(Person.self) { (oldEntity) in
var newEntity = oldEntity
if oldSchemaVersion < 2 {
newEntity["fullName"] = "\(oldEntity["firstName"]!) \(oldEntity["lastName"]!)"
newEntity.removeValue(forKey: "firstName")
newEntity.removeValue(forKey: "lastName")
}
return newEntity
}
}
kinvey job
kinvey config [instance]
config
command now prompts for a new service on every run (fixed prior bug where it did nothing if saved data was already present)kinvey-flex-sdk
(instead of kinvey-backend-sdk
)logs
command now takes optional runtime arguments (instead of prompting for log filters)kinvey config acme-us1
)status
command (no arg command) crashed if supplied with an argumentUser.presentMICViewController()
now uses SFSafariViewController
as the default option to login using MIC. To explore other options add the parameter micUserInterface
using one of the options in the MICUserInterface
enum.User.presentMICViewController(redirectURI: URL(string: "<#myRedirectURL://#>")!) { (user, error) -> Void in
if let user = user {
self.userIdLabel.text = user.userId
}
self.completionHandler?(user, error)
}
If you are using the default .safari
option for the micUserInterface
, remember to add the code below in your app delegate.
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
if User.login(redirectURI: URL(string: "<#myRedirectURL://#>")!, micURL: url) {
return true
}
return false
}
User.presentMICViewController()
now uses SFSafariViewController
as the default option to login using MIC. To explore other options add the parameter micUserInterface
using one of the options in the MICUserInterface
enum.User.presentMICViewController(redirectURI: NSURL(string: "<#myRedirectURL://#>")!) { (user, error) -> Void in
if let user = user {
self.userIdLabel.text = user.userId
}
self.completionHandler?(user, error)
}
If you are using the default .Safari
option for the micUserInterface
, remember to add the code below in your app delegate.
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
if User.login(redirectURI: NSURL(string: "<#myRedirectURL://#>")!, micURL: url) {
return true
}
return false
}
This version of the SDK requires Swift 3 and XCode 8 (or above).
Known issue: several Kinvey app developers have reported seeing a Keychain issue when the app logs in a user on iOS 10 Simulator. The error message looks like the following: Terminating app due to uncaught exception 'KinveyException', reason: 'Could not write token to keychain. Err (null) (-34018)'
This is a known issue with the iOS 10 simulator. To work around it, you can share the keychain.
Query
objects not working properlyDataStore
operations like find()
and pull()
can now report progress of the requestlet request = store.find() { (events, error) in
//completion handler
}
request.progress = {
//progress handler
print("Progress: \($0.countOfBytesReceived)/\($0.countOfBytesExpectedToReceive)")
}
DataStore.count()
returns the total number of records in a colletion.let store = DataStore<Event>.collection(.Network)
store.count { (count, error) in
//completion handler
}
let query = Query {
$0.skip = 10
$0.limit = 50
}
store.find(query) {
//it will get max of 50 results starting from the 11th record
}
User.loginWithAuthorization(redirectURI: "myRedirectURI://", username: "myUsername", password: "myPassword") { user, error in
if (user != nil) {
//logged in successfully
} else if (error != nil) {
//something went wrong if the error object is not nil
} else {
//should never happen!
}
}
find()
operations returning wrong results for StoreType.Network
User.forgotUsername(email: "your@email.com") { error in
}
let userQuery = UserQuery {
$0.username = username
}
user.lookup(userQuery) { users, error in
}
let file: File = ...
fileStore.download(file) { (file, url: NSURL?, error) in
//file is now cached
}
With an optional parameter to not cache the downloaded files:
let file: File = ...
fileStore.download(file, storeType: .Network) { (file, url: NSURL?, error) in
//file is not cached
}
client.micApiVersion = "v2" //v1 is the default value
DataStore
you now have to call the collection()
method instead of getInstance()
let user: User = ...
user.changePassword(newPassword: "myNewPassword") { user, error in
}
let user: User = ...
user.sendEmailConfirmation { error in
}
User.login(authSource: .Facebook, facebookAuthDictionary) { user, error in
}
push()
, pull()
, sync()
and purge()
operations on DataStoreType.Cache
DataStore.syncCount()
method addedClient.logNetworkEnabled
enables the ability of log network requests and responses. Default value is false
Kinvey.sharedClient.logNetworkEnabled = true //it will start log network requests and responses
DataStore<MyCollection>.getInstance(.Network, tag: "MyCustomDataContainer")
Acl
now includes readers and writers permissions.Error
now includes a localized description error. Available only in English for now.FileStore
now supports resumable uploads and downloads.DataStore<MyCollection>.getInstance(.Network, deltaSet: true)
push()
methodPersistable
objects using fromJson()
and toJson()
methodslet store = DataStore<MyPersistableClass>.getInstance(filePath: customPath)
The beta version of the iOS 3.0 SDK is now available!
New in this release:
Full support for data synchronization between your app and backend. Refer to the Data Store Guide to learn how to use the new data manipulation APIs.
We've simplified data stores and caching policies, making it easier for you to start building apps with caching and offline built in.
The Kinvey framework is now a published as a module.
Code samples and API docs for Objective-C are coming soon.
logs
command