How to get Array of Unique PIDs from CGWindowListCopyWindowInfo in Swift - objective-c

I am trying to convert the following Objective-C method to Swift 3. The goal is to obtain an array of unique process identifiers (kCGWindowOwnerPID) for all "onscreen" window elements in layer 0, excluding desktop elements.
My Obj-C method uses NSSet to remove duplicate PIDs from an NSArray that is filtered using an NSPredicate
+ (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;
}
This Swift 3 example works to get a filtered array of elements (in layer 0 and not myPid), however this test contains all keys, and duplicate PIDs:
/// - 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]?)!
}
The windowListFiltered() method result produces:
[{
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;
}]
What I need is an Array like:
[453,495]
I have been able to get part-way there, but I am unable to pull an array of PIDs from the filtered array. This attempt iterates through one array to build a second array, which does work, but there are still duplicate PIDs - which I can eliminate, but I am trying to find the best way to accomplish the original 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
}
In simplest terms, considering I have the filtered array, I tried to return:
filtered["kCGWindowOwnerPID"]
which won't compile due to error: "Type 'NSArray?' has no subscript members"
I am hoping to create something a little more succinct like the beautiful Objective-C example :-). I'll try again tonight and concentrate on using a Swift3 equivalent to NSSet in order to eliminate duplicates.
Any insight on the best way to obtain an array of unique process identifiers from CGWindowListCopyWindowInfo() would be greatly appreciated.

The for loop inside the function filteredProcessIndentifiers change it to this:
for diction in filtered! {
let test = diction as? Dictionary<String,Any>
if let item = test{
print("testa: \(String(describing: item["kCGWindowOwnerPID"]))")
}
}
Thank you. I've been trying to figure this out for almost two days and coming across your question gave me this idea and it worked! So thank you.

Related

Loop over path points in Photoshop

I'm trying to iterate over a create path in Photoshop finding out the anchor points position etc
var srcDoc = app.activeDocument;
// create the array of PathPointInfo objects
var lineArray = new Array();
lineArray.push(new PathPointInfo());
lineArray[0].kind = PointKind.CORNERPOINT;
lineArray[0].anchor = new Array(20, 160);
lineArray[0].leftDirection = [35, 200];
lineArray[0].rightDirection = lineArray[0].anchor;
lineArray.push(new PathPointInfo());
lineArray[1].kind = PointKind.CORNERPOINT;
lineArray[1].anchor = new Array(20, 40);
lineArray[1].leftDirection = lineArray[1].anchor;
lineArray[1].rightDirection = [220, 260];
// create a SubPathInfo object, which holds the line array in its entireSubPath property.
var lineSubPathArray = new Array();
lineSubPathArray.push(new SubPathInfo());
lineSubPathArray[0].operation = ShapeOperation.SHAPEXOR;
lineSubPathArray[0].closed = false;
lineSubPathArray[0].entireSubPath = lineArray;
//create the path item, passing subpath to add method
var myPathItem = srcDoc.pathItems.add("A Line", lineSubPathArray);
for (var i = 0; i < lineSubPathArray[0].entireSubPath.length; i++)
{
var b = lineSubPathArray[0].entireSubPath[i].anchor;
alert(b);
}
This works fine, but instead of creating the path and finding out it's information I want to loop over each path and get the same. This should be the same as the loop above only without explicitly calling lineSubPathArray and its parts.
for (var i = 0; i < srcDoc.pathItems[0].subPathItems.pathPoints.length; i++) // wrong I think
{
var b = srcDoc.pathItems[0].entireSubPath[i].anchor; // wrong
alert(b);
}
Almost: you need to iterate through subPathItems which consist of pathPoints:
var srcDoc = activeDocument;
var workPath = srcDoc.pathItems[0];
var i, k, b;
for (i = 0; i < workPath.subPathItems.length; i++) {
for (k = 0; k < workPath.subPathItems[i].pathPoints.length; k++) {
b = workPath.subPathItems[i].pathPoints[k].anchor;
alert(b);
}
}

