Skip to content

Commit 2b0f588

Browse files
ObjectBox Swift database 5.0.0
1 parent 2710f8a commit 2b0f588

File tree

15 files changed

+193
-46
lines changed

15 files changed

+193
-46
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ Notable changes to the ObjectBox Swift library.
44

55
For more insights into what changed in the ObjectBox C++ core, [check the ObjectBox C changelog](https://github.com/objectbox/objectbox-c/blob/main/CHANGELOG.md).
66

7-
## 5.0.0 - in development
7+
## 5.0.0 - 2025-09-29
8+
9+
- Update ObjectBox database to version `5.0.0-2025-09-27`.
10+
- ToOne relations: when deleting an object with an ID larger than the maximum 32-bit unsigned integer
11+
(`4294967295`) that is used as the target object of a ToOne, correctly re-set the target ID of the ToOne to
12+
`0`. [objectbox-dart#740](https://github.com/objectbox/objectbox-dart/issues/740)
813

914
### Sync
1015

Example/NotesExample.xcodeproj/project.pbxproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@
581581
repositoryURL = "https://github.com/objectbox/objectbox-swift-spm";
582582
requirement = {
583583
kind = upToNextMajorVersion;
584-
minimumVersion = 4.4.1;
584+
minimumVersion = 5.0.0;
585585
};
586586
};
587587
/* End XCRemoteSwiftPackageReference section */

Source/fetch_dependencies.command

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ set -e
1313

1414
# objectbox-swift release version on GitHub:
1515
# https://github.com/objectbox/objectbox-swift/releases/download/v${version}
16-
version=4.4.1
16+
version=5.0.0
1717

1818
# C library version attached to the GitHub release:
1919
# ObjectBoxCore-static-${c_version}.zip
20-
c_version=4.3.1
20+
c_version=5.0.0
2121

2222
# Params supported by apple-build-static-libs.sh
2323
if [ -n "$OBX_SKIP_STATIC_C_TESTS" ]; then

Source/ios-framework/CommonSource/Box.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ extension Box {
177177
/// - Returns: List of IDs of the entities were written to.
178178
/// - Throws: ObjectBoxError errors for database write errors.
179179
@discardableResult
180-
public func putAndReturnIDs <C: Collection>(_ entities: C, mode: PutMode = .put) throws
180+
public func putAndReturnIDs<C: Collection>(_ entities: C, mode: PutMode = .put) throws
181181
-> [EntityType.EntityBindingType.IdType]
182182
where C.Element == EntityType {
183183
if entities.isEmpty {

Source/ios-framework/CommonSource/Internal/objectbox-c-sync.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
#include "objectbox-c.h"
3535

3636
#if defined(static_assert) || defined(__cplusplus)
37-
static_assert(OBX_VERSION_MAJOR == 4 && OBX_VERSION_MINOR == 3 && OBX_VERSION_PATCH == 1, // NOLINT
37+
static_assert(OBX_VERSION_MAJOR == 5 && OBX_VERSION_MINOR == 0 && OBX_VERSION_PATCH == 0, // NOLINT
3838
"Versions of objectbox.h and objectbox-sync.h files do not match, please update");
3939
#endif
4040

@@ -201,6 +201,20 @@ OBX_C_API OBX_sync* obx_sync_urls(OBX_store* store, const char* server_urls[], s
201201
/// Stops and closes (deletes) the sync client, freeing its resources.
202202
OBX_C_API obx_err obx_sync_close(OBX_sync* sync);
203203

204+
/// Adds or replaces a sync filter variable value for the given name to the sync client.
205+
/// Eventually existing values for the same name are replaced.
206+
/// Client filter variables can be used in server-side sync filters to filter out objects that do not match the filter.
207+
/// Filter variables must be added before login, e.g. before obx_sync_start() or setting credentials.
208+
/// @param name non-NULL name of the filter variable
209+
/// @param value non-NULL value of the filter variable
210+
OBX_C_API obx_err obx_sync_filter_variables_put(OBX_sync* sync, const char* name, const char* value);
211+
212+
/// Removes a previously added sync filter variable value.
213+
OBX_C_API obx_err obx_sync_filter_variables_remove(OBX_sync* sync, const char* name);
214+
215+
/// Removes all previously added sync filter variable values.
216+
OBX_C_API obx_err obx_sync_filter_variables_remove_all(OBX_sync* sync);
217+
204218
/// Sets credentials to authenticate the client with the server.
205219
/// Any credentials that were set before are replaced;
206220
/// if you want to pass multiple credentials, use obx_sync_credentials_add() instead.

Source/ios-framework/CommonSource/Internal/objectbox-c.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ extern "C" {
5151

5252
/// When using ObjectBox as a dynamic library, you should verify that a compatible version was linked using
5353
/// obx_version() or obx_version_is_at_least().
54-
#define OBX_VERSION_MAJOR 4
55-
#define OBX_VERSION_MINOR 3
56-
#define OBX_VERSION_PATCH 1 // values >= 100 are reserved for dev releases leading to the next minor/major increase
54+
#define OBX_VERSION_MAJOR 5
55+
#define OBX_VERSION_MINOR 0
56+
#define OBX_VERSION_PATCH 0 // values >= 100 are reserved for dev releases leading to the next minor/major increase
5757

5858
//----------------------------------------------
5959
// Common types
@@ -179,6 +179,8 @@ typedef enum {
179179
/// This is a free trial version; only applies to server builds (no trial builds for database and Sync clients).
180180
OBXFeature_Trial = 18,
181181

182+
/// Server-side filters to return individual data for each sync user (user-specific data).
183+
OBXFeature_SyncFilters = 19,
182184

183185
} OBXFeature;
184186

@@ -2121,7 +2123,7 @@ OBX_C_API obx_qb_cond obx_qb_less_or_equal_string(OBX_query_builder* builder, ob
21212123
OBX_C_API obx_qb_cond obx_qb_in_strings(OBX_query_builder* builder, obx_schema_id property_id,
21222124
const char* const values[], size_t count, bool case_sensitive);
21232125

2124-
/// For OBXPropertyType_StringVector - matches if at least one vector item equals the given value.
2126+
/// @deprecated Please use obx_qb_contains_element_string() instead.
21252127
OBX_C_API obx_qb_cond obx_qb_any_equals_string(OBX_query_builder* builder, obx_schema_id property_id, const char* value,
21262128
bool case_sensitive);
21272129

Source/ios-framework/CommonSource/Store.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public class Store: CustomDebugStringConvertible {
4343
internal(set) public var directoryPath: String
4444

4545
/// The version of this ObjectBox Swift SDK.
46-
public static var version = "4.4.1"
46+
public static var version = "5.0.0"
4747

4848
/// Pass this together with a String identifier as the directory path to use
4949
/// a file-less in-memory database.

Source/ios-framework/CommonSource/Sync/Sync.swift

Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,20 @@ public class Sync {
2525
///
2626
/// Pass either a `url` or a `urlString` (auto-converted to `URL`).
2727
///
28+
/// To configure [Sync filter](https://sync.objectbox.io/sync-server/sync-filters) variables, pass
29+
/// variable names mapped to their value to `filterVariables` .
30+
///
31+
/// Sync client filter variables can be used in server-side Sync filters to filter out objects that do not match
32+
/// the filter.
33+
///
2834
/// - Throws: `ObjectBoxError.sync` if sync is unavailable in this version of the library
2935
/// or no valid URL was provided.
3036
public static func makeClient(
31-
store: Store,
32-
url: URL? = nil,
33-
urlString: String? = nil,
34-
credentials: SyncCredentials? = nil
37+
store: Store,
38+
url: URL? = nil,
39+
urlString: String? = nil,
40+
credentials: SyncCredentials? = nil,
41+
filterVariables: [String: String]? = nil
3542
) throws -> SyncClient {
3643
let client = try makeClient(store: store, url: url, urlString: urlString)
3744

@@ -44,28 +51,57 @@ public class Sync {
4451

4552
/// Like ``makeClient(store:url:urlString:credentials:)-6rikk``, but accepts multiple credentials.
4653
public static func makeClient(
47-
store: Store,
48-
url: URL,
49-
urlString: String,
50-
credentials: [SyncCredentials]
54+
store: Store,
55+
url: URL? = nil,
56+
urlString: String? = nil,
57+
credentials: [SyncCredentials],
58+
filterVariables: [String: String]? = nil
5159
) throws -> SyncClient {
5260
let client = try makeClient(store: store, url: url, urlString: urlString)
61+
5362
try client.setCredentials(credentials)
63+
5464
return client
5565
}
5666

5767
private static func makeClient(
58-
store: Store,
59-
url: URL? = nil,
60-
urlString: String? = nil
61-
) throws -> SyncClient {
68+
store: Store,
69+
url: URL? = nil,
70+
urlString: String? = nil,
71+
filterVariables: [String: String]? = nil
72+
) throws -> SyncClientImpl {
6273
guard isAvailable() else {
6374
throw ObjectBoxError.sync(
64-
message: "This library does not include ObjectBox Sync. " +
65-
"Please visit https://objectbox.io/sync/ for options.")
75+
message: "This library does not include ObjectBox Sync. " +
76+
"Please visit https://objectbox.io/sync/ for options.")
77+
}
78+
guard store.syncClient == nil else {
79+
throw ObjectBoxError.sync(
80+
message: "Cannot create a new sync client: the store is already associated with a sync client")
6681
}
67-
throw ObjectBoxError.sync(
68-
message:
69-
"Cannot create a new sync client: no Swift implementation available (but linked library supports it)")
82+
var urlToConnect = url
83+
if urlToConnect == nil {
84+
if urlString == nil {
85+
throw ObjectBoxError.sync(message: "No URL provided")
86+
} else {
87+
urlToConnect = URL(string: urlString!)
88+
if urlToConnect == nil {
89+
throw ObjectBoxError.sync(message: "Illegal URL given:" + urlString!)
90+
}
91+
}
92+
}
93+
94+
let client = try SyncClientImpl(store: store, server: urlToConnect!)
95+
96+
// Associate store with the new client: keep the client alive and provide convenient access to it
97+
store.syncClient = client // This is not very atomic...
98+
99+
if let filterVariables = filterVariables {
100+
for (name, value) in filterVariables {
101+
try client.putFilterVariable(name: name, value: value)
102+
}
103+
}
104+
105+
return client
70106
}
71107
}

Source/ios-framework/CommonSource/Sync/SyncClient.swift

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,38 @@ public protocol SyncClient: AnyObject {
4747
/// Does nothing if this sync client has already been closed.
4848
func close()
4949

50+
/// Adds or replaces a [Sync filter](https://sync.objectbox.io/sync-server/sync-filters) variable value for the
51+
/// given name.
52+
///
53+
/// Eventually, existing values for the same name are replaced.
54+
///
55+
/// Sync client filter variables can be used in server-side Sync filters to filter out objects that do not match
56+
/// the filters. Filter variables must be added before login, so before calling `start()`.
57+
///
58+
/// - SeeAlso: `removeFilterVariable(_:)`
59+
/// - SeeAlso: `removeAllFilterVariables()`
60+
func putFilterVariable(name: String, value: String) throws
61+
62+
/// Removes a previously added Sync filter variable value.
63+
///
64+
/// - SeeAlso: `putFilterVariable(name:value:)`
65+
/// - SeeAlso: `removeAllFilterVariables()`
66+
func removeFilterVariable(_ name: String) throws
67+
68+
/// Removes all previously added Sync filter variable values.
69+
///
70+
/// - SeeAlso: `putFilterVariable(name:value:)`
71+
/// - SeeAlso: `removeFilterVariable(_:)`
72+
func removeAllFilterVariables() throws
73+
5074
/// Sets credentials to authenticate the client with the server.
5175
/// Build credentials using e.g. `SyncCredentials.makeSharedSecret(secret)`.
5276
func setCredentials(_ credentials: SyncCredentials) throws
5377

5478
/// Sets multiple credentials to authenticate the client with the server.
5579
/// Build credentials using e.g. `SyncCredentials.makeSharedSecret(secret)`.
5680
func setCredentials(_ credentials: [SyncCredentials]) throws
57-
81+
5882
/// Once the sync client is configured, you can "start" it to initiate synchronization.
5983
/// This method triggers communication in the background and will return immediately.
6084
/// If the synchronization destination is reachable, this background thread will connect to the server,

Source/ios-framework/CommonSource/Sync/SyncClientImpl.swift

Lines changed: 67 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright © 2020-2021 ObjectBox. All rights reserved.
1+
// Copyright © 2020-2025 ObjectBox. All rights reserved.
22

33
import Foundation
44

@@ -76,15 +76,15 @@ class SyncClientImpl: SyncClient {
7676

7777

7878
public var updateRequestMode: RequestUpdatesMode {
79+
get {
80+
return updateRequestModeStorage
81+
}
7982
set(newValue) {
8083
let cMode = OBXRequestUpdatesMode(newValue.rawValue)
8184
if cSync != nil && obx_sync_request_updates_mode(cSync, cMode) == OBX_SUCCESS {
8285
updateRequestModeStorage = newValue
8386
}
8487
}
85-
get {
86-
return updateRequestModeStorage
87-
}
8888
}
8989

9090
init(store: Store, server: URL) throws {
@@ -148,15 +148,70 @@ class SyncClientImpl: SyncClient {
148148
}
149149
}
150150

151+
public func putFilterVariable(name: String, value: String) throws {
152+
try ensureValid()
153+
try checkLastError(obx_sync_filter_variables_put(cSync, name, value))
154+
}
155+
156+
public func removeFilterVariable(_ name: String) throws {
157+
try ensureValid()
158+
try checkLastError(obx_sync_filter_variables_remove(cSync, name))
159+
}
160+
161+
public func removeAllFilterVariables() throws {
162+
try ensureValid()
163+
try checkLastError(obx_sync_filter_variables_remove_all(cSync))
164+
}
165+
151166
public func setCredentials(_ credentials: SyncCredentials) throws {
152167
try ensureValid()
153168
// Note: we don't store credentials in Swift memory for security reasons
154-
let credentialsLength = credentials.data.count
155-
try credentials.data.withUnsafeBytes { (rawBytes: UnsafeRawBufferPointer) -> Void in
169+
if let data = credentials.data {
170+
let credentialsLength = data.count
171+
try data.withUnsafeBytes { (rawBytes: UnsafeRawBufferPointer) in
172+
let cCredsType = OBXSyncCredentialsType(credentials.type.rawValue)
173+
obx_sync_credentials(cSync, cCredsType, rawBytes.baseAddress, credentialsLength)
174+
try checkLastError()
175+
credentialsSet = true
176+
}
177+
} else if let username = credentials.username {
156178
let cCredsType = OBXSyncCredentialsType(credentials.type.rawValue)
157-
obx_sync_credentials(cSync, cCredsType, rawBytes.baseAddress, credentialsLength)
179+
obx_sync_credentials_user_password(cSync, cCredsType, username, credentials.password!)
158180
try checkLastError()
159181
credentialsSet = true
182+
} else {
183+
throw ObjectBoxError.illegalArgument(message: "Credentials neither contain bytes data nor user/password")
184+
}
185+
}
186+
187+
public func setCredentials(_ credentials: [SyncCredentials]) throws {
188+
try ensureValid()
189+
190+
var oneCredentialSet = false
191+
192+
for (index, credential) in credentials.enumerated() {
193+
let isLast = index + 1 == credentials.count
194+
if let data = credential.data {
195+
let credentialsLength = data.count
196+
try data.withUnsafeBytes { (rawBytes: UnsafeRawBufferPointer) in
197+
let cCredsType = OBXSyncCredentialsType(credential.type.rawValue)
198+
// TODO Need new C API
199+
obx_sync_credentials_add(cSync, cCredsType, rawBytes.baseAddress, credentialsLength, isLast)
200+
try checkLastError()
201+
oneCredentialSet = true
202+
}
203+
} else if let username = credential.username {
204+
let cCredsType = OBXSyncCredentialsType(credential.type.rawValue)
205+
obx_sync_credentials_add_user_password(cSync, cCredsType, username, credential.password!, isLast)
206+
try checkLastError()
207+
oneCredentialSet = true
208+
} else {
209+
throw ObjectBoxError.illegalArgument(
210+
message: "Credentials neither contain bytes data nor user/password")
211+
}
212+
}
213+
if oneCredentialSet {
214+
credentialsSet = true
160215
}
161216
}
162217

@@ -264,32 +319,32 @@ private func callWithSyncClient(_ userData: UnsafeMutableRawPointer?, action: @e
264319
}
265320

266321
private func loginCallback(_ userData: UnsafeMutableRawPointer?) {
267-
callWithSyncClient(userData, action: { (client: SyncClient) -> Void in
322+
callWithSyncClient(userData, action: { (client: SyncClient) in
268323
client.loginListener?.loggedIn()
269324
})
270325
}
271326

272327
private func loginFailureCallback(_ userData: UnsafeMutableRawPointer?, _ cCode: OBXSyncCode) {
273328
let code = SyncCode(rawValue: cCode.rawValue)!
274-
callWithSyncClient(userData, action: { (client: SyncClient) -> Void in
329+
callWithSyncClient(userData, action: { (client: SyncClient) in
275330
client.loginListener?.loginFailed(result: code)
276331
})
277332
}
278333

279334
private func connectedCallback(_ userData: UnsafeMutableRawPointer?) {
280-
callWithSyncClient(userData, action: { (client: SyncClient) -> Void in
335+
callWithSyncClient(userData, action: { (client: SyncClient) in
281336
client.connectionListener?.connected()
282337
})
283338
}
284339

285340
private func disconnectedCallback(_ userData: UnsafeMutableRawPointer?) {
286-
callWithSyncClient(userData, action: { (client: SyncClient) -> Void in
341+
callWithSyncClient(userData, action: { (client: SyncClient) in
287342
client.connectionListener?.disconnected()
288343
})
289344
}
290345

291346
private func updatesCompletedCallback(_ userData: UnsafeMutableRawPointer?) {
292-
callWithSyncClient(userData, action: { (client: SyncClient) -> Void in
347+
callWithSyncClient(userData, action: { (client: SyncClient) in
293348
client.completedListener?.updatesCompleted()
294349
})
295350
}

0 commit comments

Comments
 (0)