[ios] Move SloynikEngine startup to a separate thread.

This commit is contained in:
Yury Melnichek 2011-04-15 19:10:15 +02:00 committed by Alex Zolotarev
parent 258b69e25f
commit 66c6a2e493
8 changed files with 119 additions and 34 deletions

View file

@ -11,8 +11,14 @@
@interface GuideViewController : SearchVC
{
UIActivityIndicatorView * activityIndicator;
UILabel * loadingLabel;
}
@property (nonatomic, retain) UIActivityIndicatorView * activityIndicator;
@property (nonatomic, retain) UILabel * loadingLabel;
- (IBAction)OnMapClicked:(id)sender;
- (void)OnSloynikEngineInitialized;
@end

View file

@ -10,9 +10,12 @@
#import "MapsAppDelegate.h"
#import "MapViewController.h"
#import "ArticleVC.h"
#include "global.hpp"
@implementation GuideViewController
@synthesize activityIndicator;
@synthesize loadingLabel;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
@ -89,6 +92,32 @@
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
if (!GetSloynikEngine())
{
CGRect frame = self.view.frame;
self.activityIndicator = [[[UIActivityIndicatorView alloc]
initWithFrame:CGRectMake(frame.origin.x + frame.size.width / 2 - 15,
80, 30, 30)] autorelease];
[self.activityIndicator setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleGray];
[self.view addSubview:self.activityIndicator];
self.loadingLabel = [[[UILabel alloc]
initWithFrame:CGRectMake(frame.origin.x + frame.size.width / 2 - 30,
110, 60, 30)] autorelease];
self.loadingLabel.text = @"Indexing...";
self.loadingLabel.textAlignment = UITextAlignmentCenter;
self.loadingLabel.userInteractionEnabled = NO;
self.loadingLabel.numberOfLines = 1;
self.loadingLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
self.loadingLabel.adjustsFontSizeToFitWidth = YES;
[self.view addSubview:self.loadingLabel];
self.searchBar.hidden = YES;
self.resultsView.hidden = YES;
[self.activityIndicator startAnimating];
}
}
- (void)viewDidUnload
@ -104,4 +133,17 @@
return YES;
}
- (void)OnSloynikEngineInitialized
{
if (self.activityIndicator)
{
[self.activityIndicator removeFromSuperview];
[self.loadingLabel removeFromSuperview];
self.activityIndicator = nil;
self.searchBar.hidden = NO;
self.resultsView.hidden = NO;
[self.resultsView reloadData];
}
}
@end

View file

@ -20,5 +20,6 @@
- (GuideViewController *)guideViewController;
- (SettingsManager *)settingsManager;
- (void)onSloynikEngineInitialized:(void *)pEngine;
@end

View file

@ -30,11 +30,24 @@
[mapViewController OnEnterForeground];
}
- (void) onSloynikEngineInitialized: (void *) pEngine
{
SetSloynikEngine(static_cast<sl::SloynikEngine *>(pEngine));
if (m_guideViewController)
[m_guideViewController OnSloynikEngineInitialized];
}
- (void) applicationDidFinishLaunching: (UIApplication *) application
{
// Initialize Sloynik engine.
// It takes long for the first time, so we do it while startup image is visible.
GetSloynikEngine();
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
sl::SloynikEngine * pEngine = CreateSloynikEngine();
dispatch_async(dispatch_get_main_queue(), ^{
[[MapsAppDelegate theApp] onSloynikEngineInitialized:pEngine];
});
});
// Add the tab bar controller's current view as a subview of the window
[window addSubview:mapViewController.view];

View file

