mirror of
https://github.com/caoer/CodableFirebase.git
synced 2026-06-11 15:42:41 +08:00
Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ac3efc8b8 | ||
|
|
55b8bd92c1 | ||
|
|
9885bf2381 | ||
|
|
5e9f86496e | ||
|
|
9b65f4e473 | ||
|
|
cef13572db | ||
|
|
03459ec82a | ||
|
|
8ff6771f42 | ||
|
|
3767b9a771 | ||
|
|
c722389e5c | ||
|
|
6b0b78e597 | ||
|
|
1fbf4295b3 | ||
|
|
8ed17c7aec | ||
|
|
3cae6e90d9 | ||
|
|
222b080693 | ||
|
|
5b8627dbbe | ||
|
|
1384814716 | ||
|
|
b0e86866a0 | ||
|
|
0c60f70d91 | ||
|
|
df9dfe1dda | ||
|
|
2afa8c101c | ||
|
|
ec22c1649e | ||
|
|
8279c70901 | ||
|
|
c4ed0ec8eb | ||
|
|
fcfb7b8b1e | ||
|
|
747d540d77 | ||
|
|
e6947deb6b | ||
|
|
eaf809498a | ||
|
|
3a08c9e650 | ||
|
|
4cfd13702b | ||
|
|
3c61d54654 | ||
|
|
2528453f9b | ||
|
|
587db265cd | ||
|
|
04facd2f6d | ||
|
|
f3eed29a7d | ||
|
|
7aff81a267 | ||
|
|
9fa47dd610 | ||
|
|
31ecb57f14 | ||
|
|
6a6fcc1d07 | ||
|
|
02cd074714 | ||
|
|
69d0a835be | ||
|
|
e0b61e57e5 | ||
|
|
e32bd8f4d6 |
@@ -1,5 +1,5 @@
|
||||
language: objective-c
|
||||
osx_image: xcode9.2
|
||||
osx_image: xcode9.3
|
||||
|
||||
env:
|
||||
- ACTION=test PLATFORM=Mac DESTINATION='platform=OS X'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "CodableFirebase"
|
||||
s.version = "0.0.3"
|
||||
s.version = "0.0.10"
|
||||
s.summary = "Use Codable with Firebase"
|
||||
s.description = "This library helps you use your custom models that conform to Codable protocol with Firebase Realtime Database and Firestore"
|
||||
s.homepage = "https://github.com/alickbass/CodableFirebase"
|
||||
@@ -15,6 +15,5 @@ Pod::Spec.new do |s|
|
||||
|
||||
s.source = { :git => "https://github.com/alickbass/CodableFirebase.git", :tag => s.version, :branch => 'master'}
|
||||
s.source_files = "CodableFirebase/*.swift"
|
||||
s.pod_target_xcconfig = { 'SWIFT_VERSION' => '4' }
|
||||
|
||||
s.swift_version = '4.1'
|
||||
end
|
||||
|
||||
@@ -167,7 +167,7 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0900;
|
||||
LastUpgradeCheck = 0900;
|
||||
LastUpgradeCheck = 0930;
|
||||
ORGANIZATIONNAME = ViolentOctopus;
|
||||
TargetAttributes = {
|
||||
CE7DD3661F9CFA81000225C5 = {
|
||||
@@ -265,6 +265,7 @@
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
@@ -272,6 +273,7 @@
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
@@ -324,6 +326,7 @@
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
@@ -331,6 +334,7 @@
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0900"
|
||||
LastUpgradeVersion = "0930"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
@@ -26,7 +26,6 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
@@ -56,7 +55,6 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
||||
@@ -13,6 +13,7 @@ class _FirebaseDecoder : Decoder {
|
||||
struct _Options {
|
||||
let dateDecodingStrategy: FirebaseDecoder.DateDecodingStrategy?
|
||||
let dataDecodingStrategy: FirebaseDecoder.DataDecodingStrategy?
|
||||
let skipFirestoreTypes: Bool
|
||||
let userInfo: [CodingUserInfoKey : Any]
|
||||
}
|
||||
|
||||
@@ -129,7 +130,7 @@ fileprivate struct _FirebaseKeyedDecodingContainer<K : CodingKey> : KeyedDecodin
|
||||
|
||||
// MARK: - KeyedDecodingContainerProtocol Methods
|
||||
public var allKeys: [Key] {
|
||||
return container.keys.flatMap { Key(stringValue: $0) }
|
||||
return container.keys.compactMap { Key(stringValue: $0) }
|
||||
}
|
||||
|
||||
public func contains(_ key: Key) -> Bool {
|
||||
@@ -1229,6 +1230,8 @@ extension _FirebaseDecoder {
|
||||
} else if T.self == Decimal.self || T.self == NSDecimalNumber.self {
|
||||
guard let decimal = try self.unbox(value, as: Decimal.self) else { return nil }
|
||||
decoded = decimal as! T
|
||||
} else if options.skipFirestoreTypes && (T.self is FirestoreDecodable.Type) {
|
||||
decoded = value as! T
|
||||
} else {
|
||||
self.storage.push(container: value)
|
||||
decoded = try T(from: self)
|
||||
|
||||
@@ -13,6 +13,7 @@ class _FirebaseEncoder : Encoder {
|
||||
struct _Options {
|
||||
let dateEncodingStrategy: FirebaseEncoder.DateEncodingStrategy?
|
||||
let dataEncodingStrategy: FirebaseEncoder.DataEncodingStrategy?
|
||||
let skipFirestoreTypes: Bool
|
||||
let userInfo: [CodingUserInfoKey : Any]
|
||||
}
|
||||
|
||||
@@ -382,14 +383,30 @@ extension _FirebaseEncoder {
|
||||
return try self.box((value as! Data))
|
||||
} else if T.self == URL.self || T.self == NSURL.self {
|
||||
return self.box((value as! URL).absoluteString)
|
||||
} else if T.self == Decimal.self || T.self == NSDecimalNumber.self {
|
||||
return (value as! NSDecimalNumber)
|
||||
} else if options.skipFirestoreTypes && (value is FirestoreEncodable) {
|
||||
guard let value = value as? NSObject else {
|
||||
throw DocumentReferenceError.typeIsNotNSObject
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
// The value should request a container from the _FirebaseEncoder.
|
||||
let depth = storage.count
|
||||
try value.encode(to: self)
|
||||
let depth = self.storage.count
|
||||
do {
|
||||
try value.encode(to: self)
|
||||
} catch {
|
||||
// If the value pushed a container before throwing, pop it back off to restore state.
|
||||
if self.storage.count > depth {
|
||||
let _ = self.storage.popContainer()
|
||||
}
|
||||
|
||||
throw error
|
||||
}
|
||||
|
||||
// The top container should be a new container.
|
||||
guard storage.count > depth else {
|
||||
guard self.storage.count > depth else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ open class FirebaseDecoder {
|
||||
let options = _FirebaseDecoder._Options(
|
||||
dateDecodingStrategy: dateDecodingStrategy,
|
||||
dataDecodingStrategy: dataDecodingStrategy,
|
||||
skipFirestoreTypes: false,
|
||||
userInfo: userInfo
|
||||
)
|
||||
let decoder = _FirebaseDecoder(referencing: container, options: options)
|
||||
|
||||
@@ -57,6 +57,7 @@ open class FirebaseEncoder {
|
||||
let options = _FirebaseEncoder._Options(
|
||||
dateEncodingStrategy: dateEncodingStrategy,
|
||||
dataEncodingStrategy: dataEncodingStrategy,
|
||||
skipFirestoreTypes: false,
|
||||
userInfo: userInfo
|
||||
)
|
||||
let encoder = _FirebaseEncoder(options: options)
|
||||
|
||||
@@ -8,13 +8,30 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol FirestoreDecodable: Decodable {}
|
||||
public protocol FirestoreEncodable: Encodable {}
|
||||
|
||||
public typealias DocumentReferenceType = FirestoreDecodable & FirestoreEncodable
|
||||
public typealias FieldValueType = FirestoreEncodable
|
||||
|
||||
public protocol GeoPointType: FirestoreDecodable, FirestoreEncodable {
|
||||
var latitude: Double { get }
|
||||
var longitude: Double { get }
|
||||
init(latitude: Double, longitude: Double)
|
||||
}
|
||||
|
||||
open class FirestoreDecoder {
|
||||
public init() {}
|
||||
|
||||
open var userInfo: [CodingUserInfoKey : Any] = [:]
|
||||
|
||||
open func decode<T : Decodable>(_ type: T.Type, from container: [String: Any]) throws -> T {
|
||||
let options = _FirebaseDecoder._Options(dateDecodingStrategy: nil, dataDecodingStrategy: nil, userInfo: userInfo)
|
||||
let options = _FirebaseDecoder._Options(
|
||||
dateDecodingStrategy: nil,
|
||||
dataDecodingStrategy: nil,
|
||||
skipFirestoreTypes: true,
|
||||
userInfo: userInfo
|
||||
)
|
||||
let decoder = _FirebaseDecoder(referencing: container, options: options)
|
||||
guard let value = try decoder.unbox(container, as: T.self) else {
|
||||
throw DecodingError.valueNotFound(T.self, DecodingError.Context(codingPath: [], debugDescription: "The given dictionary was invalid"))
|
||||
@@ -23,3 +40,39 @@ open class FirestoreDecoder {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
enum GeoPointKeys: CodingKey {
|
||||
case latitude, longitude
|
||||
}
|
||||
|
||||
extension GeoPointType {
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: GeoPointKeys.self)
|
||||
let latitude = try container.decode(Double.self, forKey: .latitude)
|
||||
let longitude = try container.decode(Double.self, forKey: .longitude)
|
||||
self.init(latitude: latitude, longitude: longitude)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: GeoPointKeys.self)
|
||||
try container.encode(latitude, forKey: .latitude)
|
||||
try container.encode(longitude, forKey: .longitude)
|
||||
}
|
||||
}
|
||||
|
||||
enum DocumentReferenceError: Error {
|
||||
case typeIsNotSupported
|
||||
case typeIsNotNSObject
|
||||
}
|
||||
|
||||
extension FirestoreDecodable {
|
||||
public init(from decoder: Decoder) throws {
|
||||
throw DocumentReferenceError.typeIsNotSupported
|
||||
}
|
||||
}
|
||||
|
||||
extension FirestoreEncodable {
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
throw DocumentReferenceError.typeIsNotSupported
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,12 @@ open class FirestoreEncoder {
|
||||
}
|
||||
|
||||
internal func encodeToTopLevelContainer<Value : Encodable>(_ value: Value) throws -> Any {
|
||||
let options = _FirebaseEncoder._Options(dateEncodingStrategy: nil, dataEncodingStrategy: nil, userInfo: userInfo)
|
||||
let options = _FirebaseEncoder._Options(
|
||||
dateEncodingStrategy: nil,
|
||||
dataEncodingStrategy: nil,
|
||||
skipFirestoreTypes: true,
|
||||
userInfo: userInfo
|
||||
)
|
||||
let encoder = _FirebaseEncoder(options: options)
|
||||
guard let topLevel = try encoder.box_(value) else {
|
||||
throw EncodingError.invalidValue(value,
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.0.3</string>
|
||||
<string>0.0.10</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<string>0.0.10</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
|
||||
@@ -369,6 +369,19 @@ class TestCodableFirebase: XCTestCase {
|
||||
_testRoundTrip(of: 3 as Double)
|
||||
}
|
||||
|
||||
// MARK: - GeoPoint
|
||||
func testEncodingGeoPoint() {
|
||||
let point = Point(latitude: 2, longitude: 2)
|
||||
XCTAssertEqual((try? FirebaseEncoder().encode(point)) as? NSDictionary, ["latitude": 2, "longitude": 2])
|
||||
XCTAssertEqual(try? FirebaseDecoder().decode(Point.self, from: ["latitude": 2, "longitude": 2]), point)
|
||||
}
|
||||
|
||||
// MARK: - Document Reference
|
||||
func testEncodingDocumentReference() {
|
||||
XCTAssertThrowsError(try FirebaseEncoder().encode(DocumentReference()))
|
||||
XCTAssertThrowsError(try FirebaseDecoder().decode(DocumentReference.self, from: []))
|
||||
}
|
||||
|
||||
// MARK: - Helper Functions
|
||||
private var _emptyDictionary: [String: Any] = [:]
|
||||
|
||||
@@ -415,6 +428,19 @@ class TestCodableFirebase: XCTestCase {
|
||||
// MARK: - Test Types
|
||||
/* FIXME: Import from %S/Inputs/Coding/SharedTypes.swift somehow. */
|
||||
|
||||
// MARK: - GeoPoint
|
||||
struct Point: GeoPointType, Equatable {
|
||||
let latitude: Double
|
||||
let longitude: Double
|
||||
|
||||
static func == (lhs: Point, rhs: Point) -> Bool {
|
||||
return lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - ReferenceType
|
||||
fileprivate struct DocumentReference: DocumentReferenceType {}
|
||||
|
||||
// MARK: - Empty Types
|
||||
fileprivate struct EmptyStruct : Codable, Equatable {
|
||||
static func ==(_ lhs: EmptyStruct, _ rhs: EmptyStruct) -> Bool {
|
||||
|
||||
@@ -109,6 +109,26 @@ class TestCodableFirestore: XCTestCase {
|
||||
_testRoundTrip(of: TopLevelWrapper(date), expected: ["value": date])
|
||||
}
|
||||
|
||||
func testDecimalValue() {
|
||||
let value = Decimal(2)
|
||||
_testRoundTrip(of: TopLevelWrapper(value), expected: ["value": value])
|
||||
}
|
||||
|
||||
// MARK: - GeoPoint & Document Reference
|
||||
func testEncodingGeoPoint() {
|
||||
let point = GeoPoint(latitude: 2, longitude: 2)
|
||||
let wrapper = TopLevelWrapper(point)
|
||||
XCTAssertEqual((try? FirestoreEncoder().encode(wrapper)) as NSDictionary?, ["value": point])
|
||||
XCTAssertEqual(try? FirestoreDecoder().decode(TopLevelWrapper<GeoPoint>.self, from: ["value": point]), wrapper)
|
||||
XCTAssertThrowsError(try FirestoreEncoder().encode(TopLevelWrapper(Point(latitude: 2, longitude: 2))))
|
||||
}
|
||||
|
||||
func testEncodingDocumentReference() {
|
||||
let val = TopLevelWrapper(DocumentReference())
|
||||
XCTAssertEqual((try? FirestoreEncoder().encode(val)) as NSDictionary?, ["value": val.value])
|
||||
XCTAssertEqual(try? FirestoreDecoder().decode(TopLevelWrapper<DocumentReference>.self, from: ["value": val.value]), val)
|
||||
}
|
||||
|
||||
private func _testEncodeFailure<T : Encodable>(of value: T) {
|
||||
do {
|
||||
let _ = try FirestoreEncoder().encode(value)
|
||||
@@ -164,3 +184,21 @@ func expectEqualPaths(_ lhs: [CodingKey], _ rhs: [CodingKey], _ prefix: String)
|
||||
XCTAssertEqual(key1.stringValue, key2.stringValue, "\(prefix) CodingKey.stringValue mismatch: \(type(of: key1))('\(key1.stringValue)') != \(type(of: key2))('\(key2.stringValue)')")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - GeioPoint
|
||||
fileprivate class GeoPoint: NSObject, GeoPointType {
|
||||
let latitude: Double
|
||||
let longitude: Double
|
||||
|
||||
required init(latitude: Double, longitude: Double) {
|
||||
self.latitude = latitude
|
||||
self.longitude = longitude
|
||||
}
|
||||
|
||||
static func == (lhs: Point, rhs: Point) -> Bool {
|
||||
return lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - ReferenceType
|
||||
fileprivate class DocumentReference: NSObject, DocumentReferenceType {}
|
||||
|
||||
4
Gemfile
Normal file
4
Gemfile
Normal file
@@ -0,0 +1,4 @@
|
||||
source 'https://rubygems.org'
|
||||
|
||||
gem 'fastlane'
|
||||
gem 'cocoapods', '1.5.0'
|
||||
205
Gemfile.lock
Normal file
205
Gemfile.lock
Normal file
@@ -0,0 +1,205 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (3.0.0)
|
||||
activesupport (4.2.10)
|
||||
i18n (~> 0.7)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.3, >= 0.3.4)
|
||||
tzinfo (~> 1.1)
|
||||
addressable (2.5.2)
|
||||
public_suffix (>= 2.0.2, < 4.0)
|
||||
atomos (0.1.2)
|
||||
babosa (1.0.2)
|
||||
claide (1.0.2)
|
||||
cocoapods (1.5.0)
|
||||
activesupport (>= 4.0.2, < 5)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
cocoapods-core (= 1.5.0)
|
||||
cocoapods-deintegrate (>= 1.0.2, < 2.0)
|
||||
cocoapods-downloader (>= 1.2.0, < 2.0)
|
||||
cocoapods-plugins (>= 1.0.0, < 2.0)
|
||||
cocoapods-search (>= 1.0.0, < 2.0)
|
||||
cocoapods-stats (>= 1.0.0, < 2.0)
|
||||
cocoapods-trunk (>= 1.3.0, < 2.0)
|
||||
cocoapods-try (>= 1.1.0, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
escape (~> 0.0.4)
|
||||
fourflusher (~> 2.0.1)
|
||||
gh_inspector (~> 1.0)
|
||||
molinillo (~> 0.6.5)
|
||||
nap (~> 1.0)
|
||||
ruby-macho (~> 1.1)
|
||||
xcodeproj (>= 1.5.7, < 2.0)
|
||||
cocoapods-core (1.5.0)
|
||||
activesupport (>= 4.0.2, < 6)
|
||||
fuzzy_match (~> 2.0.4)
|
||||
nap (~> 1.0)
|
||||
cocoapods-deintegrate (1.0.2)
|
||||
cocoapods-downloader (1.2.0)
|
||||
cocoapods-plugins (1.0.0)
|
||||
nap
|
||||
cocoapods-search (1.0.0)
|
||||
cocoapods-stats (1.0.0)
|
||||
cocoapods-trunk (1.3.0)
|
||||
nap (>= 0.8, < 2.0)
|
||||
netrc (~> 0.11)
|
||||
cocoapods-try (1.1.0)
|
||||
colored (1.2)
|
||||
colored2 (3.1.2)
|
||||
commander-fastlane (4.4.6)
|
||||
highline (~> 1.7.2)
|
||||
concurrent-ruby (1.0.5)
|
||||
declarative (0.0.10)
|
||||
declarative-option (0.1.0)
|
||||
domain_name (0.5.20180417)
|
||||
unf (>= 0.0.5, < 1.0.0)
|
||||
dotenv (2.4.0)
|
||||
emoji_regex (0.1.1)
|
||||
escape (0.0.4)
|
||||
excon (0.62.0)
|
||||
faraday (0.15.0)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
faraday-cookie_jar (0.0.6)
|
||||
faraday (>= 0.7.4)
|
||||
http-cookie (~> 1.0.0)
|
||||
faraday_middleware (0.12.2)
|
||||
faraday (>= 0.7.4, < 1.0)
|
||||
fastimage (2.1.1)
|
||||
fastlane (2.93.1)
|
||||
CFPropertyList (>= 2.3, < 4.0.0)
|
||||
addressable (>= 2.3, < 3.0.0)
|
||||
babosa (>= 1.0.2, < 2.0.0)
|
||||
bundler (>= 1.12.0, < 2.0.0)
|
||||
colored
|
||||
commander-fastlane (>= 4.4.6, < 5.0.0)
|
||||
dotenv (>= 2.1.1, < 3.0.0)
|
||||
emoji_regex (~> 0.1)
|
||||
excon (>= 0.45.0, < 1.0.0)
|
||||
faraday (~> 0.9)
|
||||
faraday-cookie_jar (~> 0.0.6)
|
||||
faraday_middleware (~> 0.9)
|
||||
fastimage (>= 2.1.0, < 3.0.0)
|
||||
gh_inspector (>= 1.1.2, < 2.0.0)
|
||||
google-api-client (>= 0.13.1, < 0.14.0)
|
||||
highline (>= 1.7.2, < 2.0.0)
|
||||
json (< 3.0.0)
|
||||
mini_magick (~> 4.5.1)
|
||||
multi_json
|
||||
multi_xml (~> 0.5)
|
||||
multipart-post (~> 2.0.0)
|
||||
plist (>= 3.1.0, < 4.0.0)
|
||||
public_suffix (~> 2.0.0)
|
||||
rubyzip (>= 1.1.0, < 2.0.0)
|
||||
security (= 0.1.3)
|
||||
simctl (~> 1.6.3)
|
||||
slack-notifier (>= 2.0.0, < 3.0.0)
|
||||
terminal-notifier (>= 1.6.2, < 2.0.0)
|
||||
terminal-table (>= 1.4.5, < 2.0.0)
|
||||
tty-screen (>= 0.6.3, < 1.0.0)
|
||||
tty-spinner (>= 0.8.0, < 1.0.0)
|
||||
word_wrap (~> 1.0.0)
|
||||
xcodeproj (>= 1.5.7, < 2.0.0)
|
||||
xcpretty (>= 0.2.4, < 1.0.0)
|
||||
xcpretty-travis-formatter (>= 0.0.3)
|
||||
fourflusher (2.0.1)
|
||||
fuzzy_match (2.0.4)
|
||||
gh_inspector (1.1.3)
|
||||
google-api-client (0.13.6)
|
||||
addressable (~> 2.5, >= 2.5.1)
|
||||
googleauth (~> 0.5)
|
||||
httpclient (>= 2.8.1, < 3.0)
|
||||
mime-types (~> 3.0)
|
||||
representable (~> 3.0)
|
||||
retriable (>= 2.0, < 4.0)
|
||||
googleauth (0.6.2)
|
||||
faraday (~> 0.12)
|
||||
jwt (>= 1.4, < 3.0)
|
||||
logging (~> 2.0)
|
||||
memoist (~> 0.12)
|
||||
multi_json (~> 1.11)
|
||||
os (~> 0.9)
|
||||
signet (~> 0.7)
|
||||
highline (1.7.10)
|
||||
http-cookie (1.0.3)
|
||||
domain_name (~> 0.5)
|
||||
httpclient (2.8.3)
|
||||
i18n (0.9.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
json (2.1.0)
|
||||
jwt (2.1.0)
|
||||
little-plugger (1.1.4)
|
||||
logging (2.2.2)
|
||||
little-plugger (~> 1.1)
|
||||
multi_json (~> 1.10)
|
||||
memoist (0.16.0)
|
||||
mime-types (3.1)
|
||||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2016.0521)
|
||||
mini_magick (4.5.1)
|
||||
minitest (5.11.3)
|
||||
molinillo (0.6.5)
|
||||
multi_json (1.13.1)
|
||||
multi_xml (0.6.0)
|
||||
multipart-post (2.0.0)
|
||||
nanaimo (0.2.5)
|
||||
nap (1.1.0)
|
||||
naturally (2.1.0)
|
||||
netrc (0.11.0)
|
||||
os (0.9.6)
|
||||
plist (3.4.0)
|
||||
public_suffix (2.0.5)
|
||||
representable (3.0.4)
|
||||
declarative (< 0.1.0)
|
||||
declarative-option (< 0.2.0)
|
||||
uber (< 0.2.0)
|
||||
retriable (3.1.1)
|
||||
rouge (2.0.7)
|
||||
ruby-macho (1.1.0)
|
||||
rubyzip (1.2.1)
|
||||
security (0.1.3)
|
||||
signet (0.8.1)
|
||||
addressable (~> 2.3)
|
||||
faraday (~> 0.9)
|
||||
jwt (>= 1.5, < 3.0)
|
||||
multi_json (~> 1.10)
|
||||
simctl (1.6.4)
|
||||
CFPropertyList
|
||||
naturally
|
||||
slack-notifier (2.3.2)
|
||||
terminal-notifier (1.8.0)
|
||||
terminal-table (1.8.0)
|
||||
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||
thread_safe (0.3.6)
|
||||
tty-cursor (0.5.0)
|
||||
tty-screen (0.6.4)
|
||||
tty-spinner (0.8.0)
|
||||
tty-cursor (>= 0.5.0)
|
||||
tzinfo (1.2.5)
|
||||
thread_safe (~> 0.1)
|
||||
uber (0.1.0)
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.7.5)
|
||||
unicode-display_width (1.3.2)
|
||||
word_wrap (1.0.0)
|
||||
xcodeproj (1.5.7)
|
||||
CFPropertyList (>= 2.3.3, < 4.0)
|
||||
atomos (~> 0.1.2)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
nanaimo (~> 0.2.4)
|
||||
xcpretty (0.2.8)
|
||||
rouge (~> 2.0.7)
|
||||
xcpretty-travis-formatter (1.0.0)
|
||||
xcpretty (~> 0.2, >= 0.0.7)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
cocoapods (= 1.5.0)
|
||||
fastlane
|
||||
|
||||
BUNDLED WITH
|
||||
1.16.1
|
||||
48
README.md
48
README.md
@@ -1,16 +1,20 @@
|
||||
# CodableFirebase
|
||||
Use [Codable](https://developer.apple.com/documentation/swift/codable) with [Firebase](https://firebase.google.com)
|
||||
|
||||
[](https://github.com/alickbass/CodableFirebase)
|
||||
[](https://github.com/Carthage/Carthage)
|
||||
[](https://travis-ci.org/alickbass/CodableFirebase)
|
||||
[](https://codecov.io/gh/alickbass/CodableFirebase)
|
||||
|
||||
## Overview
|
||||
|
||||
This library helps you to use your custom type that conform to `Codable` protocol with Firebase. Here's an example of model:
|
||||
This library helps you to use your custom types that conform to `Codable` protocol with Firebase. Here's an example of a custom model:
|
||||
|
||||
```swift
|
||||
struct Model: Codable {
|
||||
enum MyEnum: Int, Codable {
|
||||
case one, two, three
|
||||
}
|
||||
|
||||
let stringExample: String
|
||||
let booleanExample: Bool
|
||||
let numberExample: Double
|
||||
@@ -18,6 +22,7 @@ struct Model: Codable {
|
||||
let arrayExample: [String]
|
||||
let nullExample: Int?
|
||||
let objectExample: [String: String]
|
||||
let myEnum: MyEnum
|
||||
}
|
||||
```
|
||||
|
||||
@@ -80,3 +85,42 @@ Firestore.firestore().collection("data").document("one").getDocument { (document
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### How to use `GeoPoint`, `DocumentRefence`, `FieldValue` in Firestore
|
||||
|
||||
In order to use these 2 types with `Firestore`, you need to add the following code somewhere in your app:
|
||||
|
||||
```swift
|
||||
extension DocumentReference: DocumentReferenceType {}
|
||||
extension GeoPoint: GeoPointType {}
|
||||
extension FieldValue: FieldValueType {}
|
||||
```
|
||||
|
||||
and now they become `Codable` and can be used properly with `FirestoreEncoder` and `FirestoreDecoder`.
|
||||
|
||||
***PLEASE NOTE*** that as `FieldValue` is only used to [`setData()` and `updateData()`](https://firebase.google.com/docs/reference/swift/firebasefirestore/api/reference/Classes/FieldValue), it only adopts the `Encodable` protocol.
|
||||
|
||||
## Integration
|
||||
|
||||
### CocoaPods (iOS 9+)
|
||||
|
||||
You can use CocoaPods to install CodableFirebase by adding it to your Podfile:
|
||||
|
||||
```swift
|
||||
platform :ios, '9.0'
|
||||
use_frameworks!
|
||||
|
||||
target 'MyApp' do
|
||||
pod 'CodableFirebase'
|
||||
end
|
||||
```
|
||||
|
||||
Note that this requires CocoaPods version 36, and your iOS deployment target to be at least 9.0:
|
||||
|
||||
### Carthage (iOS 9+)
|
||||
|
||||
You can use Carthage to install CodableFirebase by adding it to your Cartfile:
|
||||
|
||||
```swift
|
||||
github "alickbass/CodableFirebase"
|
||||
```
|
||||
|
||||
34
fastlane/Fastfile
Normal file
34
fastlane/Fastfile
Normal file
@@ -0,0 +1,34 @@
|
||||
default_platform(:ios)
|
||||
|
||||
platform :ios do
|
||||
|
||||
desc "Release a new version with a patch bump_type"
|
||||
lane :patch do
|
||||
release("patch")
|
||||
end
|
||||
|
||||
desc "Release a new version with a minor bump_type"
|
||||
lane :minor do
|
||||
release("minor")
|
||||
end
|
||||
|
||||
desc "Release a new version with a major bump_type"
|
||||
lane :major do
|
||||
release("major")
|
||||
end
|
||||
|
||||
def release(type)
|
||||
pod_lib_lint
|
||||
podspec_name = "CodableFirebase.podspec"
|
||||
version = version_bump_podspec(path: podspec_name,
|
||||
bump_type: type)
|
||||
increment_version_number(version_number: version)
|
||||
#cocoapods
|
||||
git_add
|
||||
git_commit(path: ".",
|
||||
message: "#{version} release")
|
||||
add_git_tag(tag: "#{version}")
|
||||
push_to_git_remote
|
||||
pod_push
|
||||
end
|
||||
end
|
||||
39
fastlane/README.md
Normal file
39
fastlane/README.md
Normal file
@@ -0,0 +1,39 @@
|
||||
fastlane documentation
|
||||
================
|
||||
# Installation
|
||||
|
||||
Make sure you have the latest version of the Xcode command line tools installed:
|
||||
|
||||
```
|
||||
xcode-select --install
|
||||
```
|
||||
|
||||
Install _fastlane_ using
|
||||
```
|
||||
[sudo] gem install fastlane -NV
|
||||
```
|
||||
or alternatively using `brew cask install fastlane`
|
||||
|
||||
# Available Actions
|
||||
## iOS
|
||||
### ios patch
|
||||
```
|
||||
fastlane ios patch
|
||||
```
|
||||
Release a new version with a patch bump_type
|
||||
### ios minor
|
||||
```
|
||||
fastlane ios minor
|
||||
```
|
||||
Release a new version with a minor bump_type
|
||||
### ios major
|
||||
```
|
||||
fastlane ios major
|
||||
```
|
||||
Release a new version with a major bump_type
|
||||
|
||||
----
|
||||
|
||||
This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run.
|
||||
More information about fastlane can be found on [fastlane.tools](https://fastlane.tools).
|
||||
The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools).
|
||||
Reference in New Issue
Block a user