Паскорыць пошук з дапамогай dispatch_async?

Я спрабую паскорыць свой пошук прыкладанняў, гэта атрымаць лагі, калі ёсць шмат дадзеных.

таму я спрабую падзяліць пошук <�моцны> прэдыкаты на <�моцны> UI з дапамогай dispatch_async не dispatch_sync не выклікаюць не адрозніваецца, калі я выкарыстоўваю гэта.

Праблема заключаецца ў тым, калі я выкарыстоўваю dispatch_async , крах прыкладання часам таму, што [__ NSArrayI objectAtIndex:]: індэкс "17" за межы .

Я цяпер гэта адбылося таму, што дазваляе сказаць, што першы па-ранейшаму працаваць і перазагрузіць Tableview і працягнуць пошук будзе змяняць памер масіва залежыць ад выніку, так і ў гэтым выпадку «CRASH» :(

гэта мой код:

    dispatch_async(myQueue, ^{
        searchArray = [PublicMeathods searchInArray:searchText array:allData];
    } );

    if(currentViewStyle==listViewStyle){
        [mytable reloadData];
    }

і я паспрабаваў гэта:

    dispatch_async(myQueue, ^{
        NSArray *tmpArray = [PublicMeathods searchInArray:searchText array:allData];
        dispatch_sync(dispatch_get_main_queue(), ^{
            searchArray = tmpArray;
            [mytable reloadData];
        });
    });

але ў гэтым выпадку лагі ўсё яшчэ там.

<�Моцны> Update -1:

Пошук Predicate займае ўсяго 2мс :) пасля цяжкай працы :) але клавіятура ўсё яшчэ адстае, калі карыстальнік выконвае пошук, так што адзінае, што я раблю пасля таго, як вынік атрымліваю перазарадка табліца «змяненне ў інтэрфейсе» гэта тое, што я думаю, што зрабіць гэта лагі,

So what I search for split this two operation "typing on keyboard & refresh UI".

<�Моцны> Update -2:

@matehat https://stackoverflow.com/a/16879900/1658442

і

@TomSwift https://stackoverflow.com/a/16866049/1658442

адказы працаваць як шарм :)

10
Я б значна больш аддаю перавагу NSThread і NSNotification.
дададзена аўтар Shane Hsu, крыніца
@AndreyChevozerov прыбіральнік, больш просты код. Зараз няма нічога дрэннага ў Нод, вы можаце, вядома, выкарыстанне Нод з NSNotification, я проста думаю, што гняздуюцца гэтыя Нод выклікаў можа быць праблематычным.
дададзена аўтар Shane Hsu, крыніца
Вы павінны профіль гэтага, каб сапраўды ведаць, дзе запаволенне
дададзена аўтар nielsbot, крыніца
Акрамя таго, у мяне ёсць некаторы код, якія могуць апынуцца карыснымі пры выкарыстанні CPU пробоотборник інструмента не дапамагае github.com/nielsbot/Profiler
дададзена аўтар nielsbot, крыніца
@ShaneHsu маглі б вы растлумачыць, чаму? Што здарылася з НОДОМ?
дададзена аўтар Andrey Chevozerov, крыніца
калі ваш пошук займае 2 мс, то адставанне вы сведкамі з-за вашага reloadData выкліку. Глядзіць на вашым Tableview і крыніца дадзеных дэлегаты марудлівасці.
дададзена аўтар escrafford, крыніца
колькі прадметаў ёсць у ALLDATA і ў сярэднім у tmpArray?
дададзена аўтар Valerii Hiora, крыніца
Я таксама падтрымліваю тое, што @escrafford сказаў. Калі працэс пошуку займае 2 мс, то праблема не працэс пошуку, гэта абнаўленне карыстацкага інтэрфейсу. Калі вы не можаце што-небудзь у загрузнай логіцы карыстацкага інтэрфейсу змяніць, паспрабуйце змяніць частату, абнавіць дадзеныя. Напрыклад, толькі выканаць працэс пошуку кожныя 2 ці 3 знакаў, уведзеных у тэкставым полі, або чакаць на працягу секунды ці два пасля таго, як карыстальнік спыняе ўвод дадзеных.
дададзена аўтар Mohannad A. Hassan, крыніца

