Skip to content

Commit f7849ab

Browse files
Merge pull request #872 from apollographql/add/extensions
Convenience extensions and reorganization
2 parents d3fc367 + 1abaeea commit f7849ab

13 files changed

Lines changed: 190 additions & 154 deletions

Apollo.xcodeproj/project.pbxproj

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
9BDE43D122C6655300FD7C7F /* Cancellable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BDE43D022C6655200FD7C7F /* Cancellable.swift */; };
2222
9BDE43DD22C6705300FD7C7F /* GraphQLHTTPResponseError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BDE43DC22C6705300FD7C7F /* GraphQLHTTPResponseError.swift */; };
2323
9BDE43DF22C6708600FD7C7F /* GraphQLHTTPRequestError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BDE43DE22C6708600FD7C7F /* GraphQLHTTPRequestError.swift */; };
24+
9BE071AD2368D08700FA5952 /* Collection+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BE071AC2368D08700FA5952 /* Collection+Helpers.swift */; };
25+
9BE071AF2368D34D00FA5952 /* Matchable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BE071AE2368D34D00FA5952 /* Matchable.swift */; };
26+
9BE071B12368D3F500FA5952 /* Dictionary+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BE071B02368D3F500FA5952 /* Dictionary+Helpers.swift */; };
2427
9BEDC79E22E5D2CF00549BF6 /* RequestCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BEDC79D22E5D2CF00549BF6 /* RequestCreator.swift */; };
2528
9BF1A94F22CA5784005292C2 /* HTTPTransportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BF1A94C22CA54F9005292C2 /* HTTPTransportTests.swift */; };
2629
9BF1A95122CA6E71005292C2 /* GraphQLGETTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BF1A95022CA6E71005292C2 /* GraphQLGETTransformer.swift */; };
@@ -36,7 +39,7 @@
3639
9F438D081E6C30B1007BDC1A /* StarWarsAPI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9FCE2CFA1E6C213D00E34457 /* StarWarsAPI.framework */; };
3740
9F533AB31E6C4A4200CBE097 /* BatchedLoadTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F438D0B1E6C494C007BDC1A /* BatchedLoadTests.swift */; };
3841
9F55347B1DE1DB2100E54264 /* ApolloStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F55347A1DE1DB2100E54264 /* ApolloStore.swift */; };
39-
9F578D901D8D2CB300C0EA36 /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F578D8F1D8D2CB300C0EA36 /* Utilities.swift */; };
42+
9F578D901D8D2CB300C0EA36 /* HTTPURLResponse+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F578D8F1D8D2CB300C0EA36 /* HTTPURLResponse+Helpers.swift */; };
4043
9F65B1211EC106F30090B25F /* Apollo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9FC750441D2A532C00458D91 /* Apollo.framework */; };
4144
9F69FFA91D42855900E000B1 /* NetworkTransport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F69FFA81D42855900E000B1 /* NetworkTransport.swift */; };
4245
9F7BA89922927A3700999B3B /* ResponsePath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F7BA89822927A3700999B3B /* ResponsePath.swift */; };
@@ -101,7 +104,7 @@
101104
9FE1C6E71E634C8D00C02284 /* PromiseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FE1C6E61E634C8D00C02284 /* PromiseTests.swift */; };
102105
9FE941D01E62C771007CDD89 /* Promise.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FE941CF1E62C771007CDD89 /* Promise.swift */; };
103106
9FEB050D1DB5732300DA3B44 /* JSONSerializationFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FEB050C1DB5732300DA3B44 /* JSONSerializationFormat.swift */; };
104-
9FEC15B41E681DAD00D461B4 /* Collections.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FEC15B31E681DAD00D461B4 /* Collections.swift */; };
107+
9FEC15B41E681DAD00D461B4 /* GroupedSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FEC15B31E681DAD00D461B4 /* GroupedSequence.swift */; };
105108
9FF33D811E48B98200F608A4 /* HTTPNetworkTransport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F4DAF2D1E48B84B00EBFF0B /* HTTPNetworkTransport.swift */; };
106109
9FF90A611DDDEB100034C3B6 /* GraphQLResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FF90A5B1DDDEB100034C3B6 /* GraphQLResponse.swift */; };
107110
9FF90A651DDDEB100034C3B6 /* GraphQLExecutor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FF90A5C1DDDEB100034C3B6 /* GraphQLExecutor.swift */; };
@@ -283,6 +286,9 @@
283286
9BDE43D022C6655200FD7C7F /* Cancellable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cancellable.swift; sourceTree = "<group>"; };
284287
9BDE43DC22C6705300FD7C7F /* GraphQLHTTPResponseError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphQLHTTPResponseError.swift; sourceTree = "<group>"; };
285288
9BDE43DE22C6708600FD7C7F /* GraphQLHTTPRequestError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphQLHTTPRequestError.swift; sourceTree = "<group>"; };
289+
9BE071AC2368D08700FA5952 /* Collection+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Collection+Helpers.swift"; sourceTree = "<group>"; };
290+
9BE071AE2368D34D00FA5952 /* Matchable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Matchable.swift; sourceTree = "<group>"; };
291+
9BE071B02368D3F500FA5952 /* Dictionary+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Dictionary+Helpers.swift"; sourceTree = "<group>"; };
286292
9BEDC79D22E5D2CF00549BF6 /* RequestCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestCreator.swift; sourceTree = "<group>"; };
287293
9BF1A94C22CA54F9005292C2 /* HTTPTransportTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPTransportTests.swift; sourceTree = "<group>"; };
288294
9BF1A95022CA6E71005292C2 /* GraphQLGETTransformer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphQLGETTransformer.swift; sourceTree = "<group>"; };
@@ -296,7 +302,7 @@
296302
9F438D0B1E6C494C007BDC1A /* BatchedLoadTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BatchedLoadTests.swift; sourceTree = "<group>"; };
297303
9F4DAF2D1E48B84B00EBFF0B /* HTTPNetworkTransport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPNetworkTransport.swift; sourceTree = "<group>"; };
298304
9F55347A1DE1DB2100E54264 /* ApolloStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApolloStore.swift; sourceTree = "<group>"; };
299-
9F578D8F1D8D2CB300C0EA36 /* Utilities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Utilities.swift; sourceTree = "<group>"; };
305+
9F578D8F1D8D2CB300C0EA36 /* HTTPURLResponse+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "HTTPURLResponse+Helpers.swift"; sourceTree = "<group>"; };
300306
9F69FFA81D42855900E000B1 /* NetworkTransport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkTransport.swift; sourceTree = "<group>"; };
301307
9F7BA89822927A3700999B3B /* ResponsePath.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResponsePath.swift; sourceTree = "<group>"; };
302308
9F8622F71EC2004200C38162 /* ReadWriteFromStoreTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReadWriteFromStoreTests.swift; sourceTree = "<group>"; };
@@ -379,7 +385,7 @@
379385
9FE1C6E61E634C8D00C02284 /* PromiseTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PromiseTests.swift; sourceTree = "<group>"; };
380386
9FE941CF1E62C771007CDD89 /* Promise.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Promise.swift; sourceTree = "<group>"; };
381387
9FEB050C1DB5732300DA3B44 /* JSONSerializationFormat.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSONSerializationFormat.swift; sourceTree = "<group>"; };
382-
9FEC15B31E681DAD00D461B4 /* Collections.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Collections.swift; sourceTree = "<group>"; };
388+
9FEC15B31E681DAD00D461B4 /* GroupedSequence.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupedSequence.swift; sourceTree = "<group>"; };
383389
9FF90A5B1DDDEB100034C3B6 /* GraphQLResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphQLResponse.swift; sourceTree = "<group>"; };
384390
9FF90A5C1DDDEB100034C3B6 /* GraphQLExecutor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphQLExecutor.swift; sourceTree = "<group>"; };
385391
9FF90A6A1DDDEB420034C3B6 /* InputValueEncodingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputValueEncodingTests.swift; sourceTree = "<group>"; };
@@ -530,6 +536,7 @@
530536
isa = PBXGroup;
531537
children = (
532538
9BDE43D022C6655200FD7C7F /* Cancellable.swift */,
539+
9BE071AE2368D34D00FA5952 /* Matchable.swift */,
533540
);
534541
name = Protocols;
535542
sourceTree = "<group>";
@@ -727,14 +734,16 @@
727734
children = (
728735
9FCDFD221E33A0D8007519DC /* AsynchronousOperation.swift */,
729736
9B1CCDD82360F02C007C9032 /* Bundle+Helpers.swift */,
737+
9BE071AC2368D08700FA5952 /* Collection+Helpers.swift */,
738+
9BE071B02368D3F500FA5952 /* Dictionary+Helpers.swift */,
730739
9BA3130D2302BEA5007B7FC5 /* DispatchQueue+Optional.swift */,
740+
9FEC15B31E681DAD00D461B4 /* GroupedSequence.swift */,
741+
9F578D8F1D8D2CB300C0EA36 /* HTTPURLResponse+Helpers.swift */,
742+
9FADC8491E6B0B2300C677E6 /* Locking.swift */,
731743
9FE941CF1E62C771007CDD89 /* Promise.swift */,
732744
9BA1245D22DE116B00BF1D24 /* Result+Helpers.swift */,
733745
9F19D8431EED568200C57247 /* ResultOrPromise.swift */,
734-
9FEC15B31E681DAD00D461B4 /* Collections.swift */,
735-
9FADC8491E6B0B2300C677E6 /* Locking.swift */,
736746
9B1A38522332AF6F00325FB4 /* String+SHA.swift */,
737-
9F578D8F1D8D2CB300C0EA36 /* Utilities.swift */,
738747
);
739748
name = Utilities;
740749
sourceTree = "<group>";
@@ -1216,7 +1225,9 @@
12161225
9F86B68B1E6438D700B885FF /* GraphQLSelectionSetMapper.swift in Sources */,
12171226
9F55347B1DE1DB2100E54264 /* ApolloStore.swift in Sources */,
12181227
9BDE43D122C6655300FD7C7F /* Cancellable.swift in Sources */,
1228+
9BE071B12368D3F500FA5952 /* Dictionary+Helpers.swift in Sources */,
12191229
9F69FFA91D42855900E000B1 /* NetworkTransport.swift in Sources */,
1230+
9BE071AF2368D34D00FA5952 /* Matchable.swift in Sources */,
12201231
9FCDFD291E33D0CE007519DC /* GraphQLQueryWatcher.swift in Sources */,
12211232
9FC2333D1E66BBF7001E4541 /* GraphQLDependencyTracker.swift in Sources */,
12221233
9F19D8441EED568200C57247 /* ResultOrPromise.swift in Sources */,
@@ -1232,8 +1243,8 @@
12321243
C377CCA922D798BD00572E03 /* GraphQLFile.swift in Sources */,
12331244
9FC9A9CC1E2FD0760023C4D5 /* Record.swift in Sources */,
12341245
9FC4B9201D2A6F8D0046A641 /* JSON.swift in Sources */,
1235-
9FEC15B41E681DAD00D461B4 /* Collections.swift in Sources */,
1236-
9F578D901D8D2CB300C0EA36 /* Utilities.swift in Sources */,
1246+
9FEC15B41E681DAD00D461B4 /* GroupedSequence.swift in Sources */,
1247+
9F578D901D8D2CB300C0EA36 /* HTTPURLResponse+Helpers.swift in Sources */,
12371248
9F7BA89922927A3700999B3B /* ResponsePath.swift in Sources */,
12381249
9FC9A9BD1E2C271C0023C4D5 /* RecordSet.swift in Sources */,
12391250
9BF1A95122CA6E71005292C2 /* GraphQLGETTransformer.swift in Sources */,
@@ -1242,6 +1253,7 @@
12421253
9F27D4641D40379500715680 /* JSONStandardTypeConversions.swift in Sources */,
12431254
9B1A38532332AF6F00325FB4 /* String+SHA.swift in Sources */,
12441255
9BEDC79E22E5D2CF00549BF6 /* RequestCreator.swift in Sources */,
1256+
9BE071AD2368D08700FA5952 /* Collection+Helpers.swift in Sources */,
12451257
9FA6F3681E65DF4700BF8D73 /* GraphQLResultAccumulator.swift in Sources */,
12461258
9FF90A651DDDEB100034C3B6 /* GraphQLExecutor.swift in Sources */,
12471259
9FC750611D2A59C300458D91 /* GraphQLOperation.swift in Sources */,

