[ios] Refactored search functionality.

This commit is contained in:
Ilya Grechuhin 2016-07-14 12:38:41 +03:00
parent 8cac395d40
commit a7618a2769
13 changed files with 443 additions and 287 deletions

View file

@ -3,15 +3,18 @@
static NSString * const MAPSWITHME_PREMIUM_LOCAL_URL = @"mapswithmepro://";
static NSString * const BOOKMARK_CATEGORY_DELETED_NOTIFICATION = @"BookmarkCategoryDeletedNotification";
static NSString * const BOOKMARK_CATEGORY_DELETED_NOTIFICATION =
@"BookmarkCategoryDeletedNotification";
static NSString * const METRICS_CHANGED_NOTIFICATION = @"MetricsChangedNotification";
static NSString * const BOOKMARK_DELETED_NOTIFICATION = @"BookmarkDeletedNotification";
static NSString * const LOCATION_MANAGER_STARTED_NOTIFICATION = @"LocationManagerStartedNotification";
static NSString * const LOCATION_MANAGER_STARTED_NOTIFICATION =
@"LocationManagerStartedNotification";
static NSString * const kDownloadingProgressUpdateNotificationId = @"DownloadingProgressUpdateNotificationId";
static NSString * const kDownloadingProgressUpdateNotificationId =
@"DownloadingProgressUpdateNotificationId";
static NSString * const kHaveAppleWatch = @"HaveAppleWatch";
@ -26,7 +29,8 @@ static inline NSString * const kApplicationGroupIdentifier()
static NSString * const productionExtBundleIdentifier = @"com.mapswithme.full.watchkitextension";
NSString * bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
if ([bundleIdentifier isEqualToString:productionAppBundleIdentifier] || [bundleIdentifier isEqualToString:productionExtBundleIdentifier])
if ([bundleIdentifier isEqualToString:productionAppBundleIdentifier] ||
[bundleIdentifier isEqualToString:productionExtBundleIdentifier])
return productionGroupIdentifier;
return developerGroupIdentifier;
}
@ -67,7 +71,8 @@ static uint64_t const MB = 1024 * 1024;
static inline NSString * formattedSize(uint64_t size)
{
return [NSByteCountFormatter stringFromByteCount:size countStyle:NSByteCountFormatterCountStyleFile];
return
[NSByteCountFormatter stringFromByteCount:size countStyle:NSByteCountFormatterCountStyleFile];
}
// Use only for screen dimensions CGFloat comparison
@ -75,3 +80,8 @@ static inline BOOL equalScreenDimensions(CGFloat left, CGFloat right)
{
return fabs(left - right) < 0.5;
}
static inline void runAsyncOnMainQueue(dispatch_block_t block)
{
dispatch_async(dispatch_get_main_queue(), block);
}

View file