How to efficiently loop through multiple nested NSDictionaries and compare values?

I have the following structure in an NSDictionary that I got after parsing the XMl using XMl reader from here http://troybrant.net/blog/2010/09/simple-xml-to-nsdictionary-converter/:
{
Document = {
Page = (
{
TextLR = {
Line = {
LineProps = {
applyBreakingRules = true;
autoDecimalTabPos = 0;
breakJust = BreakOptimal;
direction = ES;
hyphenationZone = 0;
kindAlign = Left;
kindJust = FullInterWord;
left = 0;
presSuppressWiggle = true;
rightBreak = 0;
rightJustify = 0;
text = "\n\t\n\t\t\n\t\t\t\n\t\t\t\t";
treatHyphenAsRegular = true;
};
Text = {
text = "\n\t\t\t\tHello ";
};
betweenBottom = false;
betweenTop = false;
bottomEnable = false;
break = EndPara;
cpLim = 12;
cpStart = 0;
direction = ES;
doc = Main;
firstLineCp = true;
};
bottom = 114115;
cpLim = 12;
cpStart = 0;
doc = Main;
left = 0;
right = 2438349;
text = "\n\t\t";
top = 0;
};
cpLim = 81963072;
fBuggyJust = false;
fEmptyPage = false;
fHasBubbles = false;
fSlicedPage = false;
height = 3448422;
marginBottom = 3448422;
},
{
TextLR = {
Line = {
LineProps = {
applyBreakingRules = true;
autoDecimalTabPos = 0;
breakJust = BreakOptimal;
direction = ES;
hyphenationZone = 0;
kindAlign = Left;
kindJust = FullInterWord;
left = 0;
presSuppressWiggle = true;
rightBreak = 0;
rightJustify = 0;
text = "\n\t\n\t\t\n\t\t\t\n\t\t\t\t";
treatHyphenAsRegular = true;
};
Text = {
text = "\n\t\t\t\tHello SO ";
};
betweenBottom = false;
betweenTop = false;
bottomEnable = false;
break = EndPara;
cpLim = 12;
cpStart = 0;
direction = ES;
doc = Main;
firstLineCp = true;
};
bottom = 114115;
cpLim = 12;
cpStart = 0;
doc = Main;
left = 0;
right = 2438349;
text = "\n\t\t";
top = 0;
};
cpLim = 81963072;
fBuggyJust = false;
fEmptyPage = false;
fHasBubbles = false;
fSlicedPage = false;
height = 3448422;
marginBottom = 3448422;
}
);
doc = "simple1.htm";
xdpi = 72;
xmlns = "http://apple/sites;
"xmlns:xsi" = "http://www.w3.org/2001/XMLSchema-instance";
"xsi:schemaLocation" = "xmlns = "http://apple/sites/Dump.xsd";
ydpi = 72;
};
}
I have been struggling to iterate through this nested NSDictionary and extract each attribute to compare with another NSDictionary of similar structure. The dictionaries can be somewhat dynamic, as in there might be additional levels of nesting for different xml files but the dictionaries to compare are of exact similar structure with same tags. Is there a way to iterate and create nested dictionaries on the go and then have parallel loops going so that I can extract the values and compare with between 2 NSDictionaries? I have tried the following code, but I am stuck in finding a good way to make it create dictionaries dynamically at the same time compare values/attributes with another dictionary. Help is much appreciated.
NSArray *arrPages = [[_xmlDictionary_master objectForKey:#"Document"] objectForKey:#"Page"];//this would return the array of Page dictionaries
for(int i=0;i<[arrPages count];i++){
NSDictionary *aPage = [arrStation objectAtIndex:i];
NSLog(#"id = %#",[aStation objectForKey:#"id"]);
}
Above code returns 2 Nested key/value pairs which in turn have multiple nested dictionaries. I am finding it hard to know which value has nesting and which doesnt during run time.
First tip: Refactor your data so that this isn't such a difficult operation! If that's not possible there's a few things you can try.
Rather than a "for loop", use:
[arrStation enumerateObjectsWithOptions: NSEnumerationConcurrent
usingBlock: ^(NSDictionary *aPage, NSUInteger idx, BOOL *stop) {
// Code here for compare
}];
That may perform your operations in parallel.
Another technique is using GCD. Using a dispatch_async, then a dispatch_apply can achieve something very similar.
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_apply([arrStation count], dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t idx) {
// Work here
});
});
Spend some time reading through the Concurrency Programming Guide. It's a great way to understand what options are available and how they work.

