Code Monkey home page Code Monkey logo

instantsearch-ios's Introduction

InstantSearch iOS

Pod Version Pod Platform Carthage compatible SwiftPM compatible Mac Catalyst compatible Licence

By Algolia.

InstantSearch family: InstantSearch iOS | InstantSearch Android | React InstantSearch | InstantSearch.js | Angular InstantSearch | Vue InstantSearch.

InstantSearch iOS is a framework providing components and helpers to help you build the best instant-search experience on iOS with Algolia. It is built on top of Algolia's Swift API Client library to provide you a high-level solution to quickly build various search interfaces.

Structure

InstantSearch iOS consists of three products

  • InstantSearch Insights – library that allows developers to capture search-related events
  • InstantSearch Core – the business logic modules of InstantSearch
  • InstantSearch – the complete InstantSearch toolset including UIKit components
  • InstantSearch SwiftUI – the set of SwiftUI data models and views to use on top of Core components

Examples

You can see InstantSearch iOS in action in the Examples project. It contains search components ans experiences built with InstantSearch and written in Swift.

Installation

Swift Package Manager

The Swift Package Manager is a tool for managing the distribution of Swift code. It’s integrated with the Swift build system to automate the process of downloading, compiling, and linking dependencies. Since the release of Swift 5 and Xcode 11, SPM is compatible with the iOS, macOS and tvOS build systems for creating apps.

To use SwiftPM, you should use Xcode 11 to open your project. Click File -> Swift Packages -> Add Package Dependency, enter InstantSearch repo's URL. Next, select the products you consider to use in your project from the provided list.

If you're a framework author and use InstantSearch as a dependency, update your Package.swift file:

let package = Package(
    // 7.26.0 ..< 8.0.0
    dependencies: [
        .package(url: "https://github.com/algolia/instantsearch-ios", from: "7.26.0")
    ],
    // ...
)

CocoaPods

CocoaPods is a dependency manager for Cocoa projects.

To install InstantSearch, simply add the following line to your Podfile:

pod 'InstantSearch', '~> 7.26'
# pod 'InstantSearch/Insights' for access to Insights library only
# pod 'InstantSearch/Core' for access business logic without UIKit components
# pod 'InstantSearch/SwiftUI' for access to SwiftUI components

Then, run the following command:

$ pod update

Carthage

Carthage is a simple, decentralized dependency manager for Cocoa.

  • To install InstantSearch, simply add the following line to your Cartfile:
github "algolia/instantsearch-ios" ~> 7.26
  • Launch the following commands from the project directory
carthage update
./Carthage/Checkouts/instant-search-ios/carthage-prebuild
carthage build

NOTE: At this time, Carthage does not provide a way to build only specific repository subcomponents (or equivalent of CocoaPods's subspecs). All components and their dependencies will be built with the above command. However, you don't need to copy frameworks you aren't using into your project. For instance, if you aren't using UI components from InstantSearch, feel free to delete that framework from the Carthage Build directory after carthage update completes keeping only InstantSearchCore. If you only need event-tracking functionalities, delete all but InstantSearchInsights framework.

If this is your first time using Carthage in the project, you'll need to go through some additional steps as explained over at Carthage.

Documentation

You can start with the Getting Started Guide.

Learn more about instantSearch iOS in the dedicated documentation website.

Basic Usage

In your ViewController.swift:

import InstantSearch

struct Item: Codable {
  let name: String
}

class SearchResultsViewController: UITableViewController, HitsController {
  
  var hitsSource: HitsInteractor<Item>?
    
  override func viewDidLoad() {
    super.viewDidLoad()
    tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
  }
      
  override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    hitsSource?.numberOfHits() ?? 0
  }
  
  override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
    cell.textLabel?.text = hitsSource?.hit(atIndex: indexPath.row)?.name
    return cell
  }
  
  override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if let _ = hitsSource?.hit(atIndex: indexPath.row) {
      // Handle hit selection
    }
  }
  
}

class ViewController: UIViewController {
      
  lazy var searchController = UISearchController(searchResultsController: hitsViewController)
  let hitsViewController = SearchResultsViewController()

  let searcher = HitsSearcher(appID: "latency",
                              apiKey: "1f6fd3a6fb973cb08419fe7d288fa4db",
                              indexName: "bestbuy")
  lazy var searchConnector = SearchConnector<Item>(searcher: searcher,
                                                    searchController: searchController,
                                                    hitsInteractor: .init(),
                                                    hitsController: hitsViewController)
  
  override func viewDidLoad() {
    super.viewDidLoad()
    searchConnector.connect()
    searcher.search()
    setupUI()
  }
  
  override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    searchController.isActive = true
  }
  
  func setupUI() {
    view.backgroundColor = .white
    navigationItem.searchController = searchController
    searchController.hidesNavigationBarDuringPresentation = false
    searchController.showsSearchResultsController = true
    searchController.automaticallyShowsCancelButton = false
  }
      
}

