Skip to content

Commit

Permalink
fix: improve equatable comparison of QueryConstraint (#275)
Browse files Browse the repository at this point in the history
* fix: improve equatable comparison of QueryConstraint

* nits
  • Loading branch information
cbaker6 committed Nov 4, 2021
1 parent af447a6 commit 37a2247
Show file tree
Hide file tree
Showing 21 changed files with 194 additions and 158 deletions.
12 changes: 9 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@

### main

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

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

__Fixes__
- Improve equatable comparison of QueryConstraint ([#275](https://github.com/parse-community/Parse-Swift/pull/275)), thanks to [Corey Baker](https://github.com/cbaker6).

### 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).
- 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 All @@ -18,7 +24,7 @@ __Improvements__
- Added ability to fetch ParsePointer using async/await ([#271](https://github.com/parse-community/Parse-Swift/pull/271)), thanks to [Corey Baker](https://github.com/cbaker6).

__Fixes__
- By default, don't use cache when fetching ParseObject's and `ParseFile`s. Developers can choose to fetch from cache if desired by passing the necessary option while fetching. Fixed a bug when the incorrect file location for a dowloaded ParseFile was being cached ([#272](https://github.com/parse-community/Parse-Swift/pull/272)), thanks to [Corey Baker](https://github.com/cbaker6).
- By default, don't use cache when fetching ParseObject's and ParseFile's. Developers can choose to fetch from cache if desired by passing the necessary option while fetching. Fixed a bug when the incorrect file location for a dowloaded ParseFile was being cached ([#272](https://github.com/parse-community/Parse-Swift/pull/272)), thanks to [Corey Baker](https://github.com/cbaker6).

### 2.1.0
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/2.0.3...2.1.0)
Expand Down
122 changes: 70 additions & 52 deletions ParseSwift.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

61 changes: 0 additions & 61 deletions Sources/ParseSwift/Coding/Extensions.swift

This file was deleted.

42 changes: 42 additions & 0 deletions Sources/ParseSwift/Coding/ParseCoding.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,48 @@ extension ParseCoding {
}
}

// MARK: Coding
public extension ParseObject {

/// The Parse encoder is used to JSON encode all `ParseObject`s and
/// types in a way meaninful for a Parse Server to consume.
static func getEncoder() -> ParseEncoder {
return ParseCoding.parseEncoder()
}

/// The Parse encoder is used to JSON encode all `ParseObject`s and
/// types in a way meaninful for a Parse Server to consume.
func getEncoder() -> ParseEncoder {
return Self.getEncoder()
}

/// The JSON encoder setup with the correct `dateEncodingStrategy`
/// strategy to send data to a Parse Server.
static func getJSONEncoder() -> JSONEncoder {
return ParseCoding.jsonEncoder()
}

/// The JSON encoder setup with the correct `dateEncodingStrategy`
/// strategy to send data to a Parse Server.
func getJSONEncoder() -> JSONEncoder {
return Self.getJSONEncoder()
}

/// The JSON decoder setup with the correct `dateDecodingStrategy`
/// strategy to decode data from a Parse Server. This encoder is used to decode all data received
/// from the server.
static func getDecoder() -> JSONDecoder {
ParseCoding.jsonDecoder()
}

/// The JSON decoder setup with the correct `dateDecodingStrategy`
/// strategy to decode data from a Parse Server. This encoder is used to decode all data received
/// from the server.
func getDecoder() -> JSONDecoder {
Self.getDecoder()
}
}

// MARK: Dates
extension ParseCoding {
enum DateEncodingKeys: String, CodingKey {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Data+hexString.swift
// Data.swift
// ParseSwift
//
// Created by Corey Baker on 2/14/21.
Expand Down
20 changes: 20 additions & 0 deletions Sources/ParseSwift/Extensions/Date.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// Date.swift
// ParseSwift
//
// Created by Corey Baker on 11/4/21.
// Copyright © 2021 Parse Community. All rights reserved.
//

import Foundation

// MARK: Date
internal extension Date {
func parseFormatted() -> String {
return ParseCoding.dateFormatter.string(from: self)
}

var parseRepresentation: [String: String] {
return ["__type": "Date", "iso": parseFormatted()]
}
}
21 changes: 21 additions & 0 deletions Sources/ParseSwift/Extensions/Encodable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// Encodable.swift
// ParseSwift
//
// Created by Corey Baker on 11/4/21.
// Copyright © 2021 Parse Community. All rights reserved.
//

import Foundation

internal extension Encodable {
func isEqual(_ other: Encodable) -> Bool {
guard let lhsData = try? ParseCoding.parseEncoder().encode(self),
let lhsString = String(data: lhsData, encoding: .utf8),
let rhsData = try? ParseCoding.parseEncoder().encode(other),
let rhsString = String(data: rhsData, encoding: .utf8) else {
return false
}
return lhsString == rhsString
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// URLCache+extensions.swift
// URLCache.swift
// ParseSwift
//
// Created by Corey Baker on 7/17/21.
Expand All @@ -11,7 +11,7 @@ import Foundation
import FoundationNetworking
#endif

extension URLCache {
internal extension URLCache {
static let parse: URLCache = {
guard let cacheURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first else {
return URLCache(memoryCapacity: ParseSwift.configuration.cacheMemoryCapacity,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//
// URLSession+extensions.swift
// URLSession.swift
// ParseSwift
//
// Original file, URLSession+sync.swift, created by Florent Vilmart on 17-09-24.
// Name change to URLSession+extensions.swift and support for sync/async by Corey Baker on 7/25/20.
// Name change to URLSession.swift and support for sync/async by Corey Baker on 7/25/20.
// Copyright © 2020 Parse Community. All rights reserved.
//

Expand All @@ -12,7 +12,7 @@ import Foundation
import FoundationNetworking
#endif

extension URLSession {
internal extension URLSession {
static let parse: URLSession = {
if !ParseSwift.configuration.isTestingSDK {
let configuration = URLSessionConfiguration.default
Expand All @@ -29,11 +29,11 @@ extension URLSession {
}
}()

internal func makeResult<U>(request: URLRequest,
responseData: Data?,
urlResponse: URLResponse?,
responseError: Error?,
mapper: @escaping (Data) throws -> U) -> Result<U, ParseError> {
func makeResult<U>(request: URLRequest,
responseData: Data?,
urlResponse: URLResponse?,
responseError: Error?,
mapper: @escaping (Data) throws -> U) -> Result<U, ParseError> {
guard let response = urlResponse else {
guard let parseError = responseError as? ParseError else {
return .failure(ParseError(code: .unknownError,
Expand Down Expand Up @@ -87,11 +87,11 @@ extension URLSession {
message: "Unable to sync with parse-server: \(String(describing: urlResponse))."))
}

internal func makeResult<U>(request: URLRequest,
location: URL?,
urlResponse: URLResponse?,
responseError: Error?,
mapper: @escaping (Data) throws -> U) -> Result<U, ParseError> {
func makeResult<U>(request: URLRequest,
location: URL?,
urlResponse: URLResponse?,
responseError: Error?,
mapper: @escaping (Data) throws -> U) -> Result<U, ParseError> {
guard let response = urlResponse else {
guard let parseError = responseError as? ParseError else {
return .failure(ParseError(code: .unknownError,
Expand Down Expand Up @@ -125,7 +125,7 @@ extension URLSession {
message: "Unable to sync with parse-server: \(response)."))
}

internal func dataTask<U>(
func dataTask<U>(
with request: URLRequest,
mapper: @escaping (Data) throws -> U,
completion: @escaping(Result<U, ParseError>) -> Void
Expand All @@ -141,8 +141,8 @@ extension URLSession {
}
}

extension URLSession {
internal func uploadTask<U>( // swiftlint:disable:this function_parameter_count
internal extension URLSession {
func uploadTask<U>( // swiftlint:disable:this function_parameter_count
callbackQueue: DispatchQueue,
with request: URLRequest,
from data: Data?,
Expand Down Expand Up @@ -176,7 +176,7 @@ extension URLSession {
}
}

internal func downloadTask<U>(
func downloadTask<U>(
callbackQueue: DispatchQueue,
with request: URLRequest,
progress: ((URLSessionDownloadTask, Int64, Int64, Int64) -> Void)?,
Expand Down Expand Up @@ -210,7 +210,7 @@ extension URLSession {
task.resume()
}

internal func downloadTask<U>(
func downloadTask<U>(
with request: URLRequest,
mapper: @escaping (Data) throws -> U,
completion: @escaping(Result<U, ParseError>) -> Void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@

import Foundation

struct BaseConfig: ParseConfig { }
struct BaseConfig: ParseConfig {}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import Foundation
You can use this protocol on any custom class of yours, instead of `Subscription` or
`SubscriptionCallback`, if it fits your use case better.
*/
public protocol QuerySubscribable: AnyObject {
public protocol QuerySubscribable: AnyObject {

/// The `ParseObject` associated with this subscription.
associatedtype Object: ParseObject
Expand Down
1 change: 0 additions & 1 deletion Sources/ParseSwift/Objects/ParseSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ extension ParseSession {
if let objectId = objectId {
return .session(objectId: objectId)
}

return .sessions
}
}
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.1"
static let version = "2.2.2"
static let fileManagementDirectory = "parse/"
static let fileManagementPrivateDocumentsDirectory = "Private Documents/"
static let fileManagementLibraryDirectory = "Library/"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import Foundation
For example, setting, deleting, or incrementing a value are all `ParseOperation`'s.
`ParseOperation` themselves can be considered to be immutable.
In most cases, you should not call this class directly as a `ParseOperation` can be
indirectly created from any `ParseObject` by using its `operation` property.
In most cases, you do not need to create an instance of `ParseOperation` directly as it can be
indirectly created from any `ParseObject` by using the respective `operation` property.
*/
public struct ParseOperation<T>: Savable where T: ParseObject {

Expand All @@ -38,7 +38,7 @@ public struct ParseOperation<T>: Savable where T: ParseObject {
throw ParseError(code: .unknownError, message: "Target shouldn't be nil")
}
var mutableOperation = self
if !isEqual(target[keyPath: key.1], to: value) {
if !target[keyPath: key.1].isEqual(value) {
mutableOperation.operations[key.0] = value
mutableOperation.target?[keyPath: key.1] = value
}
Expand Down Expand Up @@ -397,16 +397,6 @@ 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
3 changes: 3 additions & 0 deletions Sources/ParseSwift/Types/ParseRelation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import Foundation
/**
The `ParseRelation` class that is used to access all of the children of a many-to-many relationship.
Each instance of `ParseRelation` is associated with a particular parent object and key.
In most cases, you do not need to create an instance of `ParseOperation` directly as it can be
indirectly created from any `ParseObject` by using the respective `relation` property.
*/
public struct ParseRelation<T>: Codable, Hashable where T: ParseObject {
internal let __type: String = "Relation" // swiftlint:disable:this identifier_name
Expand Down
6 changes: 2 additions & 4 deletions Sources/ParseSwift/Types/Query.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,10 @@ public struct QueryConstraint: Encodable, Equatable {

public static func == (lhs: QueryConstraint, rhs: QueryConstraint) -> Bool {
guard lhs.key == rhs.key,
lhs.comparator == rhs.comparator,
let lhsObject = lhs.value as? NSObject,
let rhsObject = rhs.value as? NSObject else {
lhs.comparator == rhs.comparator else {
return false
}
return lhsObject == rhsObject
return lhs.value.isEqual(rhs.value)
}
}

Expand Down

0 comments on commit 37a2247

Please sign in to comment.