如何从Swift中的CGWindowListCopyWindowInfo获取唯一PID数组

时间:2017-06-21 15:44:43

标签: objective-c arrays swift3 nspredicate core-foundation

我正在尝试将以下Objective-C方法转换为 Swift 3 目标是为所有"在屏幕上获取唯一进程标识符(kCGWindowOwnerPID)的数组"第0层中的窗口元素,不包括桌面元素。

我的Obj-C方法使用NSSet从使用NSArray

过滤的NSPredicate中移除重复的PID
+ (NSArray*)filteredProcessIndentifiers
{
    pid_t myPid = [[NSProcessInfo processInfo] processIdentifier];

    NSArray *windowList = (id)CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly
                                 | kCGWindowListExcludeDesktopElements,
                                   kCGNullWindowID);

    NSArray *uniquePidArray = [[NSSet setWithArray:[
                    [(id)windowList filteredArrayUsingPredicate:
                        [NSPredicate predicateWithFormat:@"(kCGWindowLayer == 0 && kCGWindowOwnerPID != %d)", myPid]]
                    valueForKey:@"kCGWindowOwnerPID"]]
                    allObjects];

    if (windowList) {
        CFRelease(windowList);
    }

    return uniquePidArray;
}

Swift 3 示例用于获取已过滤的元素数组(在第0层而非myPid),但此测试包含 all {{1 },重复的PID:

keys

/// - returns: Array of WindowInfo dictionaries. func windowListFiltered() throws -> [AnyObject] { var windowListArray: CFArray? let options = CGWindowListOption(arrayLiteral: CGWindowListOption.excludeDesktopElements, CGWindowListOption.optionOnScreenOnly) let filterPredicate = NSPredicate(format: "(kCGWindowLayer == 0 && kCGWindowOwnerPID != %d)", getpid()) windowListArray = CGWindowListCopyWindowInfo(options, kCGNullWindowID) let filtered = (windowListArray as NSArray?)?.filtered(using: filterPredicate) return (filtered as [AnyObject]?)! } 方法结果产生:

windowListFiltered()

我需要的是一个像:

的数组
[{
    kCGWindowAlpha = 1;
    kCGWindowBounds =     {
        Height = 436;
        Width = 770;
        X = 525;
        Y = 313;
    };
    kCGWindowIsOnscreen = 1;
    kCGWindowLayer = 0;
    kCGWindowMemoryUsage = 1072;
    kCGWindowName = Debug;
    kCGWindowNumber = 213;
    kCGWindowOwnerName = Finder;
    kCGWindowOwnerPID = 453;
    kCGWindowSharingState = 1;
    kCGWindowStoreType = 1;
}, {
    kCGWindowAlpha = 1;
    kCGWindowBounds =     {
        Height = 537;
        Width = 380;
        X = 61;
        Y = 354;
    };
    kCGWindowIsOnscreen = 1;
    kCGWindowLayer = 0;
    kCGWindowMemoryUsage = 1072;
    kCGWindowName = Documents;
    kCGWindowNumber = 3416;
    kCGWindowOwnerName = Finder;
    kCGWindowOwnerPID = 453;
    kCGWindowSharingState = 1;
    kCGWindowStoreType = 1;
}, {
    kCGWindowAlpha = 1;
    kCGWindowBounds =     {
        Height = 22;
        Width = 1414;
        X = 118;
        Y = 28;
    };
    kCGWindowIsOnscreen = 1;
    kCGWindowLayer = 0;
    kCGWindowMemoryUsage = 128208;
    kCGWindowName = "swift3 - Cannot subscript a value of type [[String:Any]] with an index of type 'String' - Swift 3 - Stack Overflow";
    kCGWindowNumber = 7798;
    kCGWindowOwnerName = WindowMizer;
    kCGWindowOwnerPID = 495;
    kCGWindowSharingState = 1;
    kCGWindowStoreType = 2;
}]

我已经能够在那里获得分数,但我无法从[453,495] 数组中提取PID数组。这个尝试遍历一个数组来构建第二个数组,这确实有效,但仍然有重复的PID - 我可以消除,但我试图找到完成原始目标的最佳方法。

filtered

简单来说,考虑到我有func filteredProcessIndentifiers() throws -> [Int] { var processIds:[Int] = [] var windowListArray: CFArray? let options = CGWindowListOption(arrayLiteral: CGWindowListOption.excludeDesktopElements, CGWindowListOption.optionOnScreenOnly) let filterPredicate = NSPredicate(format: "(kCGWindowLayer == 0 && kCGWindowOwnerPID != %d)", getpid()) windowListArray = CGWindowListCopyWindowInfo(options, kCGNullWindowID) let filtered = (windowListArray as NSArray?)?.filtered(using: filterPredicate) as? [[ String : Any]] for dict in filtered! { processIds.append((dict["kCGWindowOwnerPID"] as! Int)) } return processIds } 数组,我试图返回:

filtered

因错误而无法编译:"输入' NSArray?'没有下标成员"

我希望创建一些像美丽的Objective-C例子一样简洁的东西:-)。今晚我会再次尝试使用相当于filtered["kCGWindowOwnerPID"] 的Swift3来消除重复。

非常感谢有关从NSSet获取唯一进程标识符数组的最佳方法的任何见解。

1 个答案:

答案 0 :(得分:0)

函数filteredProcessIndentifiers内的for循环将其更改为:

for diction in filtered! {
    let test = diction as? Dictionary<String,Any>
    if let item = test{
         print("testa: \(String(describing: item["kCGWindowOwnerPID"]))")
    }
}

谢谢。我已经试图解决这个问题差不多两天了,遇到你的问题给了我这个想法并且它有效!谢谢你。