You can now build and run your application to see the basic search experience in action. You should see that the results are changing on each key stroke.

To get a more meaningful search experience, please follow the Getting Started Guide. If you build a SwiftUI application, please check out the Getting Started with SwiftUI guide

If you only require business logic modules in your project and use InstantSearchCore framework, add import InstantSearchCore to your source files.

Logs

There are 7 levels of logs severity produced by the library. The default severity level is .info. You can configure the logging level as follows:

Logs.logSeverityLevel = .debug

Telemetry

InstantSearch iOS collects data points at runtime. This helps the InstantSearch team improve and prioritize future development.

Here's an exhaustive list of the collected data:

  • InstantSearch version
  • The name of the instantiated InstantSearch components, for example, HitsSearcher, FilterState
  • The name of the components with custom parameters (overridden defaults). InstantSearch doesn't collect the values of those parameters. For example, the default of the facets value in FacetListInteractor is an empty list. If you instantiate it with a list of facets, then the telemetry tracks that the facets parameter received a custom value, but not the value itself.

InstantSearch doesn't collect any sensitive or personal data. However, you can still opt out of the telemetry collection with the following code:

InstantSearchTelemetry.shared.isEnabled = false

Getting Help

  • Need help? Ask a question to the Algolia Community or on Stack Overflow.
  • Encountering an issue? Before reaching out to support, we recommend heading to our FAQ where you will find answers for the most common issues and gotchas with the framework.
  • Found a bug? You can open a GitHub issue.
  • Questions about Algolia? You can search our FAQ in our website.

Getting involved

  • If you want to contribute please feel free to submit pull requests.
  • If you have a feature request please open an issue.
  • If you use InstantSearch in your app, we would love to hear about it! Drop us a line on discourse or twitter.

License

InstantSearch iOS is Apache 2.0 licensed.

instantsearch-ios's People

Contributors

francoischalifour avatar haroenv avatar lukyvj avatar mobilealgolia avatar nicfontana avatar plnech avatar raphi avatar robertmogos avatar sarahdayan avatar shipow avatar spinach avatar vladislavfitz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

instantsearch-ios's Issues

Updating HitsTableViewController

What is the best way to update HitsTableViewController after an add/delete/edit? Say that I have an index of items, and one of them is deleted from Algolia. I can use searcher.search() to force a reload, but this doesn't seem to always work.

For instance, I'll delete an item through the Swift iOS API call and see the output below in the console after getting a response and then triggering searcher.search()

2020-12-29T12:54:30-0600 info com.algolia.InstantSearchCore : InstantSearch.SingleIndexSearcher: received results - index: LXIUfjLYsWgtRJGbdSsMluTr9GH3 query: "" hits count: 27 in 1ms

This is the correct count (there were 28 before the delete, so now there are 27), but when I return to the HitsTableViewController, the item I deleted is (sometimes, not always) still there. So I'm having trouble syncing the UI with the data available and creating predictive behavior. I don't want a user to see an item they just deleted. When I perform a blank search it usually gets rid of the old item and the display matches up with the data, but this is an additional unnecessary step I don't want a user to have to do. Not to mention it uses up two operations to do what one should do.