@ -60,7 +60,6 @@ struct SloynikData
self.resultsView.delegate = self;
m_pSloynikData = new SloynikData;
GetSloynikEngine()->Search("", m_pSloynikData->m_SearchResult);
[self onEmptySearch];
}
@ -86,11 +85,15 @@ struct SloynikData
ASSERT_EQUAL(self.searchBar, sender, ());
if ([searchText length] != 0)
{
sl::SloynikEngine * const pEngine = GetSloynikEngine();
ASSERT(pEngine, ());
if (!pEngine)
return;
self.resultsView.hidden = NO;
GetSloynikEngine()->Search([searchText UTF8String], m_pSloynikData->m_SearchResult);
pEngine->Search([searchText UTF8String], m_pSloynikData->m_SearchResult);
sl::SloynikEngine::WordId row = m_pSloynikData->m_SearchResult.m_FirstMatched;
ASSERT_LESS_OR_EQUAL(row, GetSloynikEngine()->WordCount(), ());
row = min(row, GetSloynikEngine()->WordCount() - 1);
ASSERT_LESS_OR_EQUAL(row, pEngine->WordCount(), ());
row = min(row, pEngine->WordCount() - 1);
[self.resultsView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:row inSection:0]
atScrollPosition:UITableViewScrollPositionTop
animated:NO];
@ -117,8 +120,11 @@ struct SloynikData
ASSERT_EQUAL(self.resultsView, tableView, ());
if (section != 0)
return 0;
sl::SloynikEngine * const pEngine = GetSloynikEngine();
if (!pEngine)
return 0;
int const rowsInView = self.resultsView.bounds.size.height / max(1.f, self.resultsView.rowHeight);
return GetSloynikEngine()->WordCount() + max(1, rowsInView - 1);
return pEngine->WordCount() + max(1, rowsInView - 1);
}
- (UITableViewCell *)tableView:(UITableView *)tableView
@ -132,10 +138,12 @@ struct SloynikData
autorelease];
}
sl::SloynikEngine::WordId const wordId = indexPath.row;
if (wordId < GetSloynikEngine()->WordCount())
sl::SloynikEngine * const pEngine = GetSloynikEngine();
ASSERT(pEngine, ());
if (pEngine && wordId < pEngine->WordCount())
{
sl::SloynikEngine::WordInfo wordInfo;
GetSloynikEngine()->GetWordInfo(wordId, wordInfo);
pEngine->GetWordInfo(wordId, wordInfo);
cell.textLabel.text = [NSString stringWithUTF8String:wordInfo.m_Word.c_str()];
}
else
@ -149,7 +157,8 @@ struct SloynikData
- (NSIndexPath *)tableView:(UITableView *)tableView
willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row < GetSloynikEngine()->WordCount())
sl::SloynikEngine * const pEngine = GetSloynikEngine();
if (pEngine && indexPath.row < pEngine->WordCount())
return indexPath;
else
return nil;
@ -158,7 +167,8 @@ struct SloynikData
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
sl::SloynikEngine::WordId const wordId = indexPath.row;
if (wordId < GetSloynikEngine()->WordCount())
sl::SloynikEngine * const pEngine = GetSloynikEngine();
if (pEngine && wordId < pEngine->WordCount())
{
[self willShowArticleVC:articleVC];
[articleVC setArticleById:wordId];

View file

@ -14,4 +14,6 @@ namespace sl
class SloynikEngine;
}
sl::SloynikEngine * CreateSloynikEngine();
sl::SloynikEngine * GetSloynikEngine();
void SetSloynikEngine(sl::SloynikEngine *);

View file

@ -7,9 +7,10 @@
//
#include "global.hpp"
#import "PerfCount.h"
#include "../../words/sloynik_engine.hpp"
#include "../../base/assert.hpp"
#include "../../base/logging.hpp"
#import <UIKit/UIKit.h>
sl::StrFn::Str const * StrCreateApple(char const * utf8Str, uint32_t size)
{
@ -47,29 +48,38 @@ int StrSecondaryCompareApple(void *, sl::StrFn::Str const * a, sl::StrFn::Str co
kCFCompareLocalized, NULL);
}
sl::SloynikEngine * g_pEngine = NULL;
sl::SloynikEngine * GetSloynikEngine()
{
static sl::SloynikEngine * s_pEngine = NULL;
if (!s_pEngine)
{
LogTimeCounter("EngineStartUp", "Starting engine.");
NSBundle * bundle = [NSBundle mainBundle];
string const dictionaryPath = [[bundle pathForResource:@"dictionary" ofType:@"slf"] UTF8String];
string const indexPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
NSUserDomainMask,
YES)
objectAtIndex:0]
UTF8String] + string("/index");
sl::StrFn strFn;
strFn.Create = StrCreateApple;
strFn.Destroy = StrDestroyApple;
strFn.PrimaryCompare = StrPrimaryCompareApple;
strFn.SecondaryCompare = StrSecondaryCompareApple;
strFn.m_pData = NULL;
strFn.m_PrimaryCompareId = 1;
strFn.m_SecondaryCompareId = 2;
s_pEngine = new sl::SloynikEngine(dictionaryPath, indexPath, strFn);
LogTimeCounter("EngineStartUp", "Engine started.");
}
return s_pEngine;
return g_pEngine;
}
void SetSloynikEngine(sl::SloynikEngine * pEngine)
{
g_pEngine = pEngine;
}
sl::SloynikEngine * CreateSloynikEngine()
{
ASSERT(!g_pEngine, ());
LOG(LINFO, ("Starting sloynik engine."));
NSBundle * bundle = [NSBundle mainBundle];
string const dictionaryPath = [[bundle pathForResource:@"dictionary" ofType:@"slf"] UTF8String];
string const indexPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
NSUserDomainMask,
YES)
objectAtIndex:0]
UTF8String] + string("/index");
sl::StrFn strFn;
strFn.Create = StrCreateApple;
strFn.Destroy = StrDestroyApple;
strFn.PrimaryCompare = StrPrimaryCompareApple;
strFn.SecondaryCompare = StrSecondaryCompareApple;
strFn.m_pData = NULL;
strFn.m_PrimaryCompareId = 1;
strFn.m_SecondaryCompareId = 2;
sl::SloynikEngine * pEngine = new sl::SloynikEngine(dictionaryPath, indexPath, strFn);
LOG(LINFO, ("Starting sloynik engine."));
return pEngine;
}

View file

@ -34,6 +34,7 @@ public:
struct SearchResult
{
SearchResult() : m_FirstMatched(0) {}
WordId m_FirstMatched;
};