@ -5,6 +5,7 @@
#import "MWMMapViewControlsManager.h"
#import "MWMNoMapsViewController.h"
#import "MWMRouter.h"
#import "MWMSearch.h"
#import "MWMSearchTabButtonsView.h"
#import "MWMSearchTabbedViewController.h"
#import "MWMSearchTableViewController.h"
@ -27,18 +28,18 @@ extern NSString * const kSearchStateKey = @"SearchStateKey";
MWMSearchTabButtonsViewProtocol, UITextFieldDelegate,
MWMFrameworkStorageObserver>
@property (weak, nonatomic) UIView * parentView;
@property (nonatomic) IBOutlet MWMSearchView * rootView;
@property (weak, nonatomic) IBOutlet UIView * contentView;
@property(weak, nonatomic) UIView * parentView;
@property(nonatomic) IBOutlet MWMSearchView * rootView;
@property(weak, nonatomic) IBOutlet UIView * contentView;
@property (nonatomic) IBOutletCollection(MWMSearchTabButtonsView) NSArray * tabButtons;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint * scrollIndicatorOffset;
@property (weak, nonatomic) IBOutlet UIView * scrollIndicator;
@property(nonatomic) IBOutletCollection(MWMSearchTabButtonsView) NSArray * tabButtons;
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * scrollIndicatorOffset;
@property(weak, nonatomic) IBOutlet UIView * scrollIndicator;
@property (nonatomic) UINavigationController * navigationController;
@property (nonatomic) MWMSearchTabbedViewController * tabbedController;
@property (nonatomic) MWMSearchTableViewController * tableViewController;
@property (nonatomic) MWMNoMapsViewController * noMapsController;
@property(nonatomic) UINavigationController * navigationController;
@property(nonatomic) MWMSearchTabbedViewController * tabbedController;
@property(nonatomic) MWMSearchTableViewController * tableViewController;
@property(nonatomic) MWMNoMapsViewController * noMapsController;
@end
@ -69,17 +70,14 @@ extern NSString * const kSearchStateKey = @"SearchStateKey";
{
if (self.state == MWMSearchManagerStateDefault)
self.state = MWMSearchManagerStateTableSearch;
self.searchTextField.isSearching = YES;
}
- (void)endSearch
{
GetFramework().CancelInteractiveSearch();
if (self.state != MWMSearchManagerStateHidden)
self.state = MWMSearchManagerStateDefault;
self.searchTextField.isSearching = NO;
self.searchTextField.text = @"";
[self.tableViewController searchText:@"" forInputLocale:nil];
[MWMSearch clear];
}
#pragma mark - Actions
@ -108,8 +106,7 @@ extern NSString * const kSearchStateKey = @"SearchStateKey";
else
{
[self beginSearch];
[self.tableViewController searchText:text
forInputLocale:textField.textInputMode.primaryLanguage];
[MWMSearch searchQuery:text forInputLocale:textField.textInputMode.primaryLanguage];
}
}
else
@ -167,7 +164,7 @@ extern NSString * const kSearchStateKey = @"SearchStateKey";
[self beginSearch];
self.searchTextField.text = text;
NSString * inputLocale = locale ? locale : self.searchTextField.textInputMode.primaryLanguage;
[self.tableViewController searchText:text forInputLocale:inputLocale];
[MWMSearch searchQuery:text forInputLocale:inputLocale];
}
- (void)tapMyPositionFromHistory
@ -185,19 +182,24 @@ extern NSString * const kSearchStateKey = @"SearchStateKey";
self.state = MWMSearchManagerStateHidden;
}
- (void)processSearchWithResult:(search::Result const &)result query:(search::QuerySaver::TSearchRequest const &)query
- (void)processSearchWithResult:(search::Result const &)result
{
auto & f = GetFramework();
f.SaveSearchQuery(query);
MapsAppDelegate * a = MapsAppDelegate.theApp;
MWMRoutingPlaneMode const m = a.routingPlaneMode;
MWMRoutePoint const p = {result.GetFeatureCenter(), @(result.GetString().c_str())};
if (m == MWMRoutingPlaneModeSearchSource)
{
MWMRoutePoint const p = { result.GetFeatureCenter(), @(result.GetString().c_str()) };
[[MWMRouter router] buildFromPoint:p bestRouter:YES];
}
else if (m == MWMRoutingPlaneModeSearchDestination)
{
MWMRoutePoint const p = { result.GetFeatureCenter(), @(result.GetString().c_str()) };
[[MWMRouter router] buildToPoint:p bestRouter:YES];
}
else
f.ShowSearchResult(result);
{
[MWMSearch showResult:result];
}
if (!IPAD && a.routingPlaneMode != MWMRoutingPlaneModeNone)
a.routingPlaneMode = MWMRoutingPlaneModePlacePage;
self.state = MWMSearchManagerStateHidden;
@ -213,12 +215,13 @@ extern NSString * const kSearchStateKey = @"SearchStateKey";
if (nodeStatuses.m_status != NodeStatus::OnDisk)
return;
[self updateTopController];
if (self.state == MWMSearchManagerStateTableSearch || self.state == MWMSearchManagerStateMapSearch)
if (self.state == MWMSearchManagerStateTableSearch ||
self.state == MWMSearchManagerStateMapSearch)
{
NSString * text = self.searchTextField.text;
if (text.length > 0)
[self.tableViewController searchText:text
forInputLocale:self.searchTextField.textInputMode.primaryLanguage];
if (text.length != 0)
[MWMSearch searchQuery:text
forInputLocale:self.searchTextField.textInputMode.primaryLanguage];
}
}
@ -261,24 +264,17 @@ extern NSString * const kSearchStateKey = @"SearchStateKey";
{
self.rootView.compact = NO;
self.rootView.tabBarIsVisible = NO;
self.tableViewController.searchOnMap = NO;
[MWMSearch setSearchOnMap:NO];
if (![self.navigationController.viewControllers containsObject:self.tableViewController])
[self.navigationController pushViewController:self.tableViewController animated:NO];
}
- (void)changeToMapSearchState
{
auto & f = GetFramework();
UITextField * textField = self.searchTextField;
string const locale = textField.textInputMode.primaryLanguage ?
textField.textInputMode.primaryLanguage.UTF8String :
self.tableViewController.searchParams.m_inputLocale;
f.SaveSearchQuery(make_pair(locale, textField.text.precomposedStringWithCompatibilityMapping.UTF8String));
f.DeactivateMapSelection(true);
GetFramework().DeactivateMapSelection(true);
[self.searchTextField resignFirstResponder];
self.rootView.compact = YES;
self.tableViewController.searchOnMap = YES;
[MWMSearch setSearchOnMap:YES];
}
#pragma mark - Properties
@ -287,7 +283,8 @@ extern NSString * const kSearchStateKey = @"SearchStateKey";
{
if (!_navigationController)
{
_navigationController = [[UINavigationController alloc] initWithRootViewController:self.topController];
_navigationController =
[[UINavigationController alloc] initWithRootViewController:self.topController];
[self.contentView addSubview:_navigationController.view];
_navigationController.navigationBarHidden = YES;
}
@ -296,7 +293,8 @@ extern NSString * const kSearchStateKey = @"SearchStateKey";
- (UIViewController *)topController
{
if (self.state == MWMSearchManagerStateHidden || GetFramework().Storage().HaveDownloadedCountries())
if (self.state == MWMSearchManagerStateHidden ||
GetFramework().Storage().HaveDownloadedCountries())
{
return self.tabbedController;
}
@ -304,8 +302,10 @@ extern NSString * const kSearchStateKey = @"SearchStateKey";
{
if (!self.noMapsController)
{
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:@"Mapsme" bundle:[NSBundle mainBundle]];
self.noMapsController = [storyboard instantiateViewControllerWithIdentifier:@"MWMNoMapsViewController"];
UIStoryboard * storyboard =
[UIStoryboard storyboardWithName:@"Mapsme" bundle:[NSBundle mainBundle]];
self.noMapsController =
[storyboard instantiateViewControllerWithIdentifier:@"MWMNoMapsViewController"];
}
return self.noMapsController;
}
@ -387,9 +387,5 @@ extern NSString * const kSearchStateKey = @"SearchStateKey";
[[MWMMapViewControlsManager manager] searchViewDidEnterState:state];
}
- (UIView *)view
{
return self.rootView;
}
- (UIView *)view { return self.rootView; }
@end

View file

@ -1,5 +1,2 @@
@interface MWMSearchTextField : UITextField
@property (nonatomic) BOOL isSearching;
@end

View file