Sources/Apollo/Bundle+Helpers.swift

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,3 @@
1-
//
2-
// Bundle+Helpers.swift
3-
// Apollo
4-
//
5-
// Created by Ellen Shapiro on 10/23/19.
6-
// Copyright © 2019 Apollo GraphQL. All rights reserved.
7-
//
8-
91
import Foundation
102

113
extension Bundle {
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import Foundation
2+
3+
// MARK: - Emptiness + Optionality
4+
5+
extension Collection {
6+
7+
/// Convenience helper to make `guard` statements more readable
8+
///
9+
/// - returns: `true` if the collection has contents.
10+
var isNotEmpty: Bool {
11+
return !self.isEmpty
12+
}
13+
}
14+
15+
extension Optional where Wrapped: Collection {
16+
17+
/// - returns: `true` if the collection is empty or nil
18+
var isEmptyOrNil: Bool {
19+
switch self {
20+
case .none:
21+
return true
22+
case .some(let collection):
23+
return collection.isEmpty
24+
}
25+
}
26+
27+
/// - returns: `true` if the collection is non-nil AND has contents.
28+
var isNotEmpty: Bool {
29+
switch self {
30+
case .none:
31+
return false
32+
case .some(let collection):
33+
return collection.isNotEmpty
34+
}
35+
}
36+
}
37+
38+
// MARK: - Unzipping
39+
// MARK: Arrays of tuples to tuples of arrays
40+
41+
public func unzip<Element1, Element2>(_ array: [(Element1, Element2)]) -> ([Element1], [Element2]) {
42+
var array1: [Element1] = []
43+
var array2: [Element2] = []
44+
45+
for element in array {
46+
array1.append(element.0)
47+
array2.append(element.1)
48+
}
49+
50+
return (array1, array2)
51+
}
52+
53+
public func unzip<Element1, Element2, Element3>(_ array: [(Element1, Element2, Element3)]) -> ([Element1], [Element2], [Element3]) {
54+
var array1: [Element1] = []
55+
var array2: [Element2] = []
56+
var array3: [Element3] = []
57+
58+
for element in array {
59+
array1.append(element.0)
60+
array2.append(element.1)
61+
array3.append(element.2)
62+
}
63+
64+
return (array1, array2, array3)
65+
}

Sources/Apollo/Collections.swift

Lines changed: 0 additions & 94 deletions
This file was deleted.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
public extension Dictionary {
2+
static func += (lhs: inout Dictionary, rhs: Dictionary) {
3+
lhs.merge(rhs) { (_, new) in new }
4+
}
5+
}
6+
7+
extension Dictionary {
8+
init<S: Sequence>(_ entries: S) where S.Iterator.Element == Element {
9+
self = Dictionary(minimumCapacity: entries.underestimatedCount)
10+
for (key, value) in entries {
11+
self[key] = value
12+
}
13+
}
14+
}

Sources/Apollo/DispatchQueue+Optional.swift

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,3 @@
1-
//
2-
// DispatchQueue+Optional.swift
3-
// Apollo
4-
//
5-
// Created by Ellen Shapiro on 8/13/19.
6-
// Copyright © 2019 Apollo GraphQL. All rights reserved.
7-
//
8-
91
import Foundation
102

113
public extension DispatchQueue {

Sources/Apollo/GraphQLSelectionSet.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,11 @@ public struct GraphQLField: GraphQLSelection {
5151
}
5252

5353
func cacheKey(with variables: [String: JSONEncodable]?) throws -> String {
54-
if let argumentValues = try arguments?.evaluate(with: variables), !argumentValues.isEmpty {
55-
let argumentsKey = orderIndependentKey(for: argumentValues)
56-
return "\(name)(\(argumentsKey))"
54+
if
55+
let argumentValues = try arguments?.evaluate(with: variables),
56+
argumentValues.isNotEmpty {
57+
let argumentsKey = orderIndependentKey(for: argumentValues)
58+
return "\(name)(\(argumentsKey))"
5759
} else {
5860
return name
5961
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
struct GroupedSequence<Key: Equatable, Value> {
2+
private(set) var keys: [Key] = []
3+
fileprivate var groupsForKeys: [[Value]] = []
4+
5+
mutating func append(value: Value, forKey key: Key) -> (Int, Int) {
6+
if let index = keys.firstIndex(where: { $0 == key }) {
7+
groupsForKeys[index].append(value)
8+
return (index, groupsForKeys[index].endIndex - 1)
9+
} else {
10+
keys.append(key)
11+
groupsForKeys.append([value])
12+
return (keys.endIndex - 1, 0)
13+
}
14+
}
15+
}
16+
17+
extension GroupedSequence: Sequence {
18+
func makeIterator() -> GroupedSequenceIterator<Key, Value> {
19+
return GroupedSequenceIterator(base: self)
20+
}
21+
}
22+
23+
struct GroupedSequenceIterator<Key: Equatable, Value>: IteratorProtocol {
24+
private var base: GroupedSequence<Key, Value>
25+
26+
private var keyIterator: EnumeratedSequence<Array<Key>>.Iterator
27+
28+
init(base: GroupedSequence<Key, Value>) {
29+
self.base = base
30+
keyIterator = base.keys.enumerated().makeIterator()
31+
}
32+
33+
mutating func next() -> (Key, [Value])? {
34+
if let (index, key) = keyIterator.next() {
35+
let values = base.groupsForKeys[index]
36+
return (key, values)
37+
} else {
38+
return nil
39+
}
40+
}
41+
}

0 commit comments

Comments
 (0)