8 адказы

Калі searchArray гэта масіў, які выкарыстоўваецца ў якасці крыніцы дадзеных таблічнага, то гэты масіў павінен быць даступныя і зменены ў галоўным патоку толькі.

Такім чынам, на фоне патоку, вы павінны прасочвацца ў асобны часовы масіў раней усіх. Затым прызначыць часовы масіў searchArray на галоўнай тэме:

dispatch_async(myQueue, ^{
    NSArray *tmpArray = [PublicMeathods searchInArray:searchText array:allData];
    dispatch_sync(dispatch_get_main_queue(), ^{
        searchArray = tmpArray;
        [mytable reloadData];
    });
});

Update: Using a temporary array should solve the crash problem, and using a background thread helps to keep the UI responsive during the search. But as it turned out in the discussion, a major reason for the slow search might be the complicated search logic.

Гэта можа дапамагчы захаваць дадатковыя «нармалізаваныя» дадзеныя (напрыклад, пераўтворыцца ў ніжнім рэгістр, нумары тэлефонаў, ператвораныя ў стандартную форму, і г.д ...), так што фактычны пошук можа быць зроблены з хутчэй без уліку рэгістра параўнання.

9
дададзена
@Omarj: ён вырашае праблему аварыі? - Гэта цяжка, каб дапамагчы з запазненнем. Складаны пошук можа заняць некаторы час. Перавага фільтрацыі на фоне патоку з'яўляецца тое, што інтэрфейс павінен заставацца спагадным падчас пошуку актыўная.
дададзена аўтар Martin R, крыніца
@Omarj: Я не думаю, што гэта мае значэнне, калі вы выкарыстоўваеце dispatch_async або NSOperationQueue. Вы павінны знайсці <�я> прычына для лагов першых. Вы можаце дадаць некаторыя заявы NSLog() вашы метады, каб знайсці, дзе час сыходзіць. Або профіль яго інструменты.
дададзена аўтар Martin R, крыніца
@Omarj: Вы стварыць myQueue з DISPATCH_QUEUE_CONCURRENT сцяг?
дададзена аўтар Martin R, крыніца
@Omarj: Па змаўчанні чаргу <�я> серыйны , што азначае, што працэс фільтрацыі пачнецца толькі тады, калі папярэдні працэс фільтрацыі скончаны. А <�я> адначасова чаргу выконвае задачу "адначасова". Так што, калі вы набіраеце іншую літару ў поле пошуку, пошук будзе адразу ж пачаць.
дададзена аўтар Martin R, крыніца
так што назад да жабрацтва мне трэба падзяліць аперацыю запісу тэксту і перазагрузіць аперацыю ?? таму клавіятура не будзе лагов і перазарадка зойме час, неабходнае?
дададзена аўтар Omarj, крыніца
пасля таго, як дадаць NSLog метад пошуку проста ўзяць 2ms і перазарадка дадзеных прымаць 30мс.
дададзена аўтар Omarj, крыніца
: Што калі я выкарыстоўваю NSOperationQueue ???
дададзена аўтар Omarj, крыніца
няма, што гэта карысна для выкарыстання гэтага сцяга ??
дададзена аўтар Omarj, крыніца
Я ўжо вырашыць аварыі з дапамогай «сінхранізацыі», і гэта дае мне той жа вынік «час & хуткасць» у якасці адказу. так што я шукаць, добрую логіку, каб мець такую ​​ж хуткасць, калі я выкарыстоўваю «асинхр» без аварыі.
дададзена аўтар Omarj, крыніца
але гэта не здымае лагі :( абнавіць Q., дадаючы Сол.
дададзена аўтар Omarj, крыніца

Адным з рашэнняў можа быць добраахвотна выклікаць затрымку паміж пошукі, каб дазволіць карыстачу ўвесці і хай пошук будзе выконвацца асінхронна. Вось як:

Спачатку пераканайцеся, што ваша чаргу ствараецца наступным чынам:

dispatch_queue_t myQueue = dispatch_queue_create("com.queue.my", DISPATCH_QUEUE_CONCURRENT);

Майце гэта Івар, вызначаны ў класе (і ўсталяваць яго ў FALSE пры ініцыялізацыі):

BOOL _scheduledSearch;

Запішыце гэты макрас ў верхняй частцы файла (або дзе-небудзь на самай справе, проста пераканайцеся, што яго відаць)

#define SEARCH_DELAY_IN_MS 100

І замест таго, каб ваш другі фрагмент, выклічце гэты метад:

[self scheduleSearch];

Рэалізацыя Чыя гэта:

- (void) scheduleSearch {
    if (_scheduledSearch) return;
    _scheduledSearch = YES;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)((double)SEARCH_DELAY_IN_MS * NSEC_PER_MSEC));
    dispatch_after(popTime, myQueue, ^(void){
        _scheduledSearch = NO;
        NSString *searchText = [self textToSearchFor];
        NSArray *tmpArray = [PublicMeathods searchInArray:searchText array:allData];
        dispatch_async(dispatch_get_main_queue(), ^{
            searchArray = tmpArray;
            [mytable reloadData];
        });
        if (![[self textToSearchFor] isEqualToString:searchText])
            [self scheduleSearch];
    });
}

