Способ вашего подкласса NSThread - это все, что работает на этом потоке. Вы не можете прервать его, чтобы запустить другой код без сотрудничества main
.
Что вы действительно должны сделать, это выбросить весь цикл и заменить его на NSRunLoop и NSTimer.
- NSRunLoop держит нить в живых до тех пор, пока есть что-то, что нужно будет делать, но и спит нить до не нужно делать что-то.
- NSTimer делает что-то на повторяющемся интервале, пока он запланирован в цикле запуска.
Вам нужна ваша нить, чтобы сделать две вещи:
- отправить MyThread объект на
heartBeats
сообщение (вы делаете это)
- отправить контроллер представления на
someMethod
сообщение (это то, что вы)
Для последнего вам понадобится еще одна вещь: источник цикла запуска.
Итак, ясно из вашего метода main
и заменить его следующим:
- Получить текущий NSRunLoop и хранить его в локальной переменной.
- Создайте NSTimer с 10-секундным интервалом, целью которого является
self
, а селектор - heartBeats
. (Немного чистая версия: используйте другой метод, который принимает NSTimer *, но игнорирует его, поэтому ваш таймер вызывает этот метод, и этот метод вызывает heartBeats
. Правильный способ установки таймера - дать ему метод, который ожидается называть с таймером, но на практике также дает метод, который не принимает никаких аргументов.)
- Если вы не создали таймер, используя
scheduledTimerWith…
, добавьте его в цикл выполнения. (Методы scheduledTimerWith…
сделают это для вас.)
- Создайте источник цикла запуска и добавьте его в цикл выполнения.
- Звонок
[myRunLoop run]
.
Шаг 4 медведей, объясняющие:
Основной фонд (но не фонд, я не знаю, почему) есть то, что называется «источники пробег цикла», которые являются пользовательские объекты, которые могут быть добавлены в цикл выполнения и будет вызывать что-то однажды сигнализированное.
Похоже, что вы хотите, чтобы вызвать ваш метод контроллера точки зрения!
Во-первых, в контроллере просмотра измените значение myThread
на локальную переменную в viewDidLoad
на переменную экземпляра. Переименуйте его _myThread
, чтобы сделать это понятным.
Следующая, добавить delegate
собственности на MyThread
. Это должно быть weak
и иметь тип id <MyThreadDelegate>
. Вам также необходимо определить протокол MyThreadDelegate
, который должен иметь один метод, не принимающий никаких аргументов и не возвращающий ничего (void
).
Теперь вы можете установить _myThread.delegate = self
с контроллера вида и реализовать в контроллере представления метод, который вы указали в протоколе. Контроллер представления теперь является делегатом его MyThread.
В -[MyThread main]
, создать версию-0 CFRunLoopSource. Функция «Создать» принимает структуру «контекста», содержащую, среди прочего, версию (0), указатель «info» (задает это значение self
, то есть MyThread) и обратный вызов Perform (функция, которая будет вызываться с указателем info
в качестве единственного аргумента).
В вашем выполнения обратного вызова, вам нужно сделать что-то вроде этого:
MyThread *self = (__bridge MyThread *)info;
[self fireDelegateMessage];
В MyThread, реализовать этот fireDelegateMessage
метод. Там, отправьте сообщение self.delegate
, которое вы указали в своем протоколе.
Затем добавьте общедоступный метод в MyThread (т. Е. Объявите его в MyThread.h, а также реализуйте его в MyThread.m), назвав что-то вроде «requestDelegateMessage». В этом методе позвоните по номеру CFRunLoopSourceSignal
. (Документация для выполнения этой функции предполагает, что вы также должны вызвать CFRunLoopWakeUp
. П потока CFRunLoop
Попробуй без первого.)
Наконец, когда контроллер представления хочет someMethod
называться по этой теме, вызовите [_myThread requestDelegateMessage]
.
Итак:
- контроллер вид вызывает
requestDelegateMessage
requestDelegateMessage
сигнализирует источник цикла выполнения (и будит цикл выполнения, если это необходимо)
- источник цикла выполнения вызывает выполнение обратного вызова в потоке MyThread
- выполняют обратные вызовы
fireDelegateMessage
по теме MyThread
fireDelegateMessage
называет th внедрения электронного контроллера представления о методе делегата на нити в MyThread в
- контроллер вид вызывает
someMethod
на нити в MyThread в
занят опрос, как это ужасно код в любом месте, но особенно на мобильном устройстве – Paulw11
@ Paulw11 да, но это не может быть и речи, фактически, «heartBeats» - это API, который я должен назвать так, чтобы сохранить это длинное соединение. : ( –
Замена кода 'if' на' [NSThread sleepForTimeInterval: 0,007]; 'снижение потребления процессора с 98% до 2% и увеличение интервалов между 7,6 мс и 9,8 м. Использование' [NSThread sleepForTimeInterval: 0,0002]; 'с ваш код if дал интервалы ближе к 10.3 мс и использовал 9% процессор, но короткий ответ - вам придется использовать какую-то синхронизацию и структуру данных с общей памятью, чтобы ваш цикл определял, что он должен выполнить какой-либо другой метод. t просто отправьте метод в потоке так, как вы можете, с помощью очереди GCD – Paulw11