Можно ли использовать CARemoteLayerServer и CARemoteLayerClient между процессами? - PullRequest
6 голосов
/ 15 февраля 2012

В Mac OS X Lion CARemoteLayerServer и CARemoteLayerClient были добавлены в QuartzCore. Я пытался выяснить, подходят ли они для разделения графического приложения между несколькими процессами, но безуспешно.

Я могу успешно использовать их в одном процессе, с некоторым кодом в следующем виде:

- (void)buildLayerSingleProcess
{
    CARemoteLayerServer *server = [CARemoteLayerServer sharedServer];

    self.client = [[CARemoteLayerClient alloc] initWithServerPort: server.serverPort];    
    uint32_t clientID = self.client.clientId;    

    CALayer *layer1 = [CALayer layer];
    layer1.bounds = CGRectMake(0.0, 0.0, 100.0, 100.0);

    CGColorRef color = CGColorCreateGenericRGB(0.4, 0.2, 0.3, 1.0);
    [layer1 setBackgroundColor: color];
    CFRelease(color);

    [layer1 setOpacity: 0.75];
    [layer1 setBorderWidth: 5.0f];

    layer1.position = CGPointMake([[self.window contentView] frame].size.width / 2.0, [[self.window contentView] frame ].size.height / 2.0);

    self.client.layer = layer2;

    CALayer *servedLayer = [CALayer layerWithRemoteClientId: self.client.clientId];    
    [[[self.window contentView] layer] addSublayer: servedLayer];
}

Это хорошо, но я бы хотел попробовать сделать что-то похожее между процессами. Тот факт, что server.serverPort имеет тип mach_port_t, подразумевает, что он подходит для использования между процессами.

Однако, когда я разделяю этот код для запуска в двух процессах (либо в двух отдельных приложениях, либо в основном процессе и службе XPC), когда я пытаюсь инициализировать CARemoteLayerClient с mach_port_t с сервера в другом процессе, я получить:

unable to register with server: 0x10000003

Вполне возможно, что они не подходят для между случайными процессами, но использование mach_port_t своего рода подразумевает это.

Кто-нибудь еще имел успех, используя эти классы между процессами?

1 Ответ

6 голосов
/ 19 февраля 2012

Да, это возможно. Вот пример: https://github.com/krevis/RemoteLayerDemo

Запустите приложение, нажмите кнопку «Получить удаленный слой», и служба запустится и даст приложению зеленый удаленный слой. (Как ни странно, это занимает несколько секунд - не знаю почему.)

После этого кнопка «Изменить цвет» отправляет в сервис сообщение с просьбой изменить цвет слоя, который вступает в силу немедленно и даже анимируется. Кнопка «Удалить удаленный слой» удаляет слой; затем служба будет прервана, если вы оставите ее бездействовать на несколько секунд.

Сложная часть передает порт Маха CARemoteLayerServer между процессами. mach_port_t, который вы видите в своем процессе, это просто число; это имеет значение только в вашем процессе. (Та же идея, что и у указателя: указатели - это просто числа, но вы не можете передать указатель от одного процесса к другому и ожидать, что они укажут на одно и то же.)

Вы могли бы подумать, что XPC может отправлять порты Маха, но не может. Это сделало бы это намного проще!

Вместо этого вы должны использовать Mach API для отправки основного порта Маха. В демоверсии я использую bootstrap_register в приложении и bootstrap_look_up в сервисе, используя согласованное имя. Это небезопасно, потому что любое другое приложение в том же контексте начальной загрузки может найти порт, но этого достаточно для демонстрации. На самом деле вы бы хотели нырнуть в более уродливые вызовы Маха .

...