[self textToSearchFor] is where you should get the actual search text from.

Вось што ён робіць:

  • У першы раз прыходзіць запыт, ён ўстанаўлівае _scheduledSearch Івар ў ПРАЎДА і кажа Нод запланаваць пошук у 100 мс
  • Між тым любыя новыя пошукавыя запыты не клапоцяцца, таму што пошук будзе адбывацца ў любым выпадку на працягу некалькіх мсов
  • Калі плануецца пошук адбываецца, _scheduledSearch Івар скідаецца ў FALSE , таму наступны запыт апрацоўваецца.

Вы можаце гуляць з рознымі значэннямі SEARCH_DELAY_IN_MS , каб зрабіць яго для сваіх патрэб. Гэта рашэнне павінна цалкам раз'яднаць падзея клавіятуры з рабочай нагрузкай ад пошуку.

4
дададзена
дагэтуль галоўная праблема ў гэтым рашэнні няма, калі карыстальнік праясніцца пошук тэкст, гэта дасць яму вынік для апошняга знака, што ён/яна выдаліць яго.
дададзена аўтар Omarj, крыніца
Я думаю, што лепшае рашэнне спыніць усе аперацыі пошуку да прыпынку карыстальніка, набраўшы пасля пэўнага часу ??? ці нешта падобнае?
дададзена аўтар Omarj, крыніца
дададзена аўтар Omarj, крыніца
некалькі разоў, калі тып карыстальніка ў хуткасці, як вынік не будзе правільным, напрыклад, калі я тыпу «Smithe» вынік будзе для «каваль». пылавікі праблемы, калі карыстальнік ачысціць панэль пошуку тэксту па літарах выніку будзе для першай літары ў тэксце і некаторы час не дае мне выніку ў масіве, таму што выклік метаду пошуку для «» пустой радка.
дададзена аўтар Omarj, крыніца
ёсць нешта яшчэ няправільна вынік не дазваляе правільна, але я захапляюся у гэтым рашэнні ён з'яўляецца адным з лепшых дагэтуль
дададзена аўтар Omarj, крыніца
Thx, але ў некаторых выпадках гэта не будзе працаваць правільна, напрыклад, калі карыстальнік ўводзіць дзве літары і спыніць вынік будзе толькі для першага другога :(
дададзена аўтар Omarj, крыніца
Я разумею, што вы маеце на ўвазе. Я рэдагаваў рашэнне адпаведна.
дададзена аўтар matehat, крыніца
Што яшчэ не так? можа быць, я магу дапамагчы знайсці пытанне
дададзена аўтар matehat, крыніца
Я крыху змяніў код, я думаю, ён павінен вырашыць гэтую праблему вы маеце.
дададзена аўтар matehat, крыніца

Па-першае, пара адзначае па кодзе вы прадставілі:

1) Гэта выглядае так, як быццам вы, верагодна, у чарзе некалькі запытаў як тыпаў карыстальнікаў, і ўсе яны павінны працаваць, каб завяршыць да адпаведнага адна (самая апошняя) абнаўляе экран з жаданым наборам вынікаў.