@ -1,17 +1,26 @@
#import "MWMSearchTextField.h"
#import "MWMSearch.h"
#import "UIColor+MapsMeColor.h"
#import "UIImageView+Coloring.h"
@interface MWMSearchTextField ()<MWMSearchObserver>
@property(nonatomic) BOOL isSearching;
@end
@implementation MWMSearchTextField
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (!self)
return nil;
self.isSearching = NO;
self.leftViewMode = UITextFieldViewModeAlways;
self.textColor = [UIColor blackSecondaryText];
if (self)
{
self.isSearching = NO;
self.leftViewMode = UITextFieldViewModeAlways;
self.textColor = [UIColor blackSecondaryText];
[MWMSearch addObserver:self];
}
return self;
}
@ -29,8 +38,10 @@
_isSearching = isSearching;
if (isSearching)
{
UIActivityIndicatorView * view = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
view.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
UIActivityIndicatorView * view = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
view.autoresizingMask =
UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
[view startAnimating];
view.bounds = self.leftView.bounds;
self.leftView = view;
@ -42,4 +53,8 @@
}
}
#pragma mark - MWMSearchObserver
- (void)onSearchStarted { self.isSearching = YES; }
- (void)onSearchCompleted { self.isSearching = NO; }
@end

View file

@ -7,28 +7,22 @@
namespace search
{
class Result;
class Result;
}
@protocol MWMSearchTableViewProtocol <MWMSearchTabbedViewProtocol>
@protocol MWMSearchTableViewProtocol<MWMSearchTabbedViewProtocol>
@property (weak, nonatomic) MWMSearchTextField * searchTextField;
@property(weak, nonatomic) MWMSearchTextField * searchTextField;
@property (nonatomic) MWMSearchManagerState state;
@property(nonatomic) MWMSearchManagerState state;
- (void)processSearchWithResult:(search::Result const &)result
query:(search::QuerySaver::TSearchRequest const &)query;
- (void)processSearchWithResult:(search::Result const &)result;
@end
@interface MWMSearchTableViewController : MWMViewController
@property (nonatomic) BOOL searchOnMap;
- (nonnull instancetype)init __attribute__((unavailable("init is not available")));
- (nonnull instancetype)initWithDelegate:(nonnull id<MWMSearchTableViewProtocol>)delegate;
- (void)searchText:(nonnull NSString *)text forInputLocale:(nullable NSString *)locale;
- (search::SearchParams const &)searchParams;
@end

View file

