Узнайте, поддерживает ли Mac Force Touch
Можно ли узнать, поддерживает ли Mac Force Touch - через встроенный трекпад, например, новый MacBook, или устройство Bluetooth, например, Magic Trackpad 2?
Я хотел бы представить настройки, специфичные для Force Touch, если Mac поддерживает Force Touch, но не отображать (или отключать) эти настройки, если Force Touch недоступен.
В части после разделителя вы видите варианты, которые я имею в виду, на рисунке, связанном здесь. (извините, встраивание самой картинки не работает).
Таким образом, не показ предпочтений не ограничил бы пользователей, у которых нет принудительного прикосновения, просто позволил бы пользователям, у которых он есть, настроить, как он должен работать, и эти настройки были бы бесполезны для пользователей, у которых его нет.
Есть ли способ добиться этого?
Спасибо и всего наилучшего, Мэтт
Изменить: это в Objective-C.
1 ответ
Я понял:
+ (BOOL)isForceTouchCapable
{
if (![[self class] isAtLeastElCapitan])
return NO;
io_iterator_t iterator;
//get default HIDDevice dictionary
CFMutableDictionaryRef mDict = IOServiceMatching(kIOHIDDeviceKey);
//add manufacturer "Apple Inc." to dict
CFDictionaryAddValue(mDict, CFSTR(kIOHIDManufacturerKey), CFSTR("Apple Inc."));
//get matching services, depending on dict
IOReturn ioReturnValue = IOServiceGetMatchingServices(kIOMasterPortDefault, mDict, &iterator);
BOOL result = YES;
if (ioReturnValue != kIOReturnSuccess)
NSLog(@"error getting matching services for force touch devices");
else
{
//recursively go through each device found and its children and grandchildren, etc.
result = [[self class] _containsForceTouchDevice:iterator];
IOObjectRelease(iterator);
}
return result;
}
+ (BOOL)_containsForceTouchDevice:(io_iterator_t)iterator
{
io_object_t object = 0;
BOOL success = NO;
while ((object = IOIteratorNext(iterator)))
{
CFMutableDictionaryRef result = NULL;
kern_return_t state = IORegistryEntryCreateCFProperties(object, &result, kCFAllocatorDefault, 0);
if (state == KERN_SUCCESS && result != NULL)
{
if (CFDictionaryContainsKey(result, CFSTR("DefaultMultitouchProperties")))
{
CFDictionaryRef dict = CFDictionaryGetValue(result, CFSTR("DefaultMultitouchProperties"));
CFTypeRef val = NULL;
if (CFDictionaryGetValueIfPresent(dict, CFSTR("ForceSupported"), &val))
{
Boolean aBool = CFBooleanGetValue(val);
if (aBool) //supported
success = YES;
}
}
}
if (result != NULL)
CFRelease(result);
if (success)
{
IOObjectRelease(object);
break;
} else
{
io_iterator_t childIterator = 0;
kern_return_t err = IORegistryEntryGetChildIterator(object, kIOServicePlane, &childIterator);
if (!err)
{
success = [[self class] _containsForceTouchDevice:childIterator];
IOObjectRelease(childIterator);
} else
success = NO;
IOObjectRelease(object);
}
}
return success;
}
Просто вызовите + (BOOL)isForceTouchCapable, и он вернет ДА, если устройство Force Touch доступно (Magic Trackpad 2 или встроенный сенсорный трекпад), или НЕТ, если его нет.
Для тех, кто интересуется, как это произошло, я написал об этом в своем блоге с примером проекта.