I found this post and also this that asks a similar question (granted it's for a much older version of the library), and @spinach suggests that forcing a reload is necessary. He also mentions registering with Instant Search, and I was wondering how that's done in the current version.

I tried something like this, and it only worked on my newer device:

searcher.onResults.subscribe(with: self) { (_, results) in
		print(results.hits.count)
		if results.hits.isEmpty {
			self.showNoResultsUI()
			print("No results UI")
		 } else {
			print("There are results")
			self.showHits()
		}
	 }
     ...

   func showHits() {
	DispatchQueue.main.async {
	self.filterButton.isEnabled = true
	self.welcomeCollectionView.removeFromSuperview()
	self.noResultsView.removeFromSuperview()
	self.stackView.addArrangedSubview(hitsTableController.tableView)
	hitsTableController.tableView.reloadData()
	}
}

My question: is searcher.search() the best way to do this? For me, it seems to work sometimes, but other times does not. It depends on the device I'm using. On older devices, it's not very reliable. Are there any methods I'm not utilizing that I should be?

My theory is that reloadData() is being called before the data is actually available or faster than the device can process it, hence why on my new iPhone everything works as expected, but on my 5 year old iPad, it doesn't.

RESOLVED: Wow, I didn't search very well. @VladislavFitz answered this exact problem yesterday here. All is well. Something like the code below works great and solves the race condition for the older device.

		hitsInteractor.onResultsUpdated.subscribe(with: self) { _, results in
			DispatchQueue.main.async {
			print("Interactor Test")
			hitsTableController.tableView.reloadData()
			}
				}

Documentation for having the search bar in the navigation bar

The only reference I've found for how to put the search bar in the navigation bar is from the Movies example project, which is outdated. This method no longer works, because the new SearchBarController is not a UISearchController.

Is there any way to accomplish this with InstantSearch 5? If so, it would be nice to have it documented. The old sample project(s) should probably be updated or removed.

ResultingDelegate not working with custom widget when using multiple indices

Hello,

I have MKMapView extending the ResultingDelegate and implementing the on(results: SearchResults?, error: Error?, userInfo: [String: Any]) method, very similar to https://github.com/algolia/instantsearch-ios-examples/blob/master/Icebnb/Icebnb/MapViewWidget.swift.

I had been using a single index and this seemed to work fine, the on() method would get called after each Algolia search. However, I recently started using multiple indices and now the on() method of my MKMapView is not being called anymore. Looking at the code in InstantSearch.swift it seems like when calling InstantSearch.shared.registerAllWidgets(in: self.view) my custom widget should get added to the ResultingDelegates and thus it should work. What am I missing?

As a workaround I did:
InstantSearch.shared.getSearcher(named: Indeces.MAIN_INDEX)?.addResultHandler(mapView.on(results:error:userInfo:))
InstantSearch.shared.getSearcher(named: Indeces.SORTED_BY_RATING)?.addResultHandler(mapView.on(results:error:userInfo:))

and that seemed to fix my issue. However, shouldn't this happen automatically when registering the widgets?

Thank you

Add support for more dependency managers

Right now we only support CocoaPods, and the main reason was because of this:

InstantSearch Core has an external dependency (on the Algolia Search API Client). A package manager is therefore required to draw that dependency. Cocoapods works by adding special build phases to the Xcode project (in addition to creating a Pods project and an Xcode workspace referencing both). Because of this, it is technically impossible to support both Cocoapods and Carthage on the same project when it has external dependencies. Because Cocoapods has a wider audience than Carthage, we chose the former.

However, there are workarounds and we should add support for Carthage and SwiftPM

Cannot archive project with Xcode 12 beta 3

Describe the bug 🐛
When adding the following dependencies:

  pod 'InstantSearchClient', '~> 7.0'
  pod 'InstantSearch', '~> 7.0.0'
  pod 'AlgoliaSearchClient', :git => 'https://github.com/algolia/algoliasearch-client-swift', :branch => 'feat/xcode12-support'

I can build, but not archive the project. This is the error I recieve:

Undefined symbol: type metadata for Swift._StringObject.Variant

Here is the more detailed build output:

Ld /Users/scotto/Library/Developer/Xcode/DerivedData/Sexcellent-cnhbsnugaidhmeawcpinblrepddu/Build/Intermediates.noindex/ArchiveIntermediates/swiftUIPrototype/IntermediateBuildFilesPath/Pods.build/Release-iphoneos/InstantSearchInsights.build/Objects-normal/armv7/Binary/InstantSearchInsights normal armv7 (in target 'InstantSearchInsights' from project 'Pods')
    cd /Users/scotto/Desktop/sexcellent-ios/Pods
    /Users/scotto/Downloads/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -target armv7-apple-ios8.0 -dynamiclib -isysroot /Users/scotto/Downloads/Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk -L/Users/scotto/Library/Developer/Xcode/DerivedData/Sexcellent-cnhbsnugaidhmeawcpinblrepddu/Build/Intermediates.noindex/ArchiveIntermediates/swiftUIPrototype/BuildProductsPath/Release-iphoneos/InstantSearchInsights -F/Users/scotto/Library/Developer/Xcode/DerivedData/Sexcellent-cnhbsnugaidhmeawcpinblrepddu/Build/Intermediates.noindex/ArchiveIntermediates/swiftUIPrototype/BuildProductsPath/Release-iphoneos/InstantSearchInsights -filelist /Users/scotto/Library/Developer/Xcode/DerivedData/Sexcellent-cnhbsnugaidhmeawcpinblrepddu/Build/Intermediates.noindex/ArchiveIntermediates/swiftUIPrototype/IntermediateBuildFilesPath/Pods.build/Release-iphoneos/InstantSearchInsights.build/Objects-normal/armv7/InstantSearchInsights.LinkFileList -install_name @rpath/InstantSearchInsights.framework/InstantSearchInsights -Xlinker -rpath -Xlinker /usr/lib/swift -Xlinker -rpath -Xlinker @executable_path/Frameworks -Xlinker -rpath -Xlinker @loader_path/Frameworks -dead_strip -Xlinker -object_path_lto -Xlinker /Users/scotto/Library/Developer/Xcode/DerivedData/Sexcellent-cnhbsnugaidhmeawcpinblrepddu/Build/Intermediates.noindex/ArchiveIntermediates/swiftUIPrototype/IntermediateBuildFilesPath/Pods.build/Release-iphoneos/InstantSearchInsights.build/Objects-normal/armv7/InstantSearchInsights_lto.o -fembed-bitcode -Xlinker -bitcode_verify -Xlinker -bitcode_hide_symbols -Xlinker -bitcode_symbol_map -Xlinker /Users/scotto/Library/Developer/Xcode/DerivedData/Sexcellent-cnhbsnugaidhmeawcpinblrepddu/Build/Intermediates.noindex/ArchiveIntermediates/swiftUIPrototype/BuildProductsPath/Release-iphoneos/InstantSearchInsights -fobjc-arc -fobjc-link-runtime -L/Users/scotto/Downloads/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos -L/usr/lib/swift -Xlinker -add_ast_path -Xlinker /Users/scotto/Library/Developer/Xcode/DerivedData/Sexcellent-cnhbsnugaidhmeawcpinblrepddu/Build/Intermediates.noindex/ArchiveIntermediates/swiftUIPrototype/IntermediateBuildFilesPath/Pods.build/Release-iphoneos/InstantSearchInsights.build/Objects-normal/armv7/InstantSearchInsights.swiftmodule -framework Foundation -compatibility_version 1 -current_version 1 -Xlinker -dependency_info -Xlinker /Users/scotto/Library/Developer/Xcode/DerivedData/Sexcellent-cnhbsnugaidhmeawcpinblrepddu/Build/Intermediates.noindex/ArchiveIntermediates/swiftUIPrototype/IntermediateBuildFilesPath/Pods.build/Release-iphoneos/InstantSearchInsights.build/Objects-normal/armv7/InstantSearchInsights_dependency_info.dat -o /Users/scotto/Library/Developer/Xcode/DerivedData/Sexcellent-cnhbsnugaidhmeawcpinblrepddu/Build/Intermediates.noindex/ArchiveIntermediates/swiftUIPrototype/IntermediateBuildFilesPath/Pods.build/Release-iphoneos/InstantSearchInsights.build/Objects-normal/armv7/Binary/InstantSearchInsights

Undefined symbols for architecture armv7:
  "type metadata for Swift._StringObject.Variant", referenced from:
      outlined init with take of Swift._StringObject.Variant in CoreEvent.o
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I'm not sure but it seems to be an issue with the architecture of the source code.

To Reproduce 🔍
Steps to reproduce the behavior:

  1. Install aforementioned dependencies
  2. You can try to build, this should work.
  3. Select Build => Any iOS device (arm64)
  4. If you try to archive the project (Catalina, Xcode beta 3), the above error is thrown.

Expected behavior 💭
Error is not thrown, and code is able to be archived.

Screenshots 🖥

image

image

image

Environment:

  • Catalina
  • Xcode 12 beta 3

Thank you for looking into this- let me know if you need more details.

Xcode 12.5 (Fastlane) Archive Fails

Describe the bug 🐛
Building fails with "unknown type" errors (see screenshot) that suggest the compiler doesn't realize you're referencing SwiftUI for some reason. While this seems like it might be a compiler bug, an easy fix is to add import SwiftUI statements to any files requiring it.

To Reproduce 🔍
Steps to reproduce the behavior:

  1. Attempt to archive a build via Fastlane including this project vis SPM.
  2. Building and archiving fails.

Expected behavior 💭
Builds should succeed.

Screenshots 🖥
Screen Shot 2021-05-08 at 6 44 22 PM

Environment:

  • OS: iOS
  • Version 7.11.0

Implementing protocols in non UI-View objects

Hello,

I would like to know if other objects ,which are not UI views, can implement protocols like "ResultingDelegate" ?
From my understanding only widgets can implement these protocols. And widgets can only be UI views inheriting from AlgoliaWidget.
How to overcome this limitation and enable any swift class of any type to access the results of search() ?

Thanks for your help.

Unrecognized Selector Sent To Instance - Sequencer Class

I am using InstantSearch MultiIndex components and I am getting a crash that occurs every now and then. App crashes and returns "unrecognized selector sent to instance" error. I set a breakpoint and see that it ends up crashing in the dismissOperation(withSeqNo seqNo: Int) function in the Sequencer class. When not setting a breakpoint, I also get the following error:

Thread. 3: EXC_BAD_ACCESS (code=1, address=0x18) in the cancelOperation(withSeqNo seqNo: Int) function in the Sequencer class.

In the view controller, I am using a MultiIndexSearcher, MultiIndexSearchConnector, MultiIndexHitsInteractor, and a MultiIndexHitsController to perform the search. I have a search controller to handle user input. I eliminated everything else in the viewcontroller except these Instant Search Components

The crash only happens about 1 in 8 times. It will work as expected for a couple of builds, and then will crash with the above error every now in then.

I am using iOS 14. I can provide additional details if needed.

Support tvOS?

Is your feature request related to a problem? Please describe 🙏
Not really, but I have to implement http request manually which needs lot of effort.

Describe the solution you'd like 🤔
Support tvOS, so I can make request easily as iOS does.

Describe alternatives you've considered ✨
Manually create http request, but not an ideal.

Additional context
I'm using cocoapods to install this SDK

Thank you!

Result updated, but attribute not selected

Hi. i faced with bug. If i pressed on three attribute i see result "0", but third attribute not selected.
You can check screen record on the link. https://drive.google.com/file/d/1Iz3x67V_mjBE8TRipQcXt3_mkYbJnML_/view?usp=sharing

My code:

class SearchTableViewController: UITableViewController {

@IBOutlet weak var resultButton: StatsButtonWidget!

override func viewDidLoad() {
   super.viewDidLoad()
   
   addResultButtonView()
   
   InstantSearch.shared.registerAllWidgets(in: self.view)
   
   LayoutHelpers.setupResultButton(button: resultButton)
   resultButton.addTarget(self, action: #selector(resultButtonClicked), for: .touchUpInside)
   
}

private func addResultButtonView() {
   
   view.addSubview(resultButton)
   
   resultButton.resultTemplate = "Показать {nbHits} результат(-а/-ов)"
   
   resultButton.layer.zPosition = 5
   
   resultButton.translatesAutoresizingMaskIntoConstraints = false
   resultButton.leftAnchor.constraint(equalTo: tableView.safeAreaLayoutGuide.leftAnchor).isActive = true
   resultButton.rightAnchor.constraint(equalTo: tableView.safeAreaLayoutGuide.rightAnchor).isActive = true
   resultButton.bottomAnchor.constraint(equalTo: tableView.safeAreaLayoutGuide.bottomAnchor).isActive = true
   resultButton.widthAnchor.constraint(equalTo: tableView.safeAreaLayoutGuide.widthAnchor).isActive = true
   resultButton.heightAnchor.constraint(equalToConstant: 40).isActive = true // высота кнопки 
   
}

@objc func resultButtonClicked() {
   
   if let viewController = storyboard?.instantiateViewController(withIdentifier: "resultVC") as? ResultViewController {
       
       let backItem = UIBarButtonItem()
       backItem.title = "Поиск"
       self.navigationItem.backBarButtonItem = backItem
       
       self.navigationController?.pushViewController(viewController, animated: true)
       
   }
   
}

}

2017-12-05 13 20 42

Application rejected due to NSSpeechRecognitionUsageDescription

Kindly someone guide me regarding this one, i've added NSSpeechRecognitionUsageDescription key in info.plist but still getting rejected. Apple response is as following.
 

 
Dear Developer,We identified one or more issues with a recent delivery for your app, "App Name". Please correct the following issues, then upload again.Missing Purpose String in Info.plist File - Your app's code references one or more APIs that access sensitive user data. The app's Info.plist file should contain a NSSpeechRecognitionUsageDescription key with a user-facing purpose string explaining clearly and completely why your app needs the data. Starting Spring 2019, all apps submitted to the App Store that access user data will be required to include a purpose string.If you're using external libraries or SDKs, they may reference APIs that require a purpose string. While your app might not use these APIs, a purpose string is still required. You can contact the developer of the library or SDK and request they release a version of their code that doesn't contain the APIs. Learn more (https://developer.apple.com/documentation/uikit/core_app/protecting_the_user_s_privacy).Best regards,The App Store Team

Custom AlgoliaWidget with multi index

Hi,

I use a collectionView (HitCollectionWidget) to display a collection of products.
I need to sort those items by price.

As seen in #34, i switched to a multi-index configuration in order to be able to switch from the regular index to the price-sorted index.

For some the HitsCollectionWidget and the SearchBarWidget, I had to specify the used index, using getSearched to retrieve the index :

searchBar.index = (InstantSearch.shared.getSearcher(named: algoliaBackOfficeOfferChannel)?.indexName)!

Everything works fine but I have an issue on a custom Widget meant to dispaly the number of results that keeps displaying 0 résultat (it works fine with a single index).
I changed from AlgoliaWidget to AlgoliaIndexWidget and set the index as this :

nbResultsLabel.index = (InstantSearch.shared.getSearcher(named: algoliaBackOfficeOfferChannel)?.indexName)!

Here is the code of this widget :

import UIKit
import InstantSearch
import InstantSearchCore

class NbResultsWidget: UILabel, AlgoliaIndexWidget, ResultingDelegate {
    
    @IBInspectable public var index: String = ""
    @IBInspectable public var variant: String = ""
    
    func on(results: SearchResults?, error: Error?, userInfo: [String: Any]) {
        
        guard let results = results else {
            return
        }
        
        if results.nbHits > 1 {
            self.text = "\(results.nbHits) résultats"
        } else {
            self.text = "\(results.nbHits) résultat"
        }
    }
}

Did I miss something in the widget configuration ?
Thank you for your help.

filters

Is your feature request related to a problem? Please describe 🙏
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like 🤔
A clear and concise description of what you want to happen.

Describe alternatives you've considered ✨
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

Unable to display categories selected data in list page

Here I am using the algolia for the first time to display the categories selected id to pass and load data in list page according to it and here I passed the selected data to the list page but here unable to load the data required for selected category and got crashed in index.search line please help me how to resolve this ?

Here is my selected categories array data which I was passing from my categories page

["[categories.level0:Men]", "[categories.level1:Men///Tops]", "[categories.level2:Men///Tops///Tees]"]

and below is my facets array data

["categories.level0", "categories.level1", "categories.level2", "gometoo_seller", "style_bottom", "climate", "sleeve", "gender", "category_gear", "eco_collection", "pattern", "collar", "style_bags", "style_general", "is_trending", "erin_recommends", "format", "performance_fabric", "strap_bags", "features_bags", "activity", "material", "categories", "color", "is_new", "size", "price", "manufacturer", "price.BHD.default", "price.EGP.default", "price.EUR.default", "price.KWD.default", "price.OMR.default", "price.SAR.default", "price.USD.default", "price.AED.default"]

here is my algolia back end data

index.search("", {
 "hitsPerPage": "10",
 "page": "0",
 "analytics": "false",
 "attributesToRetrieve": "*",
 "facets": "[\"categories.level0\",\"categories.level1\",\"categories.level2\",\"activity\",\"category_gear\",\"climate\",\"color\",\"eco_collection\",\"erin_recommends\",\"features_bags\",\"format\",\"gender\",\"gometoo_seller\",\"is_new\",\"is_trending\",\"material\",\"pattern\",\"performance_fabric\",\"price.AED.default\",\"price.BHD.default\",\"price.EGP.default\",\"price.EUR.default\",\"price.KWD.default\",\"price.OMR.default\",\"price.SAR.default\",\"price.USD.default\",\"size\",\"strap_bags\",\"style_bags\",\"style_bottom\",\"style_general\"]",
 "facetFilters": "[[\"categories.level2:Men /// Tops /// Tees\"],[\"categories.level1:Men /// Tops\"],[\"categories.level0:Men\"]]"
});

and the code for this is

if (self.appId != nil && self.apiKEY != nil && self.Indices != nil) {
            InstantSearch.shared.configure(appID: "\(self.appId!)", apiKey: "\(self.apiKEY!)", index: "\(self.Indices!)en_products")
            InstantSearch.shared.params.attributesToRetrieve = ["*"]
            InstantSearch.shared.registerAllWidgets(in: self.view)
            let query = Query()
            query.facets = facetsArray
            query.facetFilters = categoriesArray
            index.search(query, completionHandler: { (res, error) in
                self.listCollectionView.reloadData()
            })
            hitsCollectionViews = [self.listCollectionView]
            ActivityIndicator.stopAnimating()  
        }

Hits Per Page

Using InstantSearch for iOS, what's the easiest way to customize the hitsPerPage option? Infinite scroll seems to just really eat up operations.

Deserializing hits blocks main thread

Describe the bug 🐛
We ran into a performance issue when updating to the newest version of InstantSearch. While most of the migration from version 3.x went smooth we ran into multiple performance issues blocking main thread and the whole app UI when using search-as-you-type. It turned out that our search objects got bloated by a bug on our end but still this should not block the app UI just to do JSON deserialization on main thread.

To Reproduce 🔍
Use an index where search documents are large (ours were about 50kB per item).

Expected behavior 💭
The app should show search results with a bigger delay but should not block the user from typing.

Environment:

  • OS: iOS
  • Version 13.2

Additional context
It looks like the whole deserialization of the payload should be taken away from main thread to make sure we don't block UI with non-UI related tasks.

P.S. Why does HitsInteractor require the Record generic to implement Codable wouldn't Decodable be enough?

When simulating a device, performance is snappy

From support:

Has anyone reported performance issues when running a build off Xcode on hardware? When simulating a device, performance is snappy. When I search while running the build on my iPhone X, it's crawling. I haven't found an explanation for this, so figured I'd ask.

Compiler error Xcode 12

After installing the "InstantSearch" via CocoaPods, I am unable to run my project, and it's showing three build errors upon installing the pod.

Screen Shot 2020-12-23 at 6 22 13 PM

SearchBarWidget, add support for searchBarSearchButtonClicked

override public func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
    resignFirstResponder()
}

Current implementation assigns self as delegate, so we can't make our viewcontroller delegate for searchbarwidget. Way searchbarwidget works it is ideal to close the keyboard upon clicking search. Either supporting above method will help or need way of controlling searchbutton clicked

{nbHits} varies according to the index

Hi,
We have products displayed in a HitsCollectionWidget with a StatsLabelWidget displaying the number of results.
We use 3 index to sort product (default, price ASC, price DESC)
When we switch the index, the number of hits varies (for example: 577 results for default index, 535 for price ASC and 544 for price DESC).
It's a strange behaviour for our customers.
Is there a way to refresh this nbHits count or make it more precise ?

Test

Describe the bug 🐛
A clear and concise description of what the bug is.

To Reproduce 🔍
Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior 💭
A clear and concise description of what you expected to happen.

Screenshots 🖥
If applicable, add screenshots to help explain your problem.

Environment:

  • OS: [e.g. iOS / windows / mac / android]
  • Version [e.g. 22]

Additional context
Add any other context about the problem here.

FacetListConnector should have a FacetListPresenter as an optional param

We should add a convenient init for FacetListConnector to expose FacetListPresenter.

In FacetListConnector.swift we do the following when connecting the interactor with the controller

interactor.connectController(controller)

We should add the optional presenter in the above method.

Edit: Also, concerning the selectionMode, we should also be able to specify it without having to specify the facets param (can add a default value there)

Selecting multiple facets is broken in 3.1.x

Describe the bug 🐛
When attempting to select multiple facets, I am no longer able to after upgrading from InstantSearch 3.0.0 to 3.1.0 or 3.1.1. When tapping on a second facet, that one will be selected but my previous selection will be reset.

To Reproduce 🔍
Steps to reproduce the behavior:

  1. Go to a controller using using the RefinementCollectionWidget
  2. Click on any facet
  3. Click on a second facet
  4. See that only the second one is selected, not both

Expected behavior 💭
In previous versions, I was able to filter by multiple facets at once.

Environment:

  • OS: iOS 12.1.2
  • Version 3.1.0 and 3.1.1

Limited advanced connectors iOS availability

The convenient initialisers of SingleIndexSearchConnector and MultiIndexSearchConnector using UISearchController require iOS 13 target.
These initialisers used in the InstantSearch iOS Getting started guide, so its applicability is limited.
Theses requirements can be wrapped inside the initializers in order to make them universal.

Filter.Numeric not working with large integer (i.e. timestamps)

Describe the bug 🐛
I have a date_timestamp in my index, and would like to add a Filter.Numeric to my FilterState.
The filter is not respected and no results is returned.

To Reproduce 🔍

let nowTimestamp = Float(NSDate().timeIntervalSince1970)
let filter = Filter.Numeric(attribute: "date_timestamp", operator: .greaterThanOrEqual, value: nowTimestamp)
filterState[and: "calendar"].add(filter)
...

This doesn't returns any results as it should be, based on my index data.

Expected behavior 💭
The filter should returns the correct answer.

Environment:

  • OS: iOS
  • Version 5.2.2

Possible Error With Xcode 12.3 and Instant Search 7.6

Describe the bug 🐛
There is a swift compiler error on Xcode 12.3 and InstantSearch 7.6. The error reads:
"Type 'Hit' does not conform to protocol 'Geolocated'"

To Reproduce 🔍
Updated from InstantSearch 7.4 to 7.6 today. Xcode version was already 12.3 and functioning properly before the pod update.

  1. Try and build project.
  2. Look at compile time errors.

Expected behavior 💭
Expecting the code to properly compile.

Screenshots 🖥

Screen Shot 2020-12-18 at 9 03 47 PM

Screen Shot 2020-12-18 at 9 05 32 PM

Environment:
Mac - Big Surr
Version - 11.01

Additional context
Downloaded InstantSearch Project to test if project itself was the problem, but the instant search project shows the same error.

'No results available' message displayed while fetching the initial data

I have implemented HitsTableViewController, it takes around few seconds to fetch the initial search result. Table displays 'No results available' message while data is not loaded.

Message should only be displayed once data is fetched and no records are available. It should render the empty table while fetching the data.

Add "fake" UITableView row when no hits

Hello, Algolia community!

When using the MultiHitsTableWidget the table view gets populated when there are results and that's totally fine. As my table view cells serve as action triggers when tapped, I miss the case when there are no results. Is there any way I can add a "fake" result row in the table view which has the exact same text as what the user has typed in the search bar? Any leads will be highly appreciated.

How to add parameters before search() ?

I am adding a parameter to Searcher like this :

InstantSearch.shared.getSearcher().params.filters = "application_categories:69539"
InstantSearch.shared.getSearcher().search()

On the results, this params is not taken in account.

Here is the debug result. The filter appears in the Searcher params :

(lldb) po InstantSearch.shared.getSearcher().params
SearchParameters{["hitsPerPage": "20", "attributesToHighlight": "[\"name\"]", 
"attributesToRetrieve": "[\"name\",\"description\",\"best_offer\",\"brand\",\"assigned_images\",\"created_on\",
\"offers_count\",\"other_offers\",\"application_categories_dict\"]", "filters": "application_categories:69539"]}

Can any one please tell me how can I add parameter to the InstantSearch ?

Objective-C Support

Hello Everyone,

Are there any plans to add objective-c support to InstantSearch 7. I believe there are many legacy projects out there that are already integrated with algolia (like us) or many more potentials that might want to integrate as well.

Cannot build project in Xcode 12 with InstantSearch 7

Describe the bug 🐛
Project will not build- there seem to be errors in the source files.

To Reproduce 🔍
Steps to reproduce the behavior:
Create new Xcode project.
Add pod 'InstantSearch', '~> 7.0'
Try to build project

Expected behavior 💭
No build errors from source

Screenshots 🖥
image

Environment:

  • OS: MacOS Catalina, 10.15.5
  • Xcode 12, beta 2

Thanks for looking into this! The InstantSearchClient is working fine for querying the algolia servers, but I'd like to use the HitsInteractor to parse the results.

Crash due to key value observer in iOS 9

Describe the bug 🐛
A clear and concise description of what the bug is.

When run in the instant search in iOS 9 getting a below crash.

2019-01-11 12:37:53.071 YosiMD[5517:107780] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'An instance 0x7fb174947c00 of class InstantSearchCore.SearchParameters was deallocated while key value observers were still registered with it. Current observation info: <NSKeyValueObservationInfo 0x7fb17494f120> (
<NSKeyValueObservance 0x7fb174948670: Observer: 0x7fb17494a6b0, Key path: query, Options: <New: NO, Old: NO, Prior: NO> Context: 0x0, Property: 0x7fb174947d10>
)'

To Reproduce 🔍
Steps to reproduce the behavior:

  1. I have create an instance of viewcontroller.
  2. Then added instant search instance to it.
  3. Added it as child view controller to another view
  4. It works fine. Then removed the view controller view.
  5. Again add it the same view controller as subview.
  6. It crashes with above code.
  7. This crash is happening only in iOS 9 and iOS 10.

Expected behavior 💭
it should crash, the same code works in iOS 11.

Screenshots 🖥
If applicable, add screenshots to help explain your problem.

Environment:

  • OS: iOS
  • Version 9.3, 10.3

Additional context
Please fix the issue as this was in the happening in the production build. Many users are affected due to it.

Overriding Widgets' protocols implementation

Hello,

I would like to call a function when I receive results after a search(). If I understand correctly the implementation of the protocol "ResultingDelegate" enables to act on the search results.
I wonder if there is a way to override the implementation of the protocols in the widgets like the search bar widget for instance.
Or do we need to create a new widget ? It would not be very good because I don't want to miss all the functionalities of the Search Bar Widget.

Thanks in advance for your help.

'HitsTableController' is unavailable: Use your own UITableViewController conforming to HitsController protocol

Describe the bug 🐛
Followed the getting started guide and have been using the library for my project for a while now without problems. But recently, after updating my podfile to remove InstantSearchClient and just use InstantSearch, I'm getting an error when trying to build and run my app:

'HitsTableController' is unavailable: Use your own UITableViewController conforming to HitsController protocol

Am I doing something wrong? I'm using InstantSearch 7.0. Is it not playing nice with the new Algolia Swift v8? I got hit with a double whammy by updating to 7, because all kinds of breaking changes to Algolia client were made recently.

Environment:
iOS

Sorting by field

Is there an example of how to sort by a field? For example, sort by rating or sort by distance, etc. I can't seem to find an example.

Application Crashing while registering widgets

Hi, my application is crashing in method InstantSearch.shared.registerAllWidgets(in: self.view) with error "Fatal error: Duplicate element found in Set. Elements may have been mutated after insertion
". If any one knows regarding this kindly let me know.
Thanks

Swift 5 compatibility

When attempting to compile on Xcode 10.2, I am getting the following error in InstantSearchClient > Cache.swift > updateTimer()

'default' has been renamed to RunLoopMode.defaultRunLoopMode

Impossible to directly modify query of IndexQueryState in the MultiIndexSearcher

Describe the bug 🐛

Since Query became a structure in the v8 of the Swift Client, it is now impossible to directly change the Query of indexQueryStates in the MultiIndexSearcher

To Reproduce 🔍

let searcher: MultiIndexSearcher
    
// Compiler error: Cannot assign to property: 'indexQueryStates' setter is inaccessible
searcher.indexQueryStates[0].query.filters = "brand:sony"

Environment:

  • Version 7.1.0

Cannot declare hitsTableController

Describe the bug 🐛
Upon following the IOS tutorial detailing how to Display hits in a tableview, I am getting the error "'HitsTableController' is unavailable: Use your own UITableViewController conforming to HitsController protocol"

To Reproduce 🔍
Copy the line:
let hitsTableController: HitsTableController<HitsInteractor<JSON>> = .init(tableView: UITableView())

from the above linked tutorial in XCode.

Expected behavior 💭
No Error

Screenshots 🖥
Screen Shot 2020-08-02 at 10 34 21 PM

Environment:

  • OS: IOS Development on XCode

How to know if HitsCollectionWidget is refined ?

Hi,

I use a HitsCollectionWidget combined with a RefinementController.
On the view containing the HitsCollectionWidget, I would like to display an indicator if the collection is refined.
Is there a way to know if a collectionWidget is refined ?

Thank you for your reply

Wrong facet value count returned

Hi,
actually, in our product list, we have a "brand" facet so in the SearchResult we have a nice list of 100 brands (the most popular).
If we apply a facet refinement with one or more of those brands, the SearchResult returns the filtered products with the brands facet values and their counts.
But if we apply a facet refinement with one or more brands that was not initially in the list of 100 (we can search brands), the SearchResult returns for those brands facet values a count equal to 0.
Everything works fine in the Algolia Dashboard, but not with the iOS & Android SDK.
Maybe we did something wrong, or maybe it is a bug in the SDK.
Thank you for your reply,

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.