@ -1,22 +1,20 @@
#import "Macros.h"
#import "MapsAppDelegate.h"
#import "MWMSearchTableViewController.h"
#import "MWMLocationManager.h"
#import "MWMSearch.h"
#import "MWMSearchCommonCell.h"
#import "MWMSearchShowOnMapCell.h"
#import "MWMSearchSuggestionCell.h"
#import "MWMSearchTableView.h"
#import "MWMSearchTableViewController.h"
#import "Macros.h"
#import "MapsAppDelegate.h"
#import "Statistics.h"
#import "ToastView.h"
#include "search/params.hpp"
static NSString * const kTableShowOnMapCell = @"MWMSearchShowOnMapCell";
static NSString * const kTableSuggestionCell = @"MWMSearchSuggestionCell";
static NSString * const kTableCommonCell = @"MWMSearchCommonCell";
typedef NS_ENUM(NSUInteger, MWMSearchTableCellType)
{
typedef NS_ENUM(NSUInteger, MWMSearchTableCellType) {
MWMSearchTableCellTypeOnMap,
MWMSearchTableCellTypeSuggestion,
MWMSearchTableCellTypeCommon
@ -26,66 +24,53 @@ NSString * identifierForType(MWMSearchTableCellType type)
{
switch (type)
{
case MWMSearchTableCellTypeOnMap:
return kTableShowOnMapCell;
case MWMSearchTableCellTypeSuggestion:
return kTableSuggestionCell;
case MWMSearchTableCellTypeCommon:
return kTableCommonCell;
case MWMSearchTableCellTypeOnMap: return kTableShowOnMapCell;
case MWMSearchTableCellTypeSuggestion: return kTableSuggestionCell;
case MWMSearchTableCellTypeCommon: return kTableCommonCell;
}
}
@interface MWMSearchTableViewController () <UITableViewDataSource, UITableViewDelegate, MWMLocationObserver>
@interface MWMSearchTableViewController ()<UITableViewDataSource, UITableViewDelegate,
MWMSearchObserver>
@property (weak, nonatomic) IBOutlet UITableView * tableView;
@property(weak, nonatomic) IBOutlet UITableView * tableView;
@property (nonatomic) BOOL watchLocationUpdates;
@property(nonatomic) MWMSearchCommonCell * commonSizingCell;
@property (nonatomic) MWMSearchCommonCell * commonSizingCell;
@property (weak, nonatomic) id<MWMSearchTableViewProtocol> delegate;
@property(weak, nonatomic) id<MWMSearchTableViewProtocol> delegate;
@end
@implementation MWMSearchTableViewController
{
search::SearchParams searchParams;
search::Results searchResults;
}
- (nonnull instancetype)initWithDelegate:(id<MWMSearchTableViewProtocol>)delegate
{
self = [super init];
if (self)
{
self.delegate = delegate;
[self setupSearchParams];
}
_delegate = delegate;
return self;
}
- (search::SearchParams const &)searchParams
{
return searchParams;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self setupTableView];
}
- (void)viewDidDisappear:(BOOL)animated
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidDisappear:animated];
searchResults.Clear();
[super viewDidAppear:animated];
[MWMSearch addObserver:self];
}
- (void)mwm_refreshUI
- (void)viewWillDisappear:(BOOL)animated
{
[self.view mwm_refreshUI];
[super viewWillDisappear:animated];
[MWMSearch removeObserver:self];
[MWMSearch clear];
}
- (void)mwm_refreshUI { [self.view mwm_refreshUI]; }
- (void)setupTableView
{
[self.tableView registerNib:[UINib nibWithNibName:kTableShowOnMapCell bundle:nil]
@ -96,37 +81,13 @@ NSString * identifierForType(MWMSearchTableCellType type)
forCellReuseIdentifier:kTableCommonCell];
}
- (void)setupSearchParams
{
__weak auto weakSelf = self;
searchParams.m_onResults = ^(search::Results const & results)
{
__strong auto self = weakSelf;
if (!self)
return;
dispatch_async(dispatch_get_main_queue(), [=]()
{
if (!results.IsEndMarker())
{
searchResults = results;
[self updateSearchResultsInTable];
}
else if (results.IsEndedNormal())
{
[self completeSearch];
if (IPAD)
GetFramework().UpdateUserViewportChanged();
}
});
};
}
- (MWMSearchTableCellType)cellTypeForIndexPath:(NSIndexPath *)indexPath
{
size_t const numSuggests = searchResults.GetSuggestsCount();
size_t const numSuggests = [MWMSearch suggestionsCount];
if (numSuggests > 0)
{
return indexPath.row < numSuggests ? MWMSearchTableCellTypeSuggestion : MWMSearchTableCellTypeCommon;
return indexPath.row < numSuggests ? MWMSearchTableCellTypeSuggestion
: MWMSearchTableCellTypeCommon;
}
else
{
@ -142,9 +103,9 @@ NSString * identifierForType(MWMSearchTableCellType type)
{
MWMSearchTableCellType firstCellType =
[self cellTypeForIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
size_t const searchPosition =
NSUInteger const searchPosition =
indexPath.row - (firstCellType == MWMSearchTableCellTypeOnMap ? 1 : 0);
return searchResults.GetResult(searchPosition);
return [MWMSearch resultAtIndex:searchPosition];
}
#pragma mark - Layout
@ -152,33 +113,33 @@ NSString * identifierForType(MWMSearchTableCellType type)
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration
{
dispatch_async(dispatch_get_main_queue(), ^
{
[self updateSearchResultsInTable];
dispatch_async(dispatch_get_main_queue(), ^{
[self onSearchResultsUpdated];
});
}
- (void)viewWillTransitionToSize:(CGSize)size
withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context)
{
[self updateSearchResultsInTable];
}
completion:nil];
[coordinator
animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
[self onSearchResultsUpdated];
}
completion:nil];
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
MWMSearchTableCellType firstCellType = [self cellTypeForIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
NSInteger const count = searchResults.GetCount();
MWMSearchTableCellType firstCellType =
[self cellTypeForIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
BOOL const showOnMap = firstCellType == MWMSearchTableCellTypeOnMap;
return count + (showOnMap ? 1 : 0);
return [MWMSearch resultsCount] + (showOnMap ? 1 : 0);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MWMSearchTableCellType const cellType = [self cellTypeForIndexPath:indexPath];
return [tableView dequeueReusableCellWithIdentifier:identifierForType(cellType)];
@ -186,7 +147,8 @@ NSString * identifierForType(MWMSearchTableCellType type)
#pragma mark - Config cells
- (void)configSuggestionCell:(MWMSearchSuggestionCell *)cell result:(search::Result &)result
- (void)configSuggestionCell:(MWMSearchSuggestionCell *)cell
result:(search::Result &)result
isLastCell:(BOOL)isLastCell
{
[cell config:result];
@ -195,16 +157,14 @@ NSString * identifierForType(MWMSearchTableCellType type)
#pragma mark - UITableViewDelegate
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
- (CGFloat)tableView:(UITableView *)tableView
estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
switch ([self cellTypeForIndexPath:indexPath])
{
case MWMSearchTableCellTypeOnMap:
return MWMSearchShowOnMapCell.cellHeight;
case MWMSearchTableCellTypeSuggestion:
return MWMSearchSuggestionCell.cellHeight;
case MWMSearchTableCellTypeCommon:
return MWMSearchCommonCell.defaultCellHeight;
case MWMSearchTableCellTypeOnMap: return MWMSearchShowOnMapCell.cellHeight;
case MWMSearchTableCellTypeSuggestion: return MWMSearchSuggestionCell.cellHeight;
case MWMSearchTableCellTypeCommon: return MWMSearchCommonCell.defaultCellHeight;
}
}
@ -213,31 +173,29 @@ NSString * identifierForType(MWMSearchTableCellType type)
MWMSearchTableCellType const cellType = [self cellTypeForIndexPath:indexPath];
switch (cellType)
{
case MWMSearchTableCellTypeOnMap:
return MWMSearchShowOnMapCell.cellHeight;
case MWMSearchTableCellTypeSuggestion:
return MWMSearchSuggestionCell.cellHeight;
case MWMSearchTableCellTypeCommon:
[self.commonSizingCell config:[self searchResultForIndexPath:indexPath] forHeight:YES];
return self.commonSizingCell.cellHeight;
case MWMSearchTableCellTypeOnMap: return MWMSearchShowOnMapCell.cellHeight;
case MWMSearchTableCellTypeSuggestion: return MWMSearchSuggestionCell.cellHeight;
case MWMSearchTableCellTypeCommon:
[self.commonSizingCell config:[self searchResultForIndexPath:indexPath] forHeight:YES];
return self.commonSizingCell.cellHeight;
}
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView
willDisplayCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath
{
switch ([self cellTypeForIndexPath:indexPath])
{
case MWMSearchTableCellTypeOnMap:
break;
case MWMSearchTableCellTypeSuggestion:
[self configSuggestionCell:(MWMSearchSuggestionCell *)cell
result:[self searchResultForIndexPath:indexPath]
isLastCell:indexPath.row == searchResults.GetSuggestsCount() - 1];
break;
case MWMSearchTableCellTypeCommon:
[(MWMSearchCommonCell *)cell config:[self searchResultForIndexPath:indexPath] forHeight:NO];
break;
case MWMSearchTableCellTypeOnMap: break;
case MWMSearchTableCellTypeSuggestion:
[self configSuggestionCell:(MWMSearchSuggestionCell *)cell
result:[self searchResultForIndexPath:indexPath]
isLastCell:indexPath.row == [MWMSearch suggestionsCount] - 1];
break;
case MWMSearchTableCellTypeCommon:
[(MWMSearchCommonCell *)cell config:[self searchResultForIndexPath:indexPath] forHeight:NO];
break;
}
}
@ -246,6 +204,8 @@ forRowAtIndexPath:(NSIndexPath *)indexPath
MWMSearchTableCellType cellType = [self cellTypeForIndexPath:indexPath];
if (cellType == MWMSearchTableCellTypeOnMap)
{
MWMSearchTextField * textField = self.delegate.searchTextField;
[MWMSearch saveQuery:textField.text forInputLocale:textField.textInputMode.primaryLanguage];
self.delegate.state = MWMSearchManagerStateMapSearch;
}
else
@ -255,24 +215,29 @@ forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString * suggestionString = @(result.GetSuggestionString());
[Statistics logEvent:kStatEventName(kStatSearch, kStatSelectResult)
withParameters:@{kStatValue : suggestionString, kStatScreen : kStatSearch}];
withParameters:@{kStatValue : suggestionString, kStatScreen : kStatSearch}];
[self.delegate searchText:suggestionString forInputLocale:nil];
}
else
[self.delegate processSearchWithResult:result query:make_pair(searchParams.m_inputLocale, searchParams.m_query)];
{
MWMSearchTextField * textField = self.delegate.searchTextField;
[MWMSearch saveQuery:textField.text forInputLocale:textField.textInputMode.primaryLanguage];
[self.delegate processSearchWithResult:result];
}
}
}
- (void)completeSearch
#pragma mark - MWMSearchObserver
- (void)onSearchCompleted
{
self.delegate.searchTextField.isSearching = NO;
MWMSearchTableView * view = (MWMSearchTableView *)self.view;
if (searchResults.GetCount() == 0)
if ([MWMSearch resultsCount] == 0)
{
view.tableView.hidden = YES;
view.noResultsView.hidden = NO;
view.noResultsText.text = L(@"search_not_found_query");
if (self.searchOnMap)
if ([MWMSearch isSearchOnMap])
[[[ToastView alloc] initWithMessage:view.noResultsText.text] show];
}
else
@ -282,100 +247,17 @@ forRowAtIndexPath:(NSIndexPath *)indexPath
}
}
- (void)updateSearchResultsInTable
- (void)onSearchResultsUpdated
{
if (!IPAD && _searchOnMap)
if (!IPAD && [MWMSearch isSearchOnMap])
return;
self.commonSizingCell = nil;
[self.tableView reloadData];
}
#pragma mark - MWMLocationObserver
- (void)onLocationUpdate:(location::GpsInfo const &)info
{
searchParams.SetPosition(info.m_latitude, info.m_longitude);
[self updateSearchResultsInTable];
}
#pragma mark - Search
- (void)searchText:(nonnull NSString *)text forInputLocale:(nullable NSString *)locale
{
if (!text)
return;
if (locale)
searchParams.SetInputLocale(locale.UTF8String);
searchParams.m_query = text.precomposedStringWithCompatibilityMapping.UTF8String;
searchParams.SetForceSearch(true);
[self updateSearch:YES];
}
- (void)updateSearch:(BOOL)textChanged
{
Framework & f = GetFramework();
if (!searchParams.m_query.empty())
{
self.watchLocationUpdates = YES;
if (self.searchOnMap)
{
if (textChanged)
f.CancelInteractiveSearch();
f.StartInteractiveSearch(searchParams);
}
if (!_searchOnMap)
{
f.Search(searchParams);
}
else
{
if (textChanged)
{
self.delegate.searchTextField.isSearching = NO;
f.UpdateUserViewportChanged();
}
else
f.ShowSearchResults(searchResults);
}
}
else
{
self.watchLocationUpdates = NO;
f.CancelInteractiveSearch();
}
}
#pragma mark - Properties
- (void)setWatchLocationUpdates:(BOOL)watchLocationUpdates
{
if (_watchLocationUpdates == watchLocationUpdates)
return;
_watchLocationUpdates = watchLocationUpdates;
if (watchLocationUpdates)
[MWMLocationManager addObserver:self];
else
[MWMLocationManager removeObserver:self];
}
@synthesize searchOnMap = _searchOnMap;
- (void)setSearchOnMap:(BOOL)searchOnMap
{
_searchOnMap = searchOnMap;
[self updateSearch:NO];
}
- (BOOL)searchOnMap
{
return IPAD || _searchOnMap;
}
- (MWMSearchCommonCell *)commonSizingCell
{
if (!_commonSizingCell)

View file

@ -1,15 +1,5 @@
#import "CLLocation+Mercator.h"
#include "platform/location.hpp"
@protocol MWMLocationObserver <NSObject>
@optional
- (void)onHeadingUpdate:(location::CompassInfo const &)compassinfo;
- (void)onLocationUpdate:(location::GpsInfo const &)gpsInfo;
- (void)onLocationError:(location::TLocationError)locationError;
@end
#import "MWMLocationObserver.h"
@interface MWMLocationManager : NSObject
@ -29,7 +19,8 @@
- (instancetype)copy __attribute__((unavailable("call +manager instead")));
- (instancetype)copyWithZone:(NSZone *)zone __attribute__((unavailable("call +manager instead")));
+ (instancetype)alloc __attribute__((unavailable("call +manager instead")));
+ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable("call +manager instead")));
+ (instancetype)new __attribute__((unavailable("call +manager instead")));
+ (instancetype)allocWithZone:(struct _NSZone *)zone
__attribute__((unavailable("call +manager instead")));
+ (instancetype) new __attribute__((unavailable("call +manager instead")));
@end

