From f9e8c97c6fb55926ff906e0320cf68c618dc02a3 Mon Sep 17 00:00:00 2001 From: Ilya Grechuhin Date: Wed, 16 Mar 2016 12:27:55 +0300 Subject: [PATCH] [ios] Fixed downloader states update. --- .../MWMMapDownloaderDefaultDataSource.mm | 90 +++++++++---------- .../MWMMapDownloaderExtendedDataSource.mm | 72 +++++++-------- .../MWMBaseMapDownloaderViewController.mm | 46 ++++++---- 3 files changed, 112 insertions(+), 96 deletions(-) diff --git a/iphone/Maps/Classes/MapDownloader/DataSources/MWMMapDownloaderDefaultDataSource.mm b/iphone/Maps/Classes/MapDownloader/DataSources/MWMMapDownloaderDefaultDataSource.mm index 52ee677dcc..d2b800c8f0 100644 --- a/iphone/Maps/Classes/MapDownloader/DataSources/MWMMapDownloaderDefaultDataSource.mm +++ b/iphone/Maps/Classes/MapDownloader/DataSources/MWMMapDownloaderDefaultDataSource.mm @@ -12,10 +12,12 @@ extern NSString * const kLargeCountryCellIdentifier; namespace { + auto compareStrings = ^NSComparisonResult(NSString * s1, NSString * s2) { return [s1 compare:s2 options:NSCaseInsensitiveSearch range:{0, s1.length} locale:[NSLocale currentLocale]]; }; + auto compareLocalNames = ^NSComparisonResult(NSString * s1, NSString * s2) { auto const & s = GetFramework().Storage(); @@ -30,11 +32,11 @@ using namespace storage; @interface MWMMapDownloaderDefaultDataSource () @property (copy, nonatomic) NSArray * indexes; -@property (copy, nonatomic) NSDictionary *> * countryIds; +@property (copy, nonatomic) NSDictionary *> * availableCountries; -@property (copy, nonatomic) NSArray * downloadedCoutryIds; -@property (nonatomic, readwrite) NSInteger downloadedCountrySection; -@property (nonatomic, readonly) NSInteger countrySectionsShift; +@property (copy, nonatomic) NSArray * downloadedCountries; +@property (nonatomic, readonly) NSInteger downloadedSection; +@property (nonatomic, readonly) NSInteger downloadedSectionShift; @property (nonatomic, readwrite) BOOL needFullReload; @@ -73,28 +75,31 @@ using namespace storage; - (void)reload { // Get old data for comparison. - NSDictionary *> * countryIds = [self.countryIds copy]; - BOOL const hadDownloadedCountries = self.haveDownloadedCountries; + NSDictionary *> * availableCountriesBeforeUpdate = [self.availableCountries copy]; + NSInteger const downloadedCountriesCountBeforeUpdate = self.downloadedCountries.count; // Load updated data. [self load]; // Compare new data vs old data to understand what kind of reload is required and what sections need reload. - self.needFullReload = (hadDownloadedCountries != self.haveDownloadedCountries || countryIds.count == 0); + NSInteger const downloadedCountriesCountAfterUpdate = self.downloadedCountries.count; + self.needFullReload = + (downloadedCountriesCountBeforeUpdate == 0 || downloadedCountriesCountAfterUpdate == 0 || + availableCountriesBeforeUpdate.count == 0); if (self.needFullReload) return; - if (self.haveDownloadedCountries) - m_reloadSections.push_back(self.downloadedCountrySection); - [countryIds enumerateKeysAndObjectsUsingBlock:^(NSString * key, NSArray * obj, BOOL * stop) + if (downloadedCountriesCountBeforeUpdate != downloadedCountriesCountAfterUpdate) + m_reloadSections.push_back(self.downloadedSection); + [availableCountriesBeforeUpdate enumerateKeysAndObjectsUsingBlock:^(NSString * key, NSArray * obj, BOOL * stop) { - NSArray * sectionCountries = self.countryIds[key]; + NSArray * sectionCountries = self.availableCountries[key]; if (!sectionCountries) { self.needFullReload = YES; *stop = YES; } - if (![obj isEqualToArray:sectionCountries]) - self->m_reloadSections.push_back([self.indexes indexOfObject:key] + self.countrySectionsShift); + if (obj.count != sectionCountries.count) + self->m_reloadSections.push_back([self.indexes indexOfObject:key] + self.downloadedSectionShift); }]; } @@ -106,7 +111,7 @@ using namespace storage; - (void)configAvailableSections:(TCountriesVec const &)availableChildren { NSMutableSet * indexSet = [NSMutableSet setWithCapacity:availableChildren.size()]; - NSMutableDictionary *> * countryIds = [@{} mutableCopy]; + NSMutableDictionary *> * availableCountries = [@{} mutableCopy]; BOOL const isParentRoot = self.isParentRoot; auto const & s = GetFramework().Storage(); for (auto const & countryId : availableChildren) @@ -116,47 +121,40 @@ using namespace storage; NSString * index = isParentRoot ? [@(localName.c_str()) substringToIndex:1].capitalizedString : L(@"downloader_available_maps"); [indexSet addObject:index]; - NSMutableArray * letterIds = [countryIds[index] mutableCopy]; + NSMutableArray * letterIds = [availableCountries[index] mutableCopy]; letterIds = letterIds ? letterIds : [@[] mutableCopy]; [letterIds addObject:nsCountryId]; - countryIds[index] = [letterIds copy]; + availableCountries[index] = [letterIds copy]; } self.indexes = [[indexSet allObjects] sortedArrayUsingComparator:compareStrings]; - [countryIds enumerateKeysAndObjectsUsingBlock:^(NSString * key, NSArray * obj, BOOL * stop) + [availableCountries enumerateKeysAndObjectsUsingBlock:^(NSString * key, NSArray * obj, BOOL * stop) { - countryIds[key] = [obj sortedArrayUsingComparator:compareLocalNames]; + availableCountries[key] = [obj sortedArrayUsingComparator:compareLocalNames]; }]; - self.countryIds = countryIds; + self.availableCountries = availableCountries; } - (void)configDownloadedSection:(TCountriesVec const &)downloadedChildren { - self.downloadedCoutryIds = nil; - self.downloadedCountrySection = NSNotFound; - NSMutableArray * nsDownloadedCoutryIds = [@[] mutableCopy]; + NSMutableArray * downloadedCountries = [@[] mutableCopy]; for (auto const & countryId : downloadedChildren) - [nsDownloadedCoutryIds addObject:@(countryId.c_str())]; - [nsDownloadedCoutryIds sortUsingComparator:compareLocalNames]; - if (nsDownloadedCoutryIds.count != 0) - { - self.downloadedCoutryIds = nsDownloadedCoutryIds; - self.downloadedCountrySection = 0; - } + [downloadedCountries addObject:@(countryId.c_str())]; + self.downloadedCountries = [downloadedCountries sortedArrayUsingComparator:compareLocalNames]; } #pragma mark - UITableViewDataSource - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return self.indexes.count + self.countrySectionsShift; + return self.indexes.count + self.downloadedSectionShift; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - if (section == self.downloadedCountrySection) - return self.downloadedCoutryIds.count; - NSString * index = self.indexes[section - self.countrySectionsShift]; - return self.countryIds[index].count; + if (section == self.downloadedSection) + return self.downloadedCountries.count; + NSString * index = self.indexes[section - self.downloadedSectionShift]; + return self.availableCountries[index].count; } - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView @@ -166,12 +164,12 @@ using namespace storage; - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { - return index + self.countrySectionsShift; + return index + self.downloadedSectionShift; } - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { - if (section == self.downloadedCountrySection) + if (section == self.downloadedSection) { NodeAttrs nodeAttrs; GetFramework().Storage().GetNodeAttrs(m_parentId, nodeAttrs); @@ -180,7 +178,7 @@ using namespace storage; else return [NSString stringWithFormat:@"%@ (%@)", L(@"downloader_dowloaded_subtitle"), formattedSize(nodeAttrs.m_localMwmSize)]; } - return self.indexes[section - self.countrySectionsShift]; + return self.indexes[section - self.downloadedSectionShift]; } - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section @@ -207,11 +205,11 @@ using namespace storage; { NSInteger const section = indexPath.section; NSInteger const row = indexPath.row; - if (section == self.downloadedCountrySection) - return self.downloadedCoutryIds[row].UTF8String; - NSString * index = self.indexes[section - self.countrySectionsShift]; - NSArray * countryIds = self.countryIds[index]; - NSString * nsCountryId = countryIds[indexPath.row]; + if (section == self.downloadedSection) + return self.downloadedCountries[row].UTF8String; + NSString * index = self.indexes[section - self.downloadedSectionShift]; + NSArray * availableCountries = self.availableCountries[index]; + NSString * nsCountryId = availableCountries[indexPath.row]; return nsCountryId.UTF8String; } @@ -228,14 +226,14 @@ using namespace storage; #pragma mark - Properties -- (NSInteger)countrySectionsShift +- (NSInteger)downloadedSectionShift { - return (self.haveDownloadedCountries ? self.downloadedCountrySection + 1 : 0); + return (self.downloadedCountries.count != 0 ? self.downloadedSection + 1 : 0); } -- (BOOL)haveDownloadedCountries +- (NSInteger)downloadedSection { - return (self.downloadedCountrySection != NSNotFound); + return self.downloadedCountries.count != 0 ? 0 : NSNotFound; } - (void)setNeedFullReload:(BOOL)needFullReload diff --git a/iphone/Maps/Classes/MapDownloader/DataSources/MWMMapDownloaderExtendedDataSource.mm b/iphone/Maps/Classes/MapDownloader/DataSources/MWMMapDownloaderExtendedDataSource.mm index 80266a87f4..65bd93f63b 100644 --- a/iphone/Maps/Classes/MapDownloader/DataSources/MWMMapDownloaderExtendedDataSource.mm +++ b/iphone/Maps/Classes/MapDownloader/DataSources/MWMMapDownloaderExtendedDataSource.mm @@ -17,12 +17,12 @@ using namespace storage; @interface MWMMapDownloaderExtendedDataSource () -@property (copy, nonatomic) NSArray * closestCoutryIds; +@property (copy, nonatomic) NSArray * nearmeCountries; -@property (nonatomic) NSInteger closestCountriesSection; -@property (nonatomic, readonly) NSInteger closestCountriesSectionShift; +@property (nonatomic, readonly) NSInteger nearmeSection; +@property (nonatomic, readonly) NSInteger nearmeSectionShift; -@property (nonatomic) BOOL needReloadClosestCountriesSection; +@property (nonatomic) BOOL needReloadNearmeSection; @end @@ -31,12 +31,16 @@ using namespace storage; - (std::vector)getReloadSections { std::vector sections = [super getReloadSections]; - if (!self.haveClosestCountries) + if (self.nearmeCountries.count == 0) return sections; for (auto & section : sections) - section += self.closestCountriesSectionShift; - if (self.needReloadClosestCountriesSection) - sections.push_back(self.closestCountriesSection); + section += self.nearmeSectionShift; + if (self.needReloadNearmeSection) + { + NSInteger const nearmeSection = self.nearmeSection; + NSAssert(nearmeSection != NSNotFound, @"Invalid nearme section."); + sections.push_back(nearmeSection); + } return sections; } @@ -48,64 +52,62 @@ using namespace storage; - (void)reload { - NSSet * closestCoutryIds = [NSSet setWithArray:self.closestCoutryIds]; + NSInteger const closestCoutriesCountBeforeUpdate = self.nearmeCountries.count; + [super reload]; - self.needReloadClosestCountriesSection = - ![closestCoutryIds isEqualToSet:[NSSet setWithArray:self.closestCoutryIds]]; - self.needFullReload |= self.needReloadClosestCountriesSection && self.closestCoutryIds.count == 0; + NSInteger const closestCoutriesCountAfterUpdate = self.nearmeCountries.count; + if (closestCoutriesCountBeforeUpdate == 0 || closestCoutriesCountAfterUpdate == 0) + self.needFullReload = YES; + if (self.needFullReload) + return; + self.needReloadNearmeSection = (closestCoutriesCountBeforeUpdate != closestCoutriesCountAfterUpdate); } - (void)configNearMeSection { - self.closestCoutryIds = nil; - self.closestCountriesSection = NSNotFound; LocationManager * lm = MapsAppDelegate.theApp.m_locationManager; if (!lm.lastLocationIsValid) return; auto & countryInfoGetter = GetFramework().CountryInfoGetter(); TCountriesVec closestCoutryIds; countryInfoGetter.GetRegionsCountryId(lm.lastLocation.mercator, closestCoutryIds); - NSMutableArray * nsClosestCoutryIds = [@[] mutableCopy]; + NSMutableArray * nearmeCountries = [@[] mutableCopy]; auto const & s = GetFramework().Storage(); for (auto const & countryId : closestCoutryIds) { NodeStatuses nodeStatuses{}; s.GetNodeStatuses(countryId, nodeStatuses); if (nodeStatuses.m_status == NodeStatus::NotDownloaded) - [nsClosestCoutryIds addObject:@(countryId.c_str())]; - } - if (nsClosestCoutryIds.count != 0) - { - self.closestCoutryIds = nsClosestCoutryIds; - self.closestCountriesSection = 0; + [nearmeCountries addObject:@(countryId.c_str())]; } + self.nearmeCountries = [nearmeCountries copy]; } #pragma mark - UITableViewDataSource - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return [super numberOfSectionsInTableView:tableView] + self.closestCountriesSectionShift; + return [super numberOfSectionsInTableView:tableView] + self.nearmeSectionShift; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - if (section == self.closestCountriesSection) - return self.closestCoutryIds.count; - return [super tableView:tableView numberOfRowsInSection:section - self.closestCountriesSectionShift]; + if (section == self.nearmeSection) + return self.nearmeCountries.count; + return [super tableView:tableView numberOfRowsInSection:section - self.nearmeSectionShift]; } - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { - return [super tableView:tableView sectionForSectionIndexTitle:title atIndex:index] + self.closestCountriesSectionShift; + return [super tableView:tableView sectionForSectionIndexTitle:title atIndex:index] + self.nearmeSectionShift; } - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { - if (section == self.closestCountriesSection) + if (section == self.nearmeSection) return L(@"downloader_near_me_subtitle"); - return [super tableView:tableView titleForHeaderInSection:section - self.closestCountriesSectionShift]; + return [super tableView:tableView titleForHeaderInSection:section - self.nearmeSectionShift]; } #pragma mark - MWMMapDownloaderDataSource @@ -114,21 +116,21 @@ using namespace storage; { NSInteger const row = indexPath.row; NSInteger const section = indexPath.section; - if (section == self.closestCountriesSection) - return self.closestCoutryIds[row].UTF8String; - return [super countryIdForIndexPath:[NSIndexPath indexPathForRow:row inSection:section - self.closestCountriesSectionShift]]; + if (section == self.nearmeSection) + return self.nearmeCountries[row].UTF8String; + return [super countryIdForIndexPath:[NSIndexPath indexPathForRow:row inSection:section - self.nearmeSectionShift]]; } #pragma mark - Properties -- (NSInteger)closestCountriesSectionShift +- (NSInteger)nearmeSectionShift { - return (self.haveClosestCountries ? self.closestCountriesSection + 1 : 0); + return (self.nearmeCountries.count != 0 ? self.nearmeSection + 1 : 0); } -- (BOOL)haveClosestCountries +- (NSInteger)nearmeSection { - return (self.closestCountriesSection != NSNotFound); + return self.nearmeCountries.count != 0 ? 0 : NSNotFound; } @end diff --git a/iphone/Maps/Classes/MapDownloader/MWMBaseMapDownloaderViewController.mm b/iphone/Maps/Classes/MapDownloader/MWMBaseMapDownloaderViewController.mm index d7c3dc08b5..e2174af26f 100644 --- a/iphone/Maps/Classes/MapDownloader/MWMBaseMapDownloaderViewController.mm +++ b/iphone/Maps/Classes/MapDownloader/MWMBaseMapDownloaderViewController.mm @@ -88,6 +88,7 @@ using namespace storage; [navBar setBackgroundImage:self.navBarBackground forBarMetrics:UIBarMetricsDefault]; navBar.shadowImage = self.navBarShadow; [MWMFrameworkListener removeObserver:self]; + [self notifyParentController]; } - (void)configNavBar @@ -100,25 +101,30 @@ using namespace storage; [self.cellHeightCache removeAllObjects]; } +- (void)notifyParentController +{ + NSArray * viewControllers = [self.navigationController viewControllers]; + BOOL const goingTreeDeeper = ([viewControllers indexOfObject:self] != NSNotFound); + if (goingTreeDeeper) + return; + MWMViewController * parentVC = viewControllers.lastObject; + if ([parentVC isKindOfClass:[MWMBaseMapDownloaderViewController class]]) + [static_cast(parentVC) processCountryEvent:self.parentCountryId]; +} + #pragma mark - MWMFrameworkStorageObserver - (void)processCountryEvent:(TCountryId const &)countryId { if (self.skipCountryEventProcessing) return; - auto notifyParentController = ^ - { - NSArray * viewControllers = [self.navigationController viewControllers]; - NSInteger const selfIndex = [viewControllers indexOfObject:self]; - if (selfIndex < 1) - return; - MWMViewController * parentVC = viewControllers[selfIndex - 1]; - if ([parentVC isKindOfClass:[MWMBaseMapDownloaderViewController class]]) - [static_cast(parentVC) processCountryEvent:countryId]; - }; auto process = ^ { [self configAllMapsView]; + + for (MWMMapDownloaderTableViewCell * cell in self.tableView.visibleCells) + [cell processCountryEvent:countryId]; + MWMMapDownloaderDefaultDataSource * dataSource = self.defaultDataSource; [dataSource reload]; if (![self.dataSource isEqual:dataSource]) @@ -138,8 +144,6 @@ using namespace storage; for (auto & section : sections) [indexSet addIndex:section]; [tv reloadSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic]; - - notifyParentController(); }; if (countryId == self.parentCountryId) @@ -153,9 +157,6 @@ using namespace storage; if (find(childrenId.cbegin(), childrenId.cend(), countryId) != childrenId.cend()) process(); } - - for (MWMMapDownloaderTableViewCell * cell in self.tableView.visibleCells) - [cell processCountryEvent:countryId]; } - (void)processCountry:(TCountryId const &)countryId progress:(TLocalAndRemoteSize const &)progress @@ -470,7 +471,10 @@ using namespace storage; kStatFrom : kStatDownloader, kStatScenario : kStatDownload }]; + self.skipCountryEventProcessing = YES; [MWMStorage downloadNode:countryId alertController:self.alertController onSuccess:nil]; + self.skipCountryEventProcessing = NO; + [self processCountryEvent:self.parentCountryId]; } - (void)retryDownloadNode:(storage::TCountryId const &)countryId @@ -482,7 +486,10 @@ using namespace storage; kStatFrom : kStatDownloader, kStatScenario : kStatDownload }]; + self.skipCountryEventProcessing = YES; [MWMStorage retryDownloadNode:countryId]; + self.skipCountryEventProcessing = NO; + [self processCountryEvent:self.parentCountryId]; } - (void)updateNode:(storage::TCountryId const &)countryId @@ -494,7 +501,10 @@ using namespace storage; kStatFrom : kStatDownloader, kStatScenario : kStatUpdate }]; + self.skipCountryEventProcessing = YES; [MWMStorage updateNode:countryId alertController:self.alertController]; + self.skipCountryEventProcessing = NO; + [self processCountryEvent:self.parentCountryId]; } - (void)deleteNode:(storage::TCountryId const &)countryId @@ -506,13 +516,19 @@ using namespace storage; kStatFrom : kStatDownloader, kStatScenario : kStatDelete }]; + self.skipCountryEventProcessing = YES; [MWMStorage deleteNode:countryId alertController:self.alertController]; + self.skipCountryEventProcessing = NO; + [self processCountryEvent:self.parentCountryId]; } - (void)cancelNode:(storage::TCountryId const &)countryId { [Statistics logEvent:kStatDownloaderDownloadCancel withParameters:@{kStatFrom : kStatDownloader}]; + self.skipCountryEventProcessing = YES; [MWMStorage cancelDownloadNode:countryId]; + self.skipCountryEventProcessing = NO; + [self processCountryEvent:self.parentCountryId]; } - (void)showNode:(storage::TCountryId const &)countryId