Swift RC4 vs. Objective-C RC4 Performance

I have been trying to rewrite a Rc4-algorithm from objective-c to swift, to test out apples(now old) claims, about it running a lot faster.
However there must be somewhere that I am doing something horribly wrong with these times I am getting
This is the objective c code:
+(NSString*)Rc4:(NSString*)aInput key:(NSString *)aKey {
NSMutableArray *iS = [[NSMutableArray alloc] initWithCapacity:256];
NSMutableArray *iK = [[NSMutableArray alloc] initWithCapacity:256];
for (int i = 0; i <256;i++){
[iS addObject:[NSNumber numberWithInt:i]];
}
for(short i=0;i<256;i++){
UniChar c = [aKey characterAtIndex:i%aKey.length];
[iK addObject:[NSNumber numberWithChar:c]];
}
int j=2;
for (int i=0; i<255;i++){
int is = [[iS objectAtIndex:i] intValue];
UniChar ik = (UniChar)[[iK objectAtIndex:i]charValue];
j= (j+is+ik)%256;
NSNumber *temp = [iS objectAtIndex:i];
[iS replaceObjectAtIndex:i withObject:[iS objectAtIndex:j]];
[iS replaceObjectAtIndex:j withObject:temp];
}
int i =0;
j=0;
NSString *result = aInput;
for (short x=0;x<[aInput length]; x++){
i = (i+1)%256;
int is = [[iS objectAtIndex:i]intValue];
j=(j+is)%256;
int is_i = [[iS objectAtIndex:i]intValue];
int is_j = [[iS objectAtIndex:j]intValue];
int t= (is_i+is_j)%256;
int iY = [[iS objectAtIndex:t]intValue];
UniChar ch = (UniChar)[aInput characterAtIndex:x];
UniChar ch_y=ch^iY;
//NSLog(ch);
//NSLog(iY);
result = [result stringByReplacingCharactersInRange:NSMakeRange(x,1) withString:
[NSString stringWithCharacters:&ch_y length:1] ];
}
[iS release];
[iK release];
return result;
}
This runs pretty fast compiling with -O3 I get times of:
100 runs:0.006 seconds
With key: 6f7e2a3d744a3b5859725f412f (128bit)
and input: "MySecretCodeToBeEncryptionSoNobodySeesIt"
This is my attempt to implement it in the same way using Swift:
extension String {
subscript (i: Int) -> String {
return String(Array(self)[i])
}
}
extension Character {
func unicodeValue() -> UInt32 {
for s in String(self).unicodeScalars {
return s.value
}
return 0
}
}
func Rc4(input:String, key:String)-> String{
var iS = Array(count:256, repeatedValue: 0)
var iK = Array(count:256, repeatedValue: "")
var keyLength = countElements(key)
for var i = 0; i < 256; i++ {
iS[i] = i;
}
for var i = 0; i < 256 ; i++ {
var c = key[i%keyLength]
iK[i] = c;
}
var j = 2
for var i = 0; i < 255; i++ {
var iss = iS[i]
var ik = iK[i]
// transform string to int
var ik_x:Character = Character(ik)
var ikk_xx = Int(ik_x.unicodeValue())
j = (j+iss+ikk_xx)%256;
var temp = iS[i]
iS[i] = iS[j]
iS[j] = temp
}
var i = 0
j=0
var result = input
var eles = countElements(input)
for var x = 0 ; x<eles ; x++ {
i = (i+1)%256
var iss = iS[i]
j = (j+iss)%256
var is_i = iS[i]
var is_j = iS[j]
var t = (is_i+is_j)%256
var iY = iS[t]
var ch = (input[x])
var ch_x:Character = Character(ch)
var ch_xx = Int(ch_x.unicodeValue())
var ch_y = ch_xx^iY
var start = advance(result.startIndex, x)
var end = advance(start,1);
let range = Range(start:start, end:end)
var maybestring = String(UnicodeScalar(ch_y))
result = result.stringByReplacingCharactersInRange(range, withString:maybestring)
}
return result;
}
I have tried to implement it so it looks as much as the objective-c version as possible.
This however gives me these horrible times, using -O
100 runs: 0.5 seconds
EDIT
Code should now run in xcode 6.1 using the extension methods I posted.
I run it from terminal like this:
xcrun swiftc -O Swift.swift -o swift
where Swift.swift is my file, and swift is my executable
Usually claims of speed don't really apply to encryption algorithms, they are more for what I usually call "business logic". The functions on bits, bytes, 16/32/64 bit words etc. are usually difficult to optimize. Basically encryption algorithms are designed to be dense operations on these data structures with relatively few choices that can be optimized away.
Take for instance Java. Although infinitely faster than most interpreted languages it really doesn't compare well with C/C++, let alone with assembly optimized encryption algorithms. The same goes for most relatively small algebraic problems.
To make things faster you should at least use explicit numeric types for your numbers.
After excessive testing of the code, i have narrowed it down to what is making my times ultra slow.
If i comment out this code, so that the iK array just contains its initial value. i go from a runtime of 5 seconds to 1 second. Which is a significant increase.
for var i = 0; i < 256 ; i++ {
var c = key[i%keyLength]
iK[i] = c;
}
The problem is with this part:
var c = key[i%keyLength]
There is no "characterAtIndex(int)" method in Swift, therefore i do this as a workaround to get the characterAtIndex. I do it using my extension:
extension String {
subscript (i: Int) -> String {
return String(Array(self)[i])
}
}
But essentially it is the same as this:
var c = Array(key)[i%keyLength]
Instead of the O(1) - (constant time) of this operation in objective-c, we are getting a running time of O(n).

