@@ -12,10 +12,15 @@ protocol Containerable: class {
1212 typealias Object = AnyObject
1313 typealias ServiceName = String
1414 typealias Service = ( ( ) -> Object )
15+ typealias RelationIn = String
16+ typealias RelationOut = String
17+
1518 var container : Containerable ? { get set }
1619 var dispatchRegistrationGroup : DispatchGroup { get }
1720
1821 var services : [ ServiceName : [ ContainerObject ] ] { get set }
22+ var relations : [ RelationIn : [ RelationOut ] ] { get set }
23+ var recursiveNotResolvedObjects : [ Object ] { get set }
1924}
2025
2126struct ContainerObject {
@@ -30,7 +35,6 @@ struct ContainerObject {
3035
3136extension Containerable {
3237 private func resolveAny( typeString: String , name: String ? = nil ) -> Object ? {
33- // TODO: replace .first with more smart condition
3438 let array : [ ContainerObject ] ? = {
3539 if let filterName = name {
3640 return services [ typeString] ? . filter { $0. name == filterName }
@@ -40,19 +44,22 @@ extension Containerable {
4044 } ( )
4145
4246 if ( array? . count ?? 0 ) > 1 {
43- SILogger ( " Warning in \( typeString) resolving. You registered two different object for this type. Try to provide \" name \" argument while registering your object. But you will receive first object of all services you registered. " ) . log ( )
47+ SILogger ( " Warning in \( typeString) resolving. You registered two different objects for this type. Try to provide \" name \" argument while registering your object. But you will receive first object of all services you registered. " ) . log ( priority : . high )
4448 }
4549
4650 if let object = array? . first? . object {
47- autoresolve ( on: object)
4851 return object
4952 } else if let object = array? . first? . registration ( ) {
53+
5054 var objects = services [ typeString]
5155 if objects? . count ?? 0 > 0 {
5256 objects ? [ 0 ] . object = object
5357 }
58+
5459 services [ typeString] = objects ?? [ ]
5560 autoresolve ( on: object)
61+ finishRegistrations ( )
62+
5663 return object
5764 } else {
5865 return nil
@@ -66,14 +73,33 @@ extension Containerable {
6673 return object
6774 }
6875
76+ func finishRegistrations( ) {
77+ relations = [ : ]
78+ for object in recursiveNotResolvedObjects {
79+ autoresolve ( on: object)
80+ }
81+ recursiveNotResolvedObjects. removeAll ( )
82+ }
83+
6984 private func autoresolve< T: Object > ( on object: T ) {
7085 let mirror = Mirror ( reflecting: object)
86+
7187 for attr in mirror. children {
7288 if let property_name = attr. label {
7389 let objectType = type ( of: attr. value)
7490 let typeString = String ( describing: objectType) . replacingOccurrences ( of: " Optional< " , with: " " ) . replacingOccurrences ( of: " > " , with: " " )
91+
92+ // MARK: MUTATE VARIABLE (DANGER OBJC RUNTIME ZONE)
7593 if let ivar = class_getInstanceVariable ( type ( of: object) , property_name) {
76- print ( type ( of: object) , mirror. children. map { $0. label } )
94+ let typeStringOfMyObject = formattedString ( of: object)
95+ recordRelations ( relationIn: typeString, relationOut: typeStringOfMyObject)
96+ if relations [ typeStringOfMyObject] ? . contains ( typeString) ?? false {
97+ relations [ typeString] ? . removeAll ( where: { ( string) -> Bool in
98+ return string == typeStringOfMyObject
99+ } )
100+ recursiveNotResolvedObjects. append ( object)
101+ return
102+ }
77103 if let value = resolveAny ( typeString: typeString) {
78104 object_setIvar ( object, ivar, value)
79105 }
@@ -82,6 +108,61 @@ extension Containerable {
82108 }
83109 }
84110
111+ private func memmoryAddress( _ object: Object ) -> String {
112+ return " \( Unmanaged . passUnretained ( object) . toOpaque ( ) ) "
113+ }
114+
115+ private func recordRelations( relationIn: RelationIn , relationOut: RelationOut ) {
116+ if let relationsOut = relations [ relationIn] , !relationsOut. contains ( relationOut) {
117+ var newRelationsOut = relationsOut
118+ newRelationsOut. append ( relationOut)
119+ relations [ relationIn] = newRelationsOut
120+ } else {
121+ relations [ relationIn] = [ relationOut]
122+ }
123+ }
124+
125+ private func formattedString< T: Object > ( of object: T ) -> String {
126+ return String ( describing: type ( of: object) ) . replacingOccurrences ( of: " Optional< " , with: " " ) . replacingOccurrences ( of: " > " , with: " " )
127+ }
128+
129+ private func doesObjectHas( object: Object , propertyType: String ) -> Bool {
130+ let mirror = Mirror ( reflecting: object)
131+ for attr in mirror. children {
132+ let objectType = type ( of: attr. value)
133+ let typeString = String ( describing: objectType) . replacingOccurrences ( of: " Optional< " , with: " " ) . replacingOccurrences ( of: " > " , with: " " )
134+ if typeString == typeString {
135+ return true
136+ }
137+ }
138+
139+ return false
140+ }
141+
142+ private func property< T> ( object: Object , propertyName: String ) -> T ? {
143+ let mirror = Mirror ( reflecting: object)
144+ for attr in mirror. children {
145+ if attr. label == propertyName {
146+ return attr. value as? T
147+ }
148+ }
149+
150+ return nil
151+ }
152+
153+ private func propertyName( by typeString: String , in object: Object ) -> String ? {
154+ let mirror = Mirror ( reflecting: object)
155+ for attr in mirror. children {
156+ let propertyType = type ( of: attr. value)
157+ let typeStringInside = String ( describing: propertyType) . replacingOccurrences ( of: " Optional< " , with: " " ) . replacingOccurrences ( of: " > " , with: " " )
158+ if typeStringInside == typeString {
159+ return attr. label
160+ }
161+ }
162+
163+ return nil
164+ }
165+
85166 func register< T: Object > ( _ registration: @escaping ( ( ) -> T ) , name: String ? = nil ) {
86167
87168 dispatchRegistrationGroup. enter ( )
0 commit comments