How to get window id from the title by swift3 - swift3

How can I get a CGWindowID from the title of it?
I thought I can get list of titles by this code
let options = CGWindowListOption(arrayLiteral: CGWindowListOption.excludeDesktopElements, CGWindowListOption.optionOnScreenOnly)
let windowListInfo = CGWindowListCopyWindowInfo(options, CGWindowID(0))
let infoList = windowListInfo as NSArray? as? [[String: AnyObject]]
https://stackoverflow.com/a/31367468/1536527
But it seems there is no info for title of the windows.
How can I get CGWindowID or any info to specify a window by title?

Actually the code snippet you posted seems to work for me. All I did was to iterate over the dictionary and find the window info for a given window title.
Here is the code:
func getWindowInfo(pname: String) -> Dictionary<String, AnyObject> {
var answer = Dictionary<String, AnyObject>()
let options = CGWindowListOption(arrayLiteral: CGWindowListOption.optionOnScreenOnly)
let windowListInfo = CGWindowListCopyWindowInfo(options, CGWindowID(0))
let infoList = windowListInfo as NSArray? as? [[String: AnyObject]]
infoList?.forEach{eachDict in
eachDict.keys.forEach{ eachKey in
if (eachKey == "kCGWindowName" && eachDict[eachKey] != nil ){
let name = eachDict[eachKey] as? String ?? ""
print (name)
if ( name == pname){
print("******** Found **********")
answer = eachDict as! Dictionary<String, AnyObject>
}
}
print(eachKey , "-->" , eachDict[eachKey])
}
}
return answer
}
With the above function, I am able to get a window's details, including name for example.
I hope it works for you too.

Related

Getting nil response while passing string to another view controller - Swift3

