Узнайте, поддерживает ли 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 или встроенный сенсорный трекпад), или НЕТ, если его нет.

Для тех, кто интересуется, как это произошло, я написал об этом в своем блоге с примером проекта.

Другие вопросы по тегам