View file

@ -19,11 +19,6 @@ namespace
using TObserver = id<MWMLocationObserver>;
using TObservers = NSHashTable<__kindof TObserver>;
void runAsyncOnMainQueue(dispatch_block_t block)
{
dispatch_async(dispatch_get_main_queue(), block);
}
location::GpsInfo gpsInfoFromLocation(CLLocation * l)
{
location::GpsInfo info;

View file

@ -0,0 +1,10 @@
#include "platform/location.hpp"
@protocol MWMLocationObserver<NSObject>
@optional
- (void)onHeadingUpdate:(location::CompassInfo const &)compassinfo;
- (void)onLocationUpdate:(location::GpsInfo const &)gpsInfo;
- (void)onLocationError:(location::TLocationError)locationError;
@end

View file

@ -0,0 +1,31 @@
#import "MWMSearchObserver.h"
#include "search/result.hpp"
@interface MWMSearch : NSObject
+ (void)addObserver:(id<MWMSearchObserver>)observer;
+ (void)removeObserver:(id<MWMSearchObserver>)observer;
+ (void)saveQuery:(NSString *)query forInputLocale:(NSString *)inputLocale;
+ (void)searchQuery:(NSString *)query forInputLocale:(NSString *)inputLocale;
+ (void)showResult:(search::Result const &)result;
+ (search::Result &)resultAtIndex:(NSUInteger)index;
+ (void)clear;
+ (BOOL)isSearchOnMap;
+ (void)setSearchOnMap:(BOOL)searchOnMap;
+ (NSUInteger)suggestionsCount;
+ (NSUInteger)resultsCount;
- (instancetype)init __attribute__((unavailable("unavailable")));
- (instancetype)copy __attribute__((unavailable("unavailable")));
- (instancetype)copyWithZone:(NSZone *)zone __attribute__((unavailable("unavailable")));
+ (instancetype)alloc __attribute__((unavailable("unavailable")));
+ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable("unavailable")));
+ (instancetype) new __attribute__((unavailable("unavailable")));
@end

