@@ -133,6 +133,16 @@ public typealias CompletionHandler = (_ content: JSONObject?, _ error: Error?) -
133133 // NOTE: Not constant only for the sake of mocking during unit tests.
134134 var session : URLSession
135135
136+ /// Cache of already created indices.
137+ ///
138+ /// This dictionary is used to avoid creating two instances to represent the same index, as it is (1) inefficient
139+ /// and (2) potentially harmful since instances are stateful (that's especially true of mirrored/offline indices,
140+ /// but also of online indices because of the search cache).
141+ ///
142+ /// + Note: The values are zeroing weak references to avoid leaking memory when an index is no longer used.
143+ ///
144+ var indices : NSMapTable < NSString , AnyObject > = NSMapTable ( keyOptions: [ . strongMemory] , valueOptions: [ . weakMemory] )
145+
136146 /// Operation queue used to keep track of requests.
137147 /// `Request` instances are inherently asynchronous, since they are merely wrappers around `NSURLSessionTask`.
138148 /// The sole purpose of the queue is to retain them for the duration of their execution!
@@ -239,6 +249,26 @@ public typealias CompletionHandler = (_ content: JSONObject?, _ error: Error?) -
239249 return headers [ name]
240250 }
241251
252+ /// Obtain a proxy to an Algolia index (no server call required by this method).
253+ ///
254+ /// + Note: Only one instance can exist for a given index name. Subsequent calls to this method with the same
255+ /// index name will return the same instance, unless it has already been released.
256+ ///
257+ /// - parameter indexName: The name of the index.
258+ /// - returns: A proxy to the specified index.
259+ ///
260+ @objc ( indexWithName: )
261+ public func index( withName indexName: String ) -> Index {
262+ if let index = indices. object ( forKey: indexName as NSString ) {
263+ assert ( index is Index , " An index with the same name but a different type has already been created " ) // may happen in offline mode
264+ return index as! Index
265+ } else {
266+ let index = Index ( client: self , name: indexName)
267+ indices. setObject ( index, forKey: indexName as NSString )
268+ return index
269+ }
270+ }
271+
242272 // MARK: - Operations
243273
244274 /// List existing indexes.
@@ -305,19 +335,6 @@ public typealias CompletionHandler = (_ content: JSONObject?, _ error: Error?) -
305335 return performHTTPQuery ( path: path, method: . POST, body: request as [ String : Any ] ? , hostnames: writeHosts, completionHandler: completionHandler)
306336 }
307337
308- /// Create a proxy to an Algolia index (no server call required by this method).
309- ///
310- /// - parameter indexName: The name of the index.
311- /// - returns: A new proxy to the specified index.
312- ///
313- @objc ( indexWithName: )
314- public func index( withName indexName: String ) -> Index {
315- // IMPLEMENTATION NOTE: This method is called `initIndex` in other clients, which better conveys its semantics.
316- // However, methods prefixed by `init` are automatically considered as initializers by the Objective-C bridge.
317- // Therefore, `initIndex` would fail to compile in Objective-C, because its return type is not `instancetype`.
318- return Index ( client: self , name: indexName)
319- }
320-
321338 /// Strategy when running multiple queries. See `Client.multipleQueries(...)`.
322339 ///
323340 public enum MultipleQueriesStrategy : String {
0 commit comments