我正在尝试将以下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
获取唯一进程标识符数组的最佳方法的任何见解。
答案 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"]))")
}
}
谢谢。我已经试图解决这个问题差不多两天了,遇到你的问题给了我这个想法并且它有效!谢谢你。