@@ -10,7 +10,7 @@ import Foundation
1010
1111/// LeanCloud Object Type.
1212@dynamicMemberLookup
13- open class LCObject : NSObject , LCValue , LCValueExtension , Sequence {
13+ open class LCObject : NSObject , Sequence , LCValue , LCValueExtension , InternalOptionalSynchronizing {
1414
1515 // MARK: Property
1616
@@ -40,7 +40,7 @@ open class LCObject: NSObject, LCValue, LCValueExtension, Sequence {
4040 private var propertyTable : LCDictionary = [ : ]
4141
4242 /// The table of all properties.
43- lazy var dictionary : LCDictionary = {
43+ private lazy var _dictionary : LCDictionary = {
4444 /**
4545 Synchronize property table.
4646
@@ -63,6 +63,9 @@ open class LCObject: NSObject, LCValue, LCValueExtension, Sequence {
6363 }
6464 return self . propertyTable
6565 } ( )
66+ var dictionary : LCDictionary {
67+ return self . optionalSync ( LCDictionary ( self . _dictionary) )
68+ }
6669
6770 public var hasObjectId : Bool {
6871 return self . objectId != nil
@@ -91,16 +94,31 @@ open class LCObject: NSObject, LCValue, LCValueExtension, Sequence {
9194 /// Whether this object has unsync-data to upload to server.
9295 public var hasDataToUpload : Bool {
9396 if self . hasObjectId {
94- if let operationHub = self . operationHub {
95- return !operationHub. isEmpty
96- } else {
97- return false
98- }
97+ return self . optionalSync ( closure: {
98+ if let operationHub = self . operationHub {
99+ return !operationHub. isEmpty
100+ } else {
101+ return false
102+ }
103+ } )
99104 } else {
100105 return true
101106 }
102107 }
103108
109+ // MARK: Internal Optional Synchronizing
110+
111+ private var _optionalMutex : NSLock ?
112+ var optionalMutex : NSLock ? {
113+ return self . _optionalMutex
114+ }
115+
116+ private func tryInitOptionalMutex( ) {
117+ if self . application. configuration. isObjectRawDataAtomic {
118+ self . _optionalMutex = NSLock ( )
119+ }
120+ }
121+
104122 // MARK: Subclassing
105123
106124 /**
@@ -135,6 +153,7 @@ open class LCObject: NSObject, LCValue, LCValueExtension, Sequence {
135153 public override required init ( ) {
136154 self . application = . default
137155 super. init ( )
156+ self . tryInitOptionalMutex ( )
138157 self . operationHub = OperationHub ( self )
139158 self . propertyTable. elementDidChange = { [ weak self] ( key, value) in
140159 Runtime . setInstanceVariable ( self , key, value)
@@ -146,6 +165,7 @@ open class LCObject: NSObject, LCValue, LCValueExtension, Sequence {
146165 public required init ( application: LCApplication ) {
147166 self . application = application
148167 super. init ( )
168+ self . tryInitOptionalMutex ( )
149169 self . operationHub = OperationHub ( self )
150170 self . propertyTable. elementDidChange = { [ weak self] ( key, value) in
151171 Runtime . setInstanceVariable ( self , key, value)
@@ -319,7 +339,7 @@ open class LCObject: NSObject, LCValue, LCValueExtension, Sequence {
319339 // MARK: Key Value Change
320340
321341 func getProperty< Value: LCValue > ( _ key: String ) throws -> Value ? {
322- let value = self . propertyTable [ key]
342+ let value : LCValueConvertible ? = self . optionalSync ( self . propertyTable [ key] )
323343 if let value = value {
324344 guard value is Value else {
325345 throw LCError (
@@ -347,7 +367,9 @@ open class LCObject: NSObject, LCValue, LCValueExtension, Sequence {
347367 " key " : key,
348368 " target_type " : " \( Value . self) " ] )
349369 }
350- self . propertyTable [ key] = value
370+ self . optionalSync ( closure: {
371+ self . propertyTable [ key] = value
372+ } )
351373 return value
352374 }
353375
@@ -359,7 +381,9 @@ open class LCObject: NSObject, LCValue, LCValueExtension, Sequence {
359381 switch operation. name {
360382 case . set, . delete:
361383 self . willChangeValue ( forKey: key)
362- self . propertyTable [ key] = value
384+ self . optionalSync ( closure: {
385+ self . propertyTable [ key] = value
386+ } )
363387 self . didChangeValue ( forKey: key)
364388 case . increment:
365389 guard let number = value as? LCNumber else {
@@ -476,7 +500,9 @@ open class LCObject: NSObject, LCValue, LCValueExtension, Sequence {
476500 }
477501 try self . updateByKeyPath ( operation)
478502 }
479- try self . operationHub? . reduce ( operation)
503+ try self . optionalSync ( closure: {
504+ try self . operationHub? . reduce ( operation)
505+ } )
480506 }
481507
482508 func transformValue( _ key: String , _ value: LCValue ? ) -> LCValue ? {
@@ -494,13 +520,18 @@ open class LCObject: NSObject, LCValue, LCValueExtension, Sequence {
494520 }
495521
496522 func update( _ key: String , _ value: LCValue ? ) {
523+ let value = self . transformValue ( key, value)
497524 self . willChangeValue ( forKey: key)
498- self . propertyTable [ key] = self . transformValue ( key, value)
525+ self . optionalSync ( closure: {
526+ self . propertyTable [ key] = value
527+ } )
499528 self . didChangeValue ( forKey: key)
500529 }
501530
502531 func discardChanges( ) {
503- self . operationHub? . reset ( )
532+ self . optionalSync ( closure: {
533+ self . operationHub? . reset ( )
534+ } )
504535 }
505536
506537 // MARK: Operation
@@ -536,7 +567,7 @@ open class LCObject: NSObject, LCValue, LCValueExtension, Sequence {
536567 */
537568 open func get( _ key: String ) -> LCValueConvertible ? {
538569 return ObjectProfiler . shared. propertyValue ( self , key)
539- ?? self . propertyTable [ key]
570+ ?? self . optionalSync ( self . propertyTable [ key] )
540571 }
541572
542573 /**
0 commit comments