Skip to content

Commit be38455

Browse files
authored
Merge pull request #278 from zapcannon87/developer
feat(storage): expressible by array literal of LCArray support LCValueConvertible
2 parents 499b271 + 52784c2 commit be38455

File tree

4 files changed

+109
-112
lines changed

4 files changed

+109
-112
lines changed

LeanCloudTests/LCEngineTestCase.swift

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,25 @@ import XCTest
1111

1212
class LCEngineTestCase: BaseTestCase {
1313

14-
func testEngineFunction() {
15-
XCTAssertEqual(LCEngine.run("test").value as? String, "test")
14+
func testFunction() {
15+
let result = LCEngine.run("test")
16+
XCTAssertEqual(result.value as? String, "test")
17+
XCTAssertNil(result.error)
1618
}
1719

18-
func testEngineRPC() {
19-
XCTAssertTrue(LCEngine.call("test").isSuccess)
20+
func testError() {
21+
let result = LCEngine.run("error")
22+
XCTAssertNil(result.value)
23+
XCTAssertNotNil(LCEngine.run("error").error)
24+
}
25+
26+
func testGetOnOffStatus() {
27+
let result = LCEngine.run(
28+
"getOnOffStatus",
29+
parameters: ["peerIds":
30+
["FCA6CAA7E5A14748BA25DE46EC1B66C8",
31+
UUID().uuidString]])
32+
XCTAssertEqual((result.value as? [Any])?.count, 2)
33+
XCTAssertNil(result.error)
2034
}
21-
2235
}

LeanCloudTests/LCTypeTestCase.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ class LCTypeTestCase: BaseTestCase {
6565
LCArray([42, true, NSNull(), [String: String](), [String](), Data(), date, object]),
6666
try LCArray(unsafeObject: [42, true, NSNull(), [String: String](), [String](), Data(), date, object]))
6767
}
68+
69+
func testArrayLiteral() {
70+
let _: LCArray = ["a"]
71+
let _: LCArray = ["a", 1]
72+
let _: LCArray = ["a", LCNumber(1)]
73+
let _: LCArray = [LCString("a"), 1]
74+
let _: LCArray = [LCString("a"), LCNumber(1)]
75+
}
6876

6977
func testDictionaryConvertible() {
7078
let date = Date()

Sources/Foundation/Array.swift

Lines changed: 66 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,8 @@
88

99
import Foundation
1010

11-
/**
12-
LeanCloud list type.
13-
14-
It is a wrapper of `Swift.Array` type, used to store a list of objects.
15-
*/
16-
public final class LCArray: NSObject, LCValue, LCValueExtension, Collection, ExpressibleByArrayLiteral {
11+
/// LeanCloud List Type
12+
public class LCArray: NSObject, LCValue, Collection, ExpressibleByArrayLiteral {
1713
public typealias Index = Int
1814
public typealias Element = LCValue
1915

@@ -30,137 +26,148 @@ public final class LCArray: NSObject, LCValue, LCValueExtension, Collection, Exp
3026

3127
public convenience init(_ value: [LCValueConvertible]) {
3228
self.init()
33-
self.value = value.map { element in element.lcValue }
29+
self.value = value.map { $0.lcValue }
3430
}
3531

36-
public convenience required init(arrayLiteral elements: Element...) {
32+
public convenience required init(arrayLiteral elements: LCValueConvertible...) {
3733
self.init(elements)
3834
}
3935

4036
public convenience init(
41-
application: LCApplication = LCApplication.default,
37+
application: LCApplication = .default,
4238
unsafeObject: Any)
4339
throws
4440
{
4541
self.init()
46-
4742
guard let object = unsafeObject as? [Any] else {
4843
throw LCError(
4944
code: .malformedData,
50-
reason: "Failed to construct LCArray with non-array object.")
45+
reason: "Failed to construct \(LCArray.self) with a \(type(of: unsafeObject)) object.")
5146
}
52-
53-
value = try object.map { element in
47+
self.value = try object.map { element in
5448
try ObjectProfiler.shared.object(application: application, jsonValue: element)
5549
}
5650
}
5751

5852
public required init?(coder aDecoder: NSCoder) {
59-
value = (aDecoder.decodeObject(forKey: "value") as? [Element]) ?? []
53+
self.value = (aDecoder.decodeObject(forKey: "value") as? [Element]) ?? []
6054
}
6155

6256
public func encode(with aCoder: NSCoder) {
63-
aCoder.encode(value, forKey: "value")
57+
aCoder.encode(self.value, forKey: "value")
6458
}
6559

6660
public func copy(with zone: NSZone?) -> Any {
67-
return LCArray(value)
61+
return LCArray(self.value)
6862
}
6963

7064
public override func isEqual(_ object: Any?) -> Bool {
7165
if let object = object as? LCArray {
72-
return object === self || object.value == value
66+
return object === self || object.value == self.value
7367
} else {
7468
return false
7569
}
7670
}
7771

7872
public func makeIterator() -> IndexingIterator<[Element]> {
79-
return value.makeIterator()
73+
return self.value.makeIterator()
8074
}
8175

8276
public var startIndex: Int {
8377
return 0
8478
}
8579

8680
public var endIndex: Int {
87-
return value.count
81+
return self.value.count
8882
}
8983

9084
public func index(after i: Int) -> Int {
91-
return value.index(after: i)
85+
return self.value.index(after: i)
9286
}
9387

9488
public subscript(index: Int) -> LCValue {
95-
get { return value[index] }
89+
get {
90+
return self.value[index]
91+
}
9692
}
9793

9894
public var jsonValue: Any {
99-
return value.map { element in element.jsonValue }
100-
}
101-
102-
func formattedJSONString(indentLevel: Int, numberOfSpacesForOneIndentLevel: Int = 4) -> String {
103-
if value.isEmpty {
104-
return "[]"
105-
}
106-
107-
let lastIndent = " " * (numberOfSpacesForOneIndentLevel * indentLevel)
108-
let bodyIndent = " " * (numberOfSpacesForOneIndentLevel * (indentLevel + 1))
109-
let body = value
110-
.map { value in (value as! LCValueExtension).formattedJSONString(indentLevel: indentLevel + 1, numberOfSpacesForOneIndentLevel: numberOfSpacesForOneIndentLevel) }
111-
.joined(separator: ",\n" + bodyIndent)
112-
113-
return "[\n\(bodyIndent)\(body)\n\(lastIndent)]"
95+
return self.value.map { $0.jsonValue }
11496
}
11597

11698
public var jsonString: String {
117-
return formattedJSONString(indentLevel: 0)
99+
return self.formattedJSONString(indentLevel: 0)
118100
}
119101

120102
public var rawValue: Any {
121-
let v: [Any] = self.value.map { element in element.rawValue }
122-
return v
103+
return self.value.map { $0.rawValue }
123104
}
105+
}
124106

107+
extension LCArray: LCValueExtension {
108+
125109
var lconValue: Any? {
126-
return value.compactMap { element in (element as? LCValueExtension)?.lconValue }
110+
return self.value.compactMap { ($0 as? LCValueExtension)?.lconValue }
127111
}
128112

129113
static func instance(application: LCApplication) -> LCValue {
130-
return self.init([])
114+
return self.init()
131115
}
132-
116+
133117
func forEachChild(_ body: (_ child: LCValue) throws -> Void) rethrows {
134-
try forEach { element in try body(element) }
118+
try forEach { try body($0) }
135119
}
136-
120+
137121
func add(_ other: LCValue) throws -> LCValue {
138-
throw LCError(code: .invalidType, reason: "Object cannot be added.")
122+
throw LCError(
123+
code: .invalidType,
124+
reason: "\(LCArray.self) cannot do `add(_:)`.")
139125
}
140-
126+
141127
func concatenate(_ other: LCValue, unique: Bool) throws -> LCValue {
142-
let result = LCArray(value)
143-
let elements = (other as! LCArray).value
144-
128+
guard let elements = (other as? LCArray)?.value else {
129+
throw LCError(
130+
code: .invalidType,
131+
reason: "\(LCArray.self) cannot do `concatenate(_:unique:)` with a \(type(of: other)) object.")
132+
}
133+
let result = LCArray(self.value)
145134
result.concatenateInPlace(elements, unique: unique)
146-
147135
return result
148136
}
149-
137+
150138
func concatenateInPlace(_ elements: [Element], unique: Bool) {
151-
value = unique ? (value +~ elements) : (value + elements)
139+
self.value = unique
140+
? (self.value +~ elements)
141+
: (self.value + elements)
152142
}
153-
143+
154144
func differ(_ other: LCValue) throws -> LCValue {
155-
let result = LCArray(value)
156-
let elements = (other as! LCArray).value
157-
145+
guard let elements = (other as? LCArray)?.value else {
146+
throw LCError(
147+
code: .invalidType,
148+
reason: "\(LCArray.self) cannot do `differ(_:)` with a \(type(of: other)) object.")
149+
}
150+
let result = LCArray(self.value)
158151
result.differInPlace(elements)
159-
160152
return result
161153
}
162-
154+
163155
func differInPlace(_ elements: [Element]) {
164-
value = value - elements
156+
self.value = (self.value - elements)
157+
}
158+
159+
func formattedJSONString(indentLevel: Int, numberOfSpacesForOneIndentLevel: Int = 4) -> String {
160+
if self.value.isEmpty {
161+
return "[]"
162+
}
163+
let lastIndent = " " * (numberOfSpacesForOneIndentLevel * indentLevel)
164+
let bodyIndent = " " * (numberOfSpacesForOneIndentLevel * (indentLevel + 1))
165+
let body = self.value
166+
.compactMap {
167+
($0 as? LCValueExtension)?.formattedJSONString(
168+
indentLevel: indentLevel + 1,
169+
numberOfSpacesForOneIndentLevel: numberOfSpacesForOneIndentLevel) }
170+
.joined(separator: ",\n" + bodyIndent)
171+
return "[\n\(bodyIndent)\(body)\n\(lastIndent)]"
165172
}
166173
}

Sources/Foundation/Extension.swift

Lines changed: 17 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ func ==(lhs: [LCDictionary.Key: LCDictionary.Value], rhs: [LCDictionary.Key: LCD
108108
}
109109

110110
extension Dictionary {
111+
111112
init(elements: [Element]) {
112113
self.init()
113114

@@ -133,47 +134,20 @@ extension Dictionary {
133134
return Dictionary<Key, T>(elements: elements)
134135
}
135136

136-
/*
137-
Maybe you will think: Why use JSONSerialization encoding and decoding `Dictionary` ?
138-
139-
Because a Swift Raw Data Type `[String: Any]` is Strong-Type-Checking.
140-
141-
e.g.
142-
```
143-
var dic: [String: Any] = ["foo": Int32(1)]
144-
(dic["foo"] as? Int) == nil
145-
(dic["foo"] as? Int32) == Optional(1)
146-
```
147-
148-
But after JSONSerialization's encoding and decoding.
149-
150-
The Swift Type `[String: Any]` has been converted to a Real JSON Object.
151-
152-
```
153-
dic = try! dic.jsonObject()
154-
(dic["foo"] as? Int) == Optional(1)
155-
(dic["foo"] as? Int32) == Optional(1)
156-
```
157-
158-
This will make data better for SDK to handle it.
159-
*/
160137
func jsonObject() throws -> [Key: Value]? {
161-
let data: Data = try JSONSerialization.data(withJSONObject: self)
162-
if let json: [Key: Value] = try JSONSerialization.jsonObject(with: data) as? [Key: Value] {
163-
return json
164-
} else {
165-
return nil
166-
}
138+
return try JSONSerialization.jsonObject(with:
139+
try JSONSerialization.data(withJSONObject: self))
140+
as? [Key: Value]
167141
}
168142

169143
func jsonString(
170144
using encoding: String.Encoding = .utf8,
171145
options: JSONSerialization.WritingOptions = [])
172-
throws
173-
-> String?
146+
throws -> String?
174147
{
175-
let data: Data = try JSONSerialization.data(withJSONObject: self, options: options)
176-
return String(data: data, encoding: encoding)
148+
return String(
149+
data: try JSONSerialization.data(withJSONObject: self, options: options),
150+
encoding: encoding)
177151
}
178152
}
179153

@@ -222,17 +196,13 @@ extension String {
222196
func jsonObject<T>(
223197
using encoding: String.Encoding = .utf8,
224198
options: JSONSerialization.ReadingOptions = [])
225-
throws
226-
-> T?
199+
throws -> T?
227200
{
228-
guard !self.isEmpty else {
229-
return nil
230-
}
231-
if let data: Data = self.data(using: encoding) {
232-
return try JSONSerialization.jsonObject(with: data, options: options) as? T
233-
} else {
234-
return nil
201+
guard !self.isEmpty,
202+
let data = self.data(using: encoding) else {
203+
return nil
235204
}
205+
return try JSONSerialization.jsonObject(with: data, options: options) as? T
236206
}
237207
}
238208

@@ -245,11 +215,11 @@ extension Sequence {
245215
func jsonString(
246216
using encoding: String.Encoding = .utf8,
247217
options: JSONSerialization.WritingOptions = [])
248-
throws
249-
-> String?
218+
throws -> String?
250219
{
251-
let data: Data = try JSONSerialization.data(withJSONObject: self, options: options)
252-
return String(data: data, encoding: encoding)
220+
return String(
221+
data: try JSONSerialization.data(withJSONObject: self, options: options),
222+
encoding: encoding)
253223
}
254224
}
255225

@@ -303,7 +273,6 @@ extension LCError {
303273
self = LCError(error: error)
304274
}
305275
}
306-
307276
}
308277

309278
/**

0 commit comments

Comments
 (0)