View file

@ -0,0 +1,207 @@
#import "MWMSearch.h"
#import <Crashlytics/Crashlytics.h>
#import "Common.h"
#import "MWMLocationManager.h"
#include "Framework.h"
#include "search/params.hpp"
#include "search/query_saver.hpp"
namespace
{
using TObserver = id<MWMSearchObserver>;
using TObservers = NSHashTable<__kindof TObserver>;
} // namespace
@interface MWMSearch ()
@property(nonatomic) NSUInteger suggestionsCount;
@property(nonatomic) NSUInteger resultsCount;
@property(nonatomic) BOOL searchOnMap;
@property(nonatomic) BOOL textChanged;
@property(nonatomic) TObservers * observers;
@end
@implementation MWMSearch
{
search::SearchParams m_params;
search::Results m_results;
}
#pragma mark - Instance
+ (MWMSearch *)manager
{
static MWMSearch * manager;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[super alloc] initManager];
});
return manager;
}
- (instancetype)initManager
{
self = [super init];
if (self)
{
_observers = [TObservers weakObjectsHashTable];
__weak auto weakSelf = self;
m_params.m_onStarted = [weakSelf] {
__strong auto self = weakSelf;
if (!self)
return;
runAsyncOnMainQueue(^{
[self onSearchStarted];
});
};
m_params.m_onResults = [weakSelf](search::Results const & results) {
__strong auto self = weakSelf;
if (!self)
return;
runAsyncOnMainQueue(^{
if (!results.IsEndMarker())
{
self->m_results = results;
self.suggestionsCount = results.GetSuggestsCount();
self.resultsCount = results.GetCount();
[self onSearchResultsUpdated];
}
else if (results.IsEndedNormal())
{
[self onSearchCompleted];
}
});
};
}
return self;
}
#pragma mark - Add/Remove Observers
+ (void)addObserver:(id<MWMSearchObserver>)observer
{
[[MWMSearch manager].observers addObject:observer];
}
+ (void)removeObserver:(id<MWMSearchObserver>)observer
{
[[MWMSearch manager].observers removeObject:observer];
}
#pragma mark - Methods
+ (void)saveQuery:(NSString *)query forInputLocale:(NSString *)inputLocale
{
if (!query || query.length == 0)
return;
CLS_LOG(@"Save search text: %@\nInputLocale: %@", query, inputLocale);
string const locale = (!inputLocale || inputLocale.length == 0)
? [MWMSearch manager]->m_params.m_inputLocale
: inputLocale.UTF8String;
string const text = query.precomposedStringWithCompatibilityMapping.UTF8String;
GetFramework().SaveSearchQuery(make_pair(locale, text));
}
+ (void)searchQuery:(NSString *)query forInputLocale:(NSString *)inputLocale
{
if (!query)
return;
CLS_LOG(@"Search text: %@\nInputLocale: %@", query, inputLocale);
MWMSearch * manager = [MWMSearch manager];
if (inputLocale && inputLocale.length != 0)
{
string const locale = inputLocale.UTF8String;
manager->m_params.SetInputLocale(locale);
}
string const text = query.precomposedStringWithCompatibilityMapping.UTF8String;
manager->m_params.m_query = text;
manager.textChanged = YES;
[manager update];
}
+ (void)showResult:(search::Result const &)result { GetFramework().ShowSearchResult(result); }
+ (search::Result &)resultAtIndex:(NSUInteger)index
{
return [MWMSearch manager]->m_results.GetResult(index);
}
+ (void)clear
{
MWMSearch * manager = [MWMSearch manager];
manager->m_params.Clear();
manager->m_results.Clear();
manager.suggestionsCount = manager->m_results.GetSuggestsCount();
manager.resultsCount = manager->m_results.GetCount();
}
+ (BOOL)isSearchOnMap { return IPAD || [MWMSearch manager].searchOnMap; }
+ (void)setSearchOnMap:(BOOL)searchOnMap
{
MWMSearch * manager = [MWMSearch manager];
manager.searchOnMap = searchOnMap;
[manager update];
}
+ (NSUInteger)suggestionsCount { return [MWMSearch manager].suggestionsCount; }
+ (NSUInteger)resultsCount { return [MWMSearch manager].resultsCount; }
- (void)update
{
auto & f = GetFramework();
f.CancelInteractiveSearch();
[self onSearchCompleted];
if (m_params.m_query.empty())
return;
CLLocation * lastLocation = [MWMLocationManager lastLocation];
if (lastLocation)
m_params.SetPosition(lastLocation.coordinate.latitude, lastLocation.coordinate.longitude);
if (self.searchOnMap)
{
if (self.textChanged)
f.UpdateUserViewportChanged();
else
f.ShowSearchResults(m_results);
f.StartInteractiveSearch(m_params);
}
else
{
f.Search(m_params);
}
}
#pragma mark - Notifications
- (void)onSearchStarted
{
for (TObserver observer in self.observers)
{
if ([observer respondsToSelector:@selector(onSearchStarted)])
[observer onSearchStarted];
}
}
- (void)onSearchCompleted
{
for (TObserver observer in self.observers)
{
if ([observer respondsToSelector:@selector(onSearchCompleted)])
[observer onSearchCompleted];
}
if (IPAD)
GetFramework().UpdateUserViewportChanged();
}
- (void)onSearchResultsUpdated
{
for (TObserver observer in self.observers)
{
if ([observer respondsToSelector:@selector(onSearchResultsUpdated)])
[observer onSearchResultsUpdated];
}
}
@end

