【发布时间】:2017-06-21 15:44:42
【问题描述】:
我正在尝试将以下 Objective-C 方法转换为 Swift 3。 目标是为第 0 层中的所有“屏幕上”窗口元素(桌面元素除外)获取一个唯一进程标识符数组 (kCGWindowOwnerPID)。
我的 Obj-C 方法使用 NSSet 从使用 NSPredicate 过滤的 NSArray 中删除重复的 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 keys, 和重复的 PID:
/// - 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]
我已经能够部分到达那里,但我无法从filtered 数组中提取一组 PID。此尝试迭代一个数组以构建第二个数组,这确实有效,但仍然存在重复的 PID - 我可以消除它,但我正在尝试找到实现原始 Goal 的最佳方法。
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 数组,我尝试返回:
filtered["kCGWindowOwnerPID"]
由于错误而无法编译:“Type 'NSArray?'没有下标成员”
我希望创建一些更简洁的东西,比如漂亮的 Objective-C 示例 :-)。今晚我会再试一次,并专注于使用相当于NSSet 的 Swift3 来消除重复。
任何有关从CGWindowListCopyWindowInfo() 获取唯一进程标识符数组的最佳方法的见解将不胜感激。
【问题讨论】:
标签: objective-c arrays swift3 nspredicate core-foundation