2) Другі фрагмент кода вы паказваеце правільны шаблон з пункту гледжання бяспекі патоку. Першы фрагмент абнаўляе інтэрфейс да завяршэння пошуку. Хутчэй за ўсё, ваша аварыя адбываецца з першым фрагментам, так як фонавы паток абнаўляе searchArray, калі асноўны паток чытае з яго, а гэта азначае, што ваш крыніца дадзеных (падтрымліваецца searchArray) знаходзіцца ў няўстойлівым стане.

Вы не кажаце, калі вы выкарыстоўваеце UISearchDisplayController або няма, і гэта на самай справе не мае значэння. Але калі вы, адна агульная праблема не выконвае - (BOOL) searchDisplayController: (UISearchDisplayController *) кантролер shouldReloadTableForSearchString: (NSString *) фільтр і вяртае NO. Пры рэалізацыі гэтага метаду і вяртанні NO вы адключаеце паводзіны па змаўчанні перазагрузкі Tableview з кожным змяненнем тэрміна пошуку. Замест гэтага ў вас ёсць магчымасць штурхнуць свой асінхронны пошук новага тэрміна, і абнавіць карыстацкі інтэрфейс ( [TableView reloadData] ) толькі адзін раз у вас ёсць новыя вынікі.

Незалежна ад таго, карыстаецеся Ці вы UISearchDisplayController вам трэба зрабіць некалькі рэчаў пад увагу пры рэалізацыі вашага асінхроннага пошуку:

1) У ідэале вы можаце перапыніць пошук у незавершаным і не адмяніць яго, калі пошук ўжо не карысна (напрыклад, тэрмін пошуку зменены). Ваш метад «searchInArray" не з'яўляецца, каб падтрымаць гэта. Але гэта лёгка зрабіць, калі ваш проста сканавання масіва.

1а) Калі не адмяніць пошук, вы па-ранейшаму патрэбен спосаб у канцы пошуку, каб убачыць, калі вашы вынікі актуальныя ці не. Калі няма, то не абнавіць карыстацкі інтэрфейс.

2) Пошук павінен працаваць у фонавым патоку, каб не ўгразнуць асноўны паток і UI.

3) Пасля таго, як па завяршэнні пошуку гэтага трэба абнавіць карыстацкі інтэрфейс (і крыніца дадзеных, карыстацкі інтэрфейс у) у асноўным струмені.

Я паставіў разам прыклад праект ( тут, на Github ), які выконвае даволі неэфектыўны пошук з вялікім спісам слоў , Карыстацкі інтэрфейс застаецца рэагаваць, як карыстальнік ўводзіць у іх тэрмін, і спараджалі пошукі адмяніць сябе, як яны становяцца неістотнымі. Мяса ўзору гэты код:

- (BOOL) searchDisplayController: (UISearchDisplayController *) controller
shouldReloadTableForSearchString: (NSString *) filter
{
   //we'll key off the _currentFilter to know if the search should proceed
    @synchronized (self)
    {
        _currentFilter = [filter copy];
    }

    dispatch_async( _workQueue, ^{

        NSDate* start = [NSDate date];

       //quit before we even begin?
        if ( ![self isCurrentFilter: filter] )
            return;

       //we're going to search, so show the indicator (may already be showing)
        [_activityIndicatorView performSelectorOnMainThread: @selector( startAnimating )
                                                 withObject: nil
                                              waitUntilDone: NO];

        NSMutableArray* filteredWords = [NSMutableArray arrayWithCapacity: _allWords.count];

       //only using a NSPredicate here because of the SO question...
        NSPredicate* p = [NSPredicate predicateWithFormat: @"SELF CONTAINS[cd] %@", filter];

       //this is a slow search... scan every word using the predicate!
        [_allWords enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {

           //check if we need to bail every so often:
            if ( idx % 100 == 0 )
            {
                *stop = ![self isCurrentFilter: filter];
                if (*stop)
                {
                    NSTimeInterval ti = [start timeIntervalSinceNow];
                    NSLog( @"interrupted search after %.4lf seconds", -ti);
                    return;
                }
            }

           //check for a match
            if ( [p evaluateWithObject: obj] )
            {
                [filteredWords addObject: obj];
            }
        }];

       //all done - if we're still current then update the UI
        if ( [self isCurrentFilter: filter] )
        {
            NSTimeInterval ti = [start timeIntervalSinceNow];
            NSLog( @"completed search in %.4lf seconds.", -ti);

            dispatch_sync( dispatch_get_main_queue(), ^{

                _filteredWords = filteredWords;
                [controller.searchResultsTableView reloadData];
                [_activityIndicatorView stopAnimating];
            });
        }
    });

    return FALSE;
}

- (BOOL) isCurrentFilter: (NSString*) filter
{
    @synchronized (self)
    {
       //are we current at this point?
        BOOL current = [_currentFilter isEqualToString: filter];
        return current;
    }
}
3
дададзена
@Omarj - адны і тыя ж прынцыпы дастасавальныя. Хутчэй за ўсё, вы хочаце, каб пачаць новы пошук з кожным змяненнем уваходнага тэксту, і вы можаце атрымаць, што з USearchBarDelegate - SearchBar: shouldChangeTextInRange: replacementText: метад.
дададзена аўтар TomSwift, крыніца
Мой вынік не заўсёды з'яўляецца ў Tableview стылі для прыкладу «Сетка стылю».
дададзена аўтар Omarj, крыніца
Што рабіць, калі я выкарыстоўваю толькі пошук-бар і выкарыстоўваць свой уласны карыстацкі інтэрфейс у гэтым выпадку нельга выкарыстоўваць - (BOOL) searchDisplayController: (UISearchDisplayController *) кантролер shouldReloadTableForSearchString: (NSString *) фільтр;
дададзена аўтар Omarj, крыніца

Я падазраю, што ваша праблема ў тым, што ALLDATA размяркоўваецца паміж асноўнай чаргой і чаргой фону. Калі вы ўносіце змены ў ALLDATA на галоўнай чарзе, што можа пакараціць ALLDATA ў фонавым рэжыме чарзе, у выніку чаго індэкс, які выкарыстоўваецца, каб быць сапраўдным, каб стаць несапраўдным.

Акрамя таго, магчыма, што праблема заключаецца не ў ALLDATA сам па сабе, але некаторыя з масіва ў межах аб'ектаў у ALLDATA . Паспрабуйце ўсталяваць кропку супыну на выключэннях (у Xcode, адкрыйце спіс крыніц Breakpoints, націсніце на кнопку плюс у ніжняй часткі, і выберыце «Дадаць Exception Breakpoint ...»), так што вы можаце ўбачыць, дзе менавіта адбываецца памылка.