In FirstViewController i'm fetching the response from JSON and want to pass that fetched response to another view controller.Below is the code which i have used so far for parsing and passing the response.
FirstViewController
var fn:String! //globally declared variable
code i have tried for parsing in FirstViewController
do {
let detailsDictionary:NSDictionary = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! Dictionary<String, AnyObject> as NSDictionary
print(detailsDictionary)
let details = detailsDictionary["Data"] as! [[String:AnyObject]]
print(details)
for dtl in details
{
self.fn = dtl["Father_Name"] as? String ?? "NA"
print(self.fn) //here i'm getting the exact value from JSON
}
}
}
SecondViewController
In SecondViewController there is a Label called profile_name and want to set that parsed string(fn) as Label's text. for that i declared another variable as global.
var pname:String!
below is the code i have used to fetch the value from FirstViewController.
viewDidLoad()
{
let othervc = FirstViewController()
self.pname = othervc.fn
self.profile_name.text = self.pname
}
Problem : I tried my best efforts to get the desired output but i'm getting nil response.
Please Help.
In Second ViewController
let strName:String!
In First ViewController
let strOne = "This is for testing"
let objstory = self.storyboard?.instantiateViewController(withIdentifier: "yout Secoond ViewController Storybord ID") as! YourSecondViewControllerName
objstory.strNam = strOne
self.navigationController?.pushViewController(objstory, animated: true)
Your updated code just won't work.
let othervc = FirstViewController()
creates a new instance of FirstViewController (not the one that got the JSON).
You should be handling it something like this:
In FirstViewController
let fn = dtl["Father_Name"] as? String ?? "NA"
let svc = SecondViewController() // Or maybe instantiate from Storyboard, or maybe you already have a reference to it
svc.pname = fn
present(svc, animated: true, completion: nil)
Then in SecondViewController
override func viewDidLoad() {
super.viewDidLoad()
profile_name.text = pname
}
I'd suggest you take some time out and re-read Apple's View Controller programming guide.
Original Answer
The problem you have here…
vcvalue.profile_name.text = fn
is that profile_name is nil as the view for the view controller hasn't been loaded at this point.
You should handle this by creating a property in LeftSideMenuViewController
var name: String?
Then set
vcvalue.name = fn
And then in LeftSideMenuViewController
override func viewDidLoad() {
super.viewDidLoad()
profile_name.text = name
}
Also, some basic tips…
Don't force unwrap (!) apart from IBOutlets. You may have to write a bit more code, but you will reduce crashes.
Make #IBOutlets private - this will prevent you accidentally assigning to them as you are now
If you're overriding any viewWill/DidDis/Appear methods, you must call super at some point.
You need to re-read the section on switch/case
So this…
let a = indexPath.row
switch(a)
{
case 0 :
if(a == 0)
{
return 45
}
break
etc
could just be…
switch indexPath.row {
case 0...4:
return 45
case 5:
return 50
default:
break
}

Swift 3 Change color of selected text in UITextView

I have just changed my code to Swift 3 from swift 2.3. The following code is working fine with swift 2.3 but there is no effect with swift 3.
I want to develop a customise text editor. And let user to select text and change its color. For that i am using this code.
let selectedRange = textView.selectedRange
let currentAttr = textView.textStorage.attributes(at: selectedRange.location, effectiveRange: nil)
var attrName = NSForegroundColorAttributeName
if !isForeGround{
attrName = NSBackgroundColorAttributeName
}
if currentAttr[attrName] == nil || currentAttr[attrName] as! UIColor != selectedUIColor{
let dict = [attrName:selectedUIColor]
let currentFont = currentAttr[NSFontAttributeName]
let fontDescriptor = (currentFont! as AnyObject).fontDescriptor
let updatedFont = UIFont(descriptor: fontDescriptor!, size: 0.0)
let dict2 = [NSFontAttributeName: updatedFont]
textView.textStorage.beginEditing()
if currentAttr.count>0{
textView.textStorage.addAttributes(dict, range: selectedRange)
}else{
textView.textStorage.setAttributes(dict, range: selectedRange)
}
textView.textStorage.addAttributes(dict2, range: selectedRange)
textView.textStorage.endEditing()
}
Runs successfully but there is no effect on text color.
This worked for me.
First you need to catch your selected text, with:
let selectedText = textView.selectedRange
Then, you create the attribute:
let myAttribute = [ NSForegroundColorAttributeName: selectedUIColor]
And lastly:
textView.textStorage.addAttributes(myAttribute, range: selectedText)
This must be in an Action called by any sender
Hope it works also for you!
Regards
Selected text can be changed with
self.textView.tintColor = .red

Cannot call value of non function type '[String:AnyObject]'

I'm facing the issue in Swift 3
I have following piece of code:
do{
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String : AnyObject]
if let datasFromJson = json["blog"] as? [[String:AnyObject]] {
for dataFromJson in datasFromJson{
if let title = dataFromJson("title")! as? String {
article.author = author
}
self.articles?.append(article)
}
}
I get this error when I try to cast title as string
Typo (brackets, not parentheses):
dataFromJson["title"] as? String // no exclamation mark after the closing bracket
Notes:
.mutableContainers is useless in Swift.
In Swift 3 JSON dictionary is [String:Any]
Is title used at all? Or is it another typo title vs. author?

Cannot subscript a value of type [[String:Any]] with an index of type 'String' - Swift 3

I am converting my code in Swift 3 and I am getting this error on the line:
let dicArray = serviceProvicedListArray?.objectEnumerator().allObjects as? [[String:Any]]
let count = dicArray.map({ Int($0["lstActType"] as? String ?? "0")! }).first!
Exception: Cannot subscript a value of type [[String:Any]] with an index of type 'String'
Please let me know where I am going wrong and let me know how I resolve the same.
Also getting error on this line:
let user_id=String(((data as AnyObject).value(forKey: "UserLoginResult") as AnyObject).value(forKey: "UserID") as! Int)
Exception: Optional chain has no effect expression already produced Any?
Does not understand where I am going wrong
Error 3:
if(!((self.serviceProvided!.value(forKey: "Weekly")! as AnyObject).isKind(of: NSNull.self))){
let resultObject = self.serviceProvided!.value(forKey: "Weekly") as! NSDictionary
self.serviceProvicedListArray!.add(resultObject)
let resultObjectItems = self.serviceProvicedListArray!.value(forKey: "lstActType")
//print(resultObjectItems[0].count)
for i in 0..<resultObjectItems[0].count {
//for(var i=0; i<resultObjectItems[0].count; i += 1){
//let resultObjectItem = resultObjectItems[0][i] as! NSDictionary
let resultObjectItem = resultObjectItems[0][i] as AnyObject
self.serviceProvicedList!.add(resultObjectItem)
}
//print(self.serviceProvicedList)
self.serviceProvidedTableView.reloadData()
}
Thanks in advance.
Your dicArray is optional so you need to wrap it with ?(Optional) or !(force) and then call map on it.
let dicArray = serviceProvicedListArray?.objectEnumerator().allObjects as? [[String:Any]]
let count = dicArray?.map({ Int($0["lstActType"] as? String ?? "0")! }).first!
The batter approach is to use guard or if let and wrapped the dicArray.
guard let dicArray = serviceProvicedListArray?.objectEnumerator().allObjects as? [[String:Any]] else {
print("Not array of dictionary")
return
}
guard let count = dicArray.map({ Int($0["lstActType"] as? String ?? "0")! }).first else {
return
}
print(count)
Or you can add both the guard let statement in single guard statement like.
guard let dicArray = serviceProvicedListArray?.objectEnumerator().allObjects as? [[String:Any]],
let count = dicArray.map({ Int($0["lstActType"] as? String ?? "0")! }).first else {
return
}
print(count)
Edit: The reason you are facing this issue is because may be you are using NSDictionary and NSArray, if you use swift's native type it will be a lot easy for you to get/access the value.You can get UserID like this way.
guard let dict = data as? [String:Any],
let loginDict = dict["UserLoginResult"] as? [String:Any],
let userId = loginDict["UserID"] as? Int else {
return
}
let strUserId = String(userId)
Edit: The problem is you need to tell complier the type of objects resultObjectItems array have, so try like this way.
if let resultObjectItems = self.serviceProvicedListArray!.value(forKey: "lstActType") as? [[[String:Any]]] {
for i in 0..<resultObjectItems[0].count {
let resultObjectItem = resultObjectItems[0][i] as AnyObject
self.serviceProvicedList!.add(resultObjectItem)
}
}

ScriptingBridge code errors in Xcode 8.0 and swift 3.0

This is the code I used in Xcode 7.3.1 and that worked fine:
var selectedFiles = NSMutableArray(capacity:1)
let finder: AnyObject! = SBApplication(bundleIdentifier:"com.apple.finder")
let finderObject = finder.selection as! SBObject
let selection: AnyObject! = finderObject.get()
let items = selection.arrayByApplyingSelector(Selector("URL"))
let filteredfiles = (items as NSArray).pathsMatchingExtensions(["ai","pdf","ap","paf","pafsc"])
for item in filteredfiles {
let url = NSURL(string:item ,relativeToURL:nil)
selectedFiles.addObject(url!)
}
This is the code corrected for Xcode 8.0 and that does not work:
the error is generated for the last line
error = Cannot call value of non-function type '[Any]!'
var selectedFiles = NSMutableArray(capacity:1)
let finder: AnyObject! = SBApplication(bundleIdentifier:"com.apple.finder")
let finderObject = finder.selection as! SBObject
if let selection = finderObject.get() as AnyObject?{
let items = selection.array(#selector(getter: NSTextCheckingResult.url))
let filteredfiles = (items as NSArray).pathsMatchingExtensions(["ai","pdf","ap","paf","pafsc"])
for item in filteredfiles {
let url = NSURL(string:item ,relativeToURL:nil)
selectedFiles.addObject(url!)
}
}
I have tried many solutions, but unfortunately cannot find a clue.
I guess this is because Swift 3.0x APIs have changed drastically....
Any help is welcome!
This is a slightly different approach using a couple of native Swift functions for Swift 3
var selectedFiles = [URL]()
let finder : AnyObject = SBApplication(bundleIdentifier:"com.apple.finder")!
let finderObject = finder.selection as! SBObject
if let selection = finderObject.get() as? [SBObject] {
selection.forEach { item in
let url = URL(string: item.value(forKey:"URL") as! String)!
selectedFiles.append(url)
}
let goodExtensions = ["ai","pdf","ap","paf","pafsc"]
let filteredURLs = selectedFiles.filter({goodExtensions.contains($0.pathExtension)})
print(filteredURLs)
}
PS: I highly recommend to use AppleScriptObjC. It's so much easier to use.
PPS: valueForKey is intentionally used because KVC is really needed to get the property value.