View file

@ -0,0 +1,8 @@
@protocol MWMSearchObserver<NSObject>
@optional
- (void)onSearchStarted;
- (void)onSearchCompleted;
- (void)onSearchResultsUpdated;
@end

View file

@ -87,6 +87,8 @@
342EE4121C43DAA7009F6A49 /* MWMAuthorizationWebViewLoginViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 342EE4101C43DAA7009F6A49 /* MWMAuthorizationWebViewLoginViewController.mm */; };
342FDDE51C6C9071000038A0 /* MWMMapDownloaderDataSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 342FDDE41C6C9071000038A0 /* MWMMapDownloaderDataSource.mm */; };
342FDDE61C6C9071000038A0 /* MWMMapDownloaderDataSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 342FDDE41C6C9071000038A0 /* MWMMapDownloaderDataSource.mm */; };
3436FE821D366CDD005CD87B /* MWMSearch.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3436FE811D366CDD005CD87B /* MWMSearch.mm */; };
3436FE831D366CDD005CD87B /* MWMSearch.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3436FE811D366CDD005CD87B /* MWMSearch.mm */; };
3438CDF41B85F1170051AA78 /* MWMConsole.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3438CDF31B85F1170051AA78 /* MWMConsole.mm */; };
3438CDF81B8616760051AA78 /* MWMSearchShowOnMapCell.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3438CDF61B8616760051AA78 /* MWMSearchShowOnMapCell.mm */; };
3438CDF91B8616760051AA78 /* MWMSearchShowOnMapCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3438CDF71B8616760051AA78 /* MWMSearchShowOnMapCell.xib */; };
@ -968,6 +970,8 @@
3434D7801BD12B2000C77E44 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
3434D7811BD12B2000C77E44 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = "<group>"; };
3434D7821BD12B2000C77E44 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/InfoPlist.strings; sourceTree = "<group>"; };
3436FE801D366CDD005CD87B /* MWMSearch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMSearch.h; sourceTree = "<group>"; };
3436FE811D366CDD005CD87B /* MWMSearch.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMSearch.mm; sourceTree = "<group>"; };
3438CDF21B85F1170051AA78 /* MWMConsole.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMConsole.h; sourceTree = "<group>"; };
3438CDF31B85F1170051AA78 /* MWMConsole.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMConsole.mm; sourceTree = "<group>"; };
3438CDF51B8616760051AA78 /* MWMSearchShowOnMapCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMSearchShowOnMapCell.h; sourceTree = "<group>"; };
@ -1022,6 +1026,8 @@
347BAC681B733D540010FF78 /* MWMPedestrianShareAlert.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MWMPedestrianShareAlert.xib; sourceTree = "<group>"; };
347BAC6C1B736BA70010FF78 /* MWMSharePedestrianRoutesToastActivityItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMSharePedestrianRoutesToastActivityItem.h; sourceTree = "<group>"; };
347BAC6D1B736BA70010FF78 /* MWMSharePedestrianRoutesToastActivityItem.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMSharePedestrianRoutesToastActivityItem.mm; sourceTree = "<group>"; };
347D5CA11D376B9F00FA28DD /* MWMSearchObserver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MWMSearchObserver.h; sourceTree = "<group>"; };
347D5CA21D376C2C00FA28DD /* MWMLocationObserver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MWMLocationObserver.h; sourceTree = "<group>"; };
347D7C671C2C0703006B2D0A /* UITextView+RuntimeAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UITextView+RuntimeAttributes.h"; sourceTree = "<group>"; };
347D7C681C2C0703006B2D0A /* UITextView+RuntimeAttributes.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "UITextView+RuntimeAttributes.mm"; sourceTree = "<group>"; };
347FD84A1C60B2CE002FB65E /* MWMOpeningHoursAddClosedTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMOpeningHoursAddClosedTableViewCell.h; sourceTree = "<group>"; };
@ -1053,7 +1059,7 @@
347FDDA01BB59B4E00871410 /* Mapsme.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Mapsme.storyboard; sourceTree = "<group>"; };
348320CC1B6A2C52007EC039 /* MWMNavigationViewProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MWMNavigationViewProtocol.h; sourceTree = "<group>"; };
3485C00F1B85C20E00F7712D /* MWMSearchTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMSearchTableViewController.h; sourceTree = "<group>"; };
3485C0101B85C20E00F7712D /* MWMSearchTableViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMSearchTableViewController.mm; sourceTree = "<group>"; };
3485C0101B85C20E00F7712D /* MWMSearchTableViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = MWMSearchTableViewController.mm; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
3485C0111B85C20E00F7712D /* MWMSearchTableViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MWMSearchTableViewController.xib; sourceTree = "<group>"; };
348D1DF91C525B8300860465 /* MWMTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MWMTypes.h; sourceTree = "<group>"; };
348E57981B0F49D8000FA02A /* maps.me dbg.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "maps.me dbg.app"; sourceTree = BUILT_PRODUCTS_DIR; };
@ -1186,7 +1192,7 @@
34CE8A651C7740E100F4351A /* MWMStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMStorage.h; sourceTree = "<group>"; };
34CE8A661C7740E100F4351A /* MWMStorage.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMStorage.mm; sourceTree = "<group>"; };
34CFFE891B7DE6FD009D0C9F /* MWMSearchManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMSearchManager.h; sourceTree = "<group>"; };
34CFFE8A1B7DE6FD009D0C9F /* MWMSearchManager.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMSearchManager.mm; sourceTree = "<group>"; };
34CFFE8A1B7DE6FD009D0C9F /* MWMSearchManager.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = MWMSearchManager.mm; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
34CFFE8C1B7DE71C009D0C9F /* MWMSearchView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MWMSearchView.xib; sourceTree = "<group>"; };
34CFFE8E1B7DE83D009D0C9F /* MWMSearchView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMSearchView.h; sourceTree = "<group>"; };
34CFFE8F1B7DE83D009D0C9F /* MWMSearchView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMSearchView.mm; sourceTree = "<group>"; };
@ -1725,6 +1731,7 @@
080E96DDFE201D6D7F000001 /* Classes */ = {
isa = PBXGroup;
children = (
3436FE7F1D366CA0005CD87B /* Search */,
344D77B11D1BD79700DBED70 /* Location */,
34002A651D2F9C8100AC201E /* Routing */,
34479C741C60C6130065D261 /* Framework */,
@ -2009,6 +2016,16 @@
path = MapDownloader;
sourceTree = "<group>";
};
3436FE7F1D366CA0005CD87B /* Search */ = {
isa = PBXGroup;
children = (
3436FE801D366CDD005CD87B /* MWMSearch.h */,
3436FE811D366CDD005CD87B /* MWMSearch.mm */,
347D5CA11D376B9F00FA28DD /* MWMSearchObserver.h */,
);
path = Search;
sourceTree = "<group>";
};
3438CDF11B85F0C30051AA78 /* Console */ = {
isa = PBXGroup;
children = (
@ -2038,6 +2055,7 @@
344D77B21D1BD7C800DBED70 /* MWMLocationManager.h */,
344D77B31D1BD7C800DBED70 /* MWMLocationManager.mm */,
34FED5521D2123CE00183B1B /* MWMLocationHelpers.h */,
347D5CA21D376C2C00FA28DD /* MWMLocationObserver.h */,
);
path = Location;
sourceTree = "<group>";
@ -3703,6 +3721,7 @@
F64F4B741B4A45FD0081A24A /* MWMDownloaderDialogHeader.mm in Sources */,
34F8ADD91B97229A004184CC /* MWMSearchTableView.mm in Sources */,
F653CE1C1C7361DA00A453F1 /* MWMObjectsCategorySelectorController.mm in Sources */,
3436FE821D366CDD005CD87B /* MWMSearch.mm in Sources */,
B08AA8DA1A26299A00810B1C /* TimeUtils.mm in Sources */,
F6CB216D1AF13EBD00FB8963 /* MWMPlacePageBookmarkCell.mm in Sources */,
F653D4231AE9398700282659 /* MWMPlacePageViewManager.mm in Sources */,
@ -3928,6 +3947,7 @@
6741A9E11BF340DE002C974C /* MWMSearchTableView.mm in Sources */,
6741A9E31BF340DE002C974C /* TimeUtils.mm in Sources */,
341F99EE1C6B28A7001C67B8 /* MWMMapDownloaderExtendedDataSource.mm in Sources */,
3436FE831D366CDD005CD87B /* MWMSearch.mm in Sources */,
6741A9E41BF340DE002C974C /* MWMPlacePageBookmarkCell.mm in Sources */,
6741A9E51BF340DE002C974C /* MWMPlacePageViewManager.mm in Sources */,
6741A9E61BF340DE002C974C /* MWMPlacePage+Animation.mm in Sources */,