У любым выпадку, у вас ёсць два магчымых рашэнні:

  1. Скапіюйце аб'ект крыўдзячы, перш чым выкарыстоўваць яго ў пошуку. Гэта абараняе фону чаргу ад зменаў у асноўны чарзе, але ў залежнасці ад таго, што вам трэба скапіяваць, гэта можа быць цяжка атрымаць змены назад у UI-вы, магчыма, павінны адпавядаць копіі назад іх арыгіналы.

  2. <�Літый> <�р> Выкарыстоўвайце блакаванне (напрыклад, @synchronized ) або чарзе для кожнага аб'екта, каб забяспечыць толькі адна чаргу выкарыстоўвае аб'ект адначасова. <�Код> NSManagedObjectContext выкарыстоўвае апошні падыход для яго -performBlock: і -performBlockAndWait: метады. Гэта можа быць крыху больш складана, каб зрабіць гэта без блакавання асноўнай чарзе, хоць.
1
дададзена

Паспрабуйце змяніць вашыя функцыі наступны шлях:

Прататып функцыі;

- (void)searchInArray:searchText array:allData complete: (void (^)(NSArray *arr)) complete;

сама функцыя

- (void)searchInArray:searchText array:allData complete: (void (^)(NSArray *arr)) complete { 
    NSArray * array = [NSArray new];
   //function code
    complete(array)//alarming that we have done our stuff
}

і калі вы выклікаеце гэтую функцыю

dispatch_queue_t searchQueue = dispatch_queue_create("com.search",NULL);
dispatch_async(searchQueue,^{
 [PublicMeathods searchInArray:searchText array:allData complete:^(NSArray *arr) {
     searchArray = arr;
     dispatch_async(dispatch_get_main_queue(), ^{
         [myTable reloadData];
     });
 }];
});

Спадзяюся, гэта дапаможа вам)

