
關(guān)于 Quick Touch & Touch Bar
Touch Bar 其實就是在原來 MBP 的按鍵區(qū)頂部新增了一個長條形的OLED觸控屏,提供一些常用的快捷鍵。(iMessage 選表情那個真的非常好 ~)
Quick Touch 這個應用的 idea 是受 Touch Bar 激發(fā)的。當然,在我看來,Quick Touch 的功能可以比 Touch Bar 更強大,可以遠程控制、自定義命令(不用等應用適配 Touch Bar)、幾乎可以執(zhí)行所有 MacBook 的操作。
Quick Touch 的功能
Quick Touch 的 github 地址 :https://github.com/xurunkang/QuickTouch
目前的 Quick Touch 界面是十分簡陋的,不過功能基本都實現(xiàn)。
具體功能功能可以參考 Quick Touch 介紹,也可以看演示視頻 Quick Touch 演示
Quick Touch 的實現(xiàn)
大體思路:利用局域網(wǎng)的 socket 連接,iOS 設(shè)備與 MacBook 之間通過 UDP 發(fā)送信息。
需要解決的問題有:
- Mac 切換 app 要及時通知 iPhone,iPhone 再相應地切換每個 app 對應的快捷鍵
Mac 提供了系統(tǒng)通知 NSWorkspaceDidActivateApplicationNotification 來使得這一功能實現(xiàn)
Mac 發(fā)送通知,這里只是監(jiān)聽了切換應用的事件,有更多通知可以監(jiān)聽。需要監(jiān)聽更多事件可以進入 NSWorkspace.h 來查看通知的名字。
// 監(jiān)聽事件
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(sendMacInfos) name:NSWorkspaceDidActivateApplicationNotification object:nil];
#pragma mark - Send Mac Infos
- (void)sendMacInfos{
NSDictionary *macInfos = @{
@"currentAppName":[NSWorkspace sharedWorkspace].frontmostApplication.localizedName,
};
NSData *macInfosData = [NSJSONSerialization dataWithJSONObject:macInfos options:NSJSONWritingPrettyPrinted error:nil];
[_udpSocket sendData:macInfosData toHost:QTHOST port:QTSENDPORT withTimeout:1.0 tag:0];
}
iOS 接收信息
#pragma mark - GCDAsyncUdpSocketDelegate
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data fromAddress:(NSData *)address withFilterContext:(id)filterContext{
NSDictionary *macInfos = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
_appNameLabel.text = macInfos[@"currentAppName"];
[_appQTTableView reloadData];
}
- iOS 控制 Mac 端的命令
由于這里涉及操作過多,就簡單介紹一下,詳細可以看 [Github / QuickTouch](<https://github.com/xurunkang/QuickTouch) 的源碼。
-
執(zhí)行快捷鍵:可以使用
CGEventCreateKeyboardEvent來創(chuàng)建鍵盤事件,從而執(zhí)行應用的快捷鍵。// 創(chuàng)建點擊鍵盤事件 CGEventRef eventDown, eventUp; eventDown = CGEventCreateKeyboardEvent(nil, keyCode, YES); eventUp = CGEventCreateKeyboardEvent(nil, keyCode, NO); CGEventPost(kCGHIDEventTap, eventDown); sleep(0.0001); CGEventPost(kCGHIDEventTap, eventUp); CFRelease(eventUp); CFRelease(eventDown); 輸出命令:如
git log / pwd,原理同上。-
點擊 Menu Bar 的功能:由于某些功能并沒有快捷鍵,所以要操作 Menu Bar,這里是使用 Apple Script。
// 創(chuàng)建點擊 Menu Bar 事件 NSString *scriptStr = [NSString stringWithFormat:@"tell application \"System Events\" to tell process \"%@\"\ \nset frontmost to true\ \nclick menu item \"%@\" of menu \"%@\" of menu bar %ld\ \nend tell",appName,item,menu,(long)menuBar]; NSAppleScript *clickMenuBarItemScript = [[NSAppleScript alloc] initWithSource:scriptStr]; [clickMenuBarItemScript executeAndReturnError:nil]; -
系統(tǒng)設(shè)置: 如亮度調(diào)節(jié)/啟動 app,則需要使用系統(tǒng)中的 API
// 調(diào)節(jié)系統(tǒng)亮度 io_iterator_t iterator; kern_return_t result = IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching("IODisplayConnect"), &iterator); if (result == kIOReturnSuccess) { io_object_t service; while ((service = IOIteratorNext(iterator))) { IODisplaySetFloatParameter(service, kNilOptions, CFSTR(kIODisplayBrightnessKey), level); IOObjectRelease(service); return; } } // 啟動 app [[NSWorkspace sharedWorkspace] launchApplication:name];
- 自定義命令
-
自定義鍵盤事件:QTKey 中提供了三個方法使用
+ (void)pressNormalKey:(CGKeyCode) keyCode; + (void)pressNormalKey:(CGKeyCode)keyCode withFlag:(NSString *)flag; + (void)pressNormalKey:(CGKeyCode) keyCode withFlags:(NSArray *)flags; -
自定義系統(tǒng)設(shè)置:QTSystemSetting 中提供了一系列方法
// 設(shè)置系統(tǒng)亮度 + (void)setSystemBrightness:(float)level; // 設(shè)置/獲取系統(tǒng)音量 + (void)setSystemVolume:(int)level; + (SInt32)getSystemVolume; // 使 Mac 休眠 + (void)sleepWithDelay:(int)delay; + (void)sleepNow; // 獲取某個 APP menuItem 的全部名稱 + (void)fetchAllMenuItemNameOfApp:(NSString *)appName; // 模擬點擊 MenuItem + (void)clickMenuItem:(NSString *)item ofMenu:(NSString *)menu ofMenuBar:(NSInteger)menuBar ofApplication:(NSString *)appName; // 模擬點擊 SubMenuItem + (void)clickSubMenuItem:(NSString *)subItem ofMenuItem:(NSString *)item ofMenu:(NSString *)menu ofMenuBar:(NSInteger)menuBar ofApplication:(NSString *)appName; // 啟動某個 APP + (void)launchApp:(NSString *)name;
-