Call method only on change in visible windows

I need to call a method every time there is a visible change in the currently viewable system windows. For example, I'm getting the full visible window list with:
CFArrayRef openWindows =(CGWindowListCreate(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID));
This will return an array such as:
{
kCGWindowAlpha = 1;
kCGWindowBounds = {
Height = 713;
Width = 1279;
X = 1;
Y = 22;
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = 0;
kCGWindowMemoryUsage = 3772468;
kCGWindowName = "Stack Overflow";
kCGWindowNumber = 7138;
kCGWindowOwnerName = "Google Chrome";
kCGWindowOwnerPID = 49972;
kCGWindowSharingState = 1;
kCGWindowStoreType = 2;
}
Due to the kCGWindowMemoryUsage value constantly changing, I cannot simply compare a previously stored CFArrayRef with the current one.

NSDictionary parsing howto

I have an NSDictionary that when printed looks like this
(
{
"current_game" = 1;
"fb_id" = 1;
"game_status" = 1;
},
{
"current_game" = 4;
"fb_id" = 2;
"game_status" = 1;
},
{
"current_game" = "";
"fb_id" = 3;
"game_status" = "";
},
{
"current_game" = "";
"fb_id" = 4;
"game_status" = "";\
}
)
When I loop it like
for (int i=0; i < [responseDict count]; i++) {
}
How can I access fb_id = 1 for example?
objectAtIndex:i doesn't seem to exist and there is no key there either.
Thanks,
Tee
Ah I figured out how to do it.
So for the looping use this instead
for (iNSDictionary *status in responseDict) {
}
That way then you can use [status objectForKey:#"fb_id"] to access.
Thanks,
Tee