1
дададзена
Вы можаце змяніць сваё пытанне з даданнем змяненняў у код, які вы зрабілі. можа быць гэта спросціць пошук рашэння
дададзена аўтар Roma, крыніца
яна павінна працаваць. Вы паспрабуеце? З апошняга абнаўлення масіва змяняецца ў фонавай чарзе і калі гэта будзе зроблена то яна вяртае яго ў поўным блоку, і толькі тады ён абнаўляе табліцу ў асноўны чарзе.
дададзена аўтар Roma, крыніца
Я змяніў код няшмат. Зараз гэта асінхронная. ён павінен працаваць лепш
дададзена аўтар Roma, крыніца
Смяці я ўжо missprinted зараз гэта Async замест сінхранізацыі і не змерзне дадатак)
дададзена аўтар Roma, крыніца
да :) Я ўжо паспрабаваць гэта, перш чым я вам казаў.
дададзена аўтар Omarj, крыніца
апошняе абнаўленне ня выправіць і не можа ўнесці змены на масіў і UI ў асінхронным гэта зробіць аварыю адтуліны: P
дададзена аўтар Omarj, крыніца
Я ўжо гэта выправіць, але ніякіх зменаў не адстае яшчэ там пры выкарыстанні гэтага рашэння. :(
дададзена аўтар Omarj, крыніца
«Dispatch_sync (dispatch_get_main_queue() ^ {» гэта будзе замарозіць прыкладанне і блок карыстацкага інтэрфейсу :(
дададзена аўтар Omarj, крыніца

Я лічу, што ваша аварыя сапраўды вырашаецца укладаннем адлюстравання элемента карыстацкага інтэрфейсу, для якога searchArray з'яўляецца падтрымка элемент выкліку GrandCentralDispatch ўнутры іншага выкліку (як вы паказваеце ў сваім абноўленым зыходным паведамленні). што гэта адзіны спосаб пераканацца, што вы не выклікаеце элементы масіва, каб змяніць за кадрам, а адлюстраванне элементаў, звязаных з ім адбываецца.

Аднак, я лічу, калі вы бачыце, адставанне, гэта не столькі выклікана апрацоўкай масіва ў 2мс або перазагрузкі, якая прымае 30мс, а да таго часу ён прымае Нод, каб дабрацца да ўнутранага выкліку dispatch_sync на галоўнай чарзе ,

калі да гэтага моманту, вы здолелі атрымаць апрацоўку вашага масіва ўніз толькі 2мс у горшым выпадку (або нават калі вам удалося атрымаць яго да менш чым 30 мс, што прыкладна ў той час, неабходнае для апрацоўкі кадр у асноўны цыкл выканання пры 30 кадрах у секунду), то вы павінны разгледзець адмову ад GCD цалкам у вашых высілкаў, каб апрацаваць гэты масіў. прымаючы 2ms на галоўнай чарзе, каб апрацаваць ваш масіў не будзе выклікаць любыя паводзіны багі.

вы можаце мець адставанне ў іншым месцы (гэта значыць, калі вы павялічваюцца вынікі пошуку, спрабуючы выйсці ў сетку, каб атрымаць вынікі, вы можаце зрабіць выклік, а затым апрацаваць адказ на асобнай чарзе адпраўкі), але раз вы гаворым, гэта біт апрацоўкі ня трэба падзяліць на асобныя з чэргаў. для любой апрацоўкі злосных, які бярэ на сябе 30мс, вы павінны разгледзець Нод.

1
дададзена

Я знайшоў простае рашэнне ў тым жа духу рашэння, прадстаўленага Matehad (вычакаць некаторы час і выканаць пошук толькі калі карыстальнік не ўводзіць нічога іншага). Вось яна:

Абвясьцеце 2 глабальныя лічыльнікі і глабальную радок:

INT keyboardInterruptionCounter1 = 0, Int keyboardInterruptionCounter2 = 0 і NSString * searchTextGlobal

Аб функцыі SearchBar зрабіць гэта:

-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{

keyboardInterruptionCounter1++;

    searchTextGlobal = searchText;//from local variable to global variable

    NSTimeInterval waitingTimeInSec = 1;//waiting time according to typing speed.

    //waits for the waiting time
    [NSTimer scheduledTimerWithTimeInterval:waitingTimeInSec target:self  selector:@selector(timerSearchBar:) userInfo:nil repeats:NO];

}

-(void)timerSearchBar:(NSTimer *)timer{

    keyboardInterruptionCounter2++;

   //enters only if nothing else has been typed.
    if (keyboardInterruptionCounter2 == keyboardInterruptionCounter1) {

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
                                             (unsigned long)NULL), ^(void) {

        //do the search with searchTextGlobal string

    dispatch_async(dispatch_get_main_queue(), ^{
         //update UI
     });

    });

    }
}

Тлумачэнне: пошук выконваецца толькі тады, калі абодва лічыльніка аднолькавыя, гэта адбываецца толькі тады, калі карыстальнік надрукаваў і стаў чакаць .52 секунды без уводу што-небудзь яшчэ. Замест гэтага, калі тыпы карыстальнікаў досыць хутка, то ні адзін з запытаў не будзе зроблена. Рашэнне можа быць зроблена з або без разьбы.

1
дададзена
я паспрабую яго як мага хутчэй :) тнх
дададзена аўтар Omarj, крыніца

Martin R апублікаваў правільны адказ. Адзінае, што трэба адзначыць, што замест

dispatch_sync(dispatch_get_main_queue()

яна павінна быць

dispatch_async(dispatch_get_main_queue()

Поўны код у Swift будзе:

        let remindersFetcherQueue = dispatch_queue_create("com.gmail.hillprincesoftware.remindersplus", DISPATCH_QUEUE_CONCURRENT)
        dispatch_sync(remindersFetcherQueue) {
            println("Start background queue")

            estore.fetchRemindersMatchingPredicate(remindersPredicate) {
                reminders in
                   //var list = ... Do something here with the fetched reminders.
                    dispatch_async(dispatch_get_main_queue()) {
                        self.list = list  //Assign to a class property
                        self.sendChangedNotification()     //This should send a notification which calls a function to ultimately call setupUI() in your view controller to do all the UI displaying and tableView.reloadData(). 
                    }                        
            }
        }
0
дададзена
3 адказаў з'яўляюцца правільнымі: D, але мы шукалі лепшы той, які дасць карыстачу добры экспа.
дададзена аўтар Omarj, крыніца