Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ coverage:
status:
patch:
default:
target: 36
target: auto
changes: false
project:
default:
Expand Down
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@

### main

[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/2.2.0...main)
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/2.2.1...main)
* _Contributing to this repo? Add info about your change here to be included in the next release_

### 2.2.1
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/2.2.0...2.2.1)

__Fixes__
- Set the default cache policy for `ParseFile` to the default policy set when initializing the SDK ([#274](https://github.com/parse-community/Parse-Swift/pull/274)), thanks to [Corey Baker](https://github.com/cbaker6).

### 2.2.0
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/2.1.0...2.2.0)

Expand Down
4 changes: 1 addition & 3 deletions Sources/ParseSwift/Objects/ParseInstallation+combine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Combine

public extension ParseInstallation {

// MARK: Fetchable - Combine
// MARK: Combine
/**
Fetches the `ParseInstallation` *aynchronously* with the current data from the server
and sets an error if one occurs. Publishes when complete.
Expand All @@ -34,7 +34,6 @@ public extension ParseInstallation {
}
}

// MARK: Savable - Combine
/**
Saves the `ParseInstallation` *asynchronously* and publishes when complete.

Expand All @@ -51,7 +50,6 @@ public extension ParseInstallation {
}
}

// MARK: Deletable - Combine
/**
Deletes the `ParseInstallation` *asynchronously* and publishes when complete.

Expand Down
2 changes: 1 addition & 1 deletion Sources/ParseSwift/Objects/ParseObject+combine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Combine

public extension ParseObject {

// MARK: Fetchable - Combine
// MARK: Combine
/**
Fetches the `ParseObject` *aynchronously* with the current data from the server and sets an error if one occurs.
Publishes when complete.
Expand Down
4 changes: 1 addition & 3 deletions Sources/ParseSwift/Objects/ParseUser+combine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ public extension ParseUser {
}
}

// MARK: Fetchable - Combine
// MARK: Combine
/**
Fetches the `ParseUser` *aynchronously* with the current data from the server and sets an error if one occurs.
Publishes when complete.
Expand All @@ -157,7 +157,6 @@ public extension ParseUser {
}
}

// MARK: Savable - Combine
/**
Saves the `ParseUser` *asynchronously* and publishes when complete.

Expand Down Expand Up @@ -186,7 +185,6 @@ public extension ParseUser {
}
}

// MARK: Deletable - Combine
/**
Deletes the `ParseUser` *asynchronously* and publishes when complete.

Expand Down
18 changes: 11 additions & 7 deletions Sources/ParseSwift/Operations/ParseOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,7 @@ public struct ParseOperation<T>: Savable where T: ParseObject {
throw ParseError(code: .unknownError, message: "Target shouldn't be nil")
}
var mutableOperation = self
if let currentValue = target[keyPath: key.1] as? NSObject,
let updatedValue = value as? NSObject {
if currentValue != updatedValue {
mutableOperation.operations[key.0] = value
mutableOperation.target?[keyPath: key.1] = value
}
} else {
if !isEqual(target[keyPath: key.1], to: value) {
mutableOperation.operations[key.0] = value
mutableOperation.target?[keyPath: key.1] = value
}
Expand Down Expand Up @@ -403,6 +397,16 @@ public struct ParseOperation<T>: Savable where T: ParseObject {
try value.encode(to: encoder)
}
}

func isEqual(_ lhs: Encodable, to rhs: Encodable) -> Bool {
guard let lhsData = try? ParseCoding.parseEncoder().encode(lhs),
let lhsString = String(data: lhsData, encoding: .utf8),
let rhsData = try? ParseCoding.parseEncoder().encode(rhs),
let rhsString = String(data: rhsData, encoding: .utf8) else {
return false
}
return lhsString == rhsString
}
}

// MARK: Savable
Expand Down
2 changes: 1 addition & 1 deletion Sources/ParseSwift/ParseConstants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Foundation

enum ParseConstants {
static let sdk = "swift"
static let version = "2.2.0"
static let version = "2.2.1"
static let fileManagementDirectory = "parse/"
static let fileManagementPrivateDocumentsDirectory = "Private Documents/"
static let fileManagementLibraryDirectory = "Library/"
Expand Down
4 changes: 1 addition & 3 deletions Sources/ParseSwift/Types/ParseConfig+combine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Combine

public extension ParseConfig {

// MARK: Fetchable - Combine
// MARK: Combine

/**
Fetch the Config *asynchronously*. Publishes when complete.
Expand All @@ -28,8 +28,6 @@ public extension ParseConfig {
}
}

// MARK: Savable - Combine

/**
Update the Config *asynchronously*.
- parameter options: A set of header options sent to the server. Defaults to an empty set.
Expand Down
25 changes: 1 addition & 24 deletions Sources/ParseSwift/Types/ParseFile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -266,15 +266,12 @@ extension ParseFile {
- parameter callbackQueue: The queue to return to after synchronous completion.
Default value of .main.
- returns: A saved `ParseFile`.
- note: The default cache policy for this method is `.reloadIgnoringLocalCacheData`. If a developer
desires a different policy, it should be inserted in `options`.
*/
public func save(options: API.Options = [],
stream: InputStream,
callbackQueue: DispatchQueue = .main,
progress: ((URLSessionTask, Int64, Int64, Int64) -> Void)? = nil) throws {
var options = options
options.insert(.cachePolicy(.reloadIgnoringLocalCacheData))
if let mimeType = mimeType {
options.insert(.mimeType(mimeType))
} else {
Expand All @@ -300,13 +297,10 @@ extension ParseFile {
- parameter options: A set of header options sent to the server. Defaults to an empty set.
- parameter callbackQueue: The queue to return to after synchronous completion.
- returns: A saved `ParseFile`.
- note: The default cache policy for this method is `.reloadIgnoringLocalCacheData`. If a developer
desires a different policy, it should be inserted in `options`.
*/
public func save(options: API.Options = [],
callbackQueue: DispatchQueue) throws -> ParseFile {
var options = options
options.insert(.cachePolicy(.reloadIgnoringLocalCacheData))
if let mimeType = mimeType {
options.insert(.mimeType(mimeType))
} else {
Expand Down Expand Up @@ -376,14 +370,11 @@ extension ParseFile {
It should have the following argument signature: `(task: URLSessionDownloadTask,
bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64)`.
- returns: A saved `ParseFile`.
- note: The default cache policy for this method is `.reloadIgnoringLocalCacheData`. If a developer
desires a different policy, it should be inserted in `options`.
*/
public func save(options: API.Options = [],
callbackQueue: DispatchQueue = .main,
progress: ((URLSessionTask, Int64, Int64, Int64) -> Void)?) throws -> ParseFile {
var options = options
options.insert(.cachePolicy(.reloadIgnoringLocalCacheData))
if let mimeType = mimeType {
options.insert(.mimeType(mimeType))
} else {
Expand Down Expand Up @@ -538,8 +529,6 @@ extension ParseFile {
- parameter callbackQueue: The queue to return to after synchronous completion.
Default value of .main.
- returns: A saved `ParseFile`.
- note: The default cache policy for this method is `.reloadIgnoringLocalCacheData`. If a developer
desires a different policy, it should be inserted in `options`.
*/
public func fetch(options: API.Options = [],
stream: InputStream,
Expand All @@ -556,7 +545,6 @@ extension ParseFile {
if let tags = tags {
options.insert(.tags(tags))
}
options.insert(.cachePolicy(.reloadIgnoringLocalCacheData))
options = options.union(self.options)
return try downloadFileCommand()
.executeStream(options: options,
Expand All @@ -570,8 +558,6 @@ extension ParseFile {
- parameter options: A set of header options sent to the server. Defaults to an empty set.
- parameter callbackQueue: The queue to return to after synchronous completion.
- returns: A saved `ParseFile`.
- note: The default cache policy for this method is `.reloadIgnoringLocalCacheData`. If a developer
desires a different policy, it should be inserted in `options`.
*/
public func fetch(includeKeys: [String]? = nil,
options: API.Options = [],
Expand All @@ -588,7 +574,6 @@ extension ParseFile {
if let tags = tags {
options.insert(.tags(tags))
}
options.insert(.cachePolicy(.reloadIgnoringLocalCacheData))
options = options.union(self.options)
return try downloadFileCommand()
.execute(options: options,
Expand All @@ -600,8 +585,6 @@ extension ParseFile {
- parameter includeKeys: Currently not used for `ParseFile`.
- parameter options: A set of header options sent to the server. Defaults to an empty set.
- returns: A saved `ParseFile`.
- note: The default cache policy for this method is `.reloadIgnoringLocalCacheData`. If a developer
desires a different policy, it should be inserted in `options`.
*/
public func fetch(includeKeys: [String]? = nil,
options: API.Options = []) throws -> ParseFile {
Expand Down Expand Up @@ -649,8 +632,6 @@ extension ParseFile {
It should have the following argument signature: `(task: URLSessionDownloadTask,
bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64)`.
- returns: A saved `ParseFile`.
- note: The default cache policy for this method is `.reloadIgnoringLocalCacheData`. If a developer
desires a different policy, it should be inserted in `options`.
*/
public func fetch(options: API.Options = [],
callbackQueue: DispatchQueue = .main,
Expand All @@ -667,7 +648,6 @@ extension ParseFile {
if let tags = tags {
options.insert(.tags(tags))
}
options.insert(.cachePolicy(.reloadIgnoringLocalCacheData))
options = options.union(self.options)
return try downloadFileCommand()
.execute(options: options,
Expand Down Expand Up @@ -715,9 +695,7 @@ extension ParseFile {
It should have the following argument signature: `(task: URLSessionDownloadTask,
bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64)`.
- parameter completion: A block that will be called when file fetches or fails.
It should have the following argument signature: `(Result<Self, ParseError>)`
- note: The default cache policy for this method is `.reloadIgnoringLocalCacheData`. If a developer
desires a different policy, it should be inserted in `options`.
It should have the following argument signature: `(Result<Self, ParseError>)`.
*/
public func fetch(options: API.Options = [],
callbackQueue: DispatchQueue = .main,
Expand All @@ -735,7 +713,6 @@ extension ParseFile {
if let tags = tags {
options.insert(.tags(tags))
}
options.insert(.cachePolicy(.reloadIgnoringLocalCacheData))
options = options.union(self.options)
downloadFileCommand()
.executeAsync(options: options,
Expand Down
22 changes: 19 additions & 3 deletions Sources/ParseSwift/Types/Pointer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@ protocol ParsePointer: Encodable {
extension ParsePointer {
/**
Determines if two objects have the same objectId.

- parameter as: Object to compare.

- returns: Returns a `true` if the other object has the same `objectId` or `false` if unsuccessful.
*/
public func hasSameObjectId(as other: ParsePointer) -> Bool {
func hasSameObjectId(as other: ParsePointer) -> Bool {
return other.className == className && other.objectId == objectId
}
}
Expand Down Expand Up @@ -82,6 +80,24 @@ public struct Pointer<T: ParseObject>: ParsePointer, Fetchable, Encodable, Hasha

public extension Pointer {

/**
Determines if a `ParseObject` and `Pointer`have the same `objectId`.
- parameter as: `ParseObject` to compare.
- returns: Returns a `true` if the other object has the same `objectId` or `false` if unsuccessful.
*/
func hasSameObjectId(as other: T) -> Bool {
return other.className == className && other.objectId == objectId
}

/**
Determines if two `Pointer`'s have the same `objectId`.
- parameter as: `Pointer` to compare.
- returns: Returns a `true` if the other object has the same `objectId` or `false` if unsuccessful.
*/
func hasSameObjectId(as other: Self) -> Bool {
return other.className == className && other.objectId == objectId
}

/**
Fetches the `ParseObject` *synchronously* with the current data from the server and sets an error if one occurs.
- parameter includeKeys: The name(s) of the key(s) to include that are
Expand Down
20 changes: 20 additions & 0 deletions Tests/ParseSwiftTests/ParseOperationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,15 @@ class ParseOperationTests: XCTestCase {
let decoded = try XCTUnwrap(String(data: encoded, encoding: .utf8))
XCTAssertEqual(decoded, expected)
XCTAssertEqual(operations.target?.score, 15)
var level = Level(level: 12)
level.members = ["hello", "world"]
let operations2 = try score.operation.set(("previous", \.previous), value: [level])
let expected2 = "{\"previous\":[{\"level\":12,\"members\":[\"hello\",\"world\"]}]}"
let encoded2 = try ParseCoding.parseEncoder()
.encode(operations2)
let decoded2 = try XCTUnwrap(String(data: encoded2, encoding: .utf8))
XCTAssertEqual(decoded2, expected2)
XCTAssertEqual(operations2.target?.previous, [level])
}
#endif

Expand All @@ -516,6 +525,17 @@ class ParseOperationTests: XCTestCase {
.encode(operations)
let decoded = try XCTUnwrap(String(data: encoded, encoding: .utf8))
XCTAssertEqual(decoded, expected)
XCTAssertEqual(operations.target?.objectId, "test")
var level = Level(level: 12)
level.members = ["hello", "world"]
score.previous = [level]
let expected2 = "{}"
let operations2 = try score.operation.set(("previous", \.previous), value: [level])
let encoded2 = try ParseCoding.parseEncoder()
.encode(operations2)
let decoded2 = try XCTUnwrap(String(data: encoded2, encoding: .utf8))
XCTAssertEqual(decoded2, expected2)
XCTAssertEqual(operations2.target?.previous, [level])
}

func testUnchangedSet() throws {
Expand Down
27 changes: 27 additions & 0 deletions Tests/ParseSwiftTests/ParsePointerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,33 @@ class ParsePointerTests: XCTestCase {
XCTAssertEqual(pointer.objectId, score.objectId)
}

func testHasSameObjectId() throws {
var score = GameScore(score: 10)
let objectId = "yarr"
score.objectId = objectId
let pointer = try score.toPointer()
let pointer2 = pointer
XCTAssertTrue(pointer.hasSameObjectId(as: pointer2))
XCTAssertTrue(pointer.hasSameObjectId(as: score))
score.objectId = "hello"
let pointer3 = try score.toPointer()
XCTAssertFalse(pointer.hasSameObjectId(as: pointer3))
XCTAssertFalse(pointer.hasSameObjectId(as: score))
}

func testPointerEquality() throws {
var score = GameScore(score: 10)
let objectId = "yarr"
score.objectId = objectId
let pointer = try score.toPointer()
var score2 = GameScore(score: 10)
score2.objectId = objectId
var pointer2 = try score2.toPointer()
XCTAssertEqual(pointer, pointer2)
pointer2.objectId = "hello"
XCTAssertNotEqual(pointer, pointer2)
}

func testDetectCircularDependency() throws {
var score = GameScore(score: 10)
score.objectId = "nice"
Expand Down