Swift: Can't seem to store the resulting place of the placesClient.currentPlace as the class property to use elsewhere - swift

I'm pretty new to this, but I've been managing to stumble my way through to getting the current location of my IOS device...etc The only problem is, I can't seem to get the GMSPlace to stay assigned to the property I declared at the top of my class, which I plan on using in another function.
It works fine when I run a print statement from within the scope of the callback, but when I seem to use the value stored in 'queryPlace', it returns a 'nil'. I'm guessing its a scope and lifetime issue, but I'm not sure if I understand it properly.
Here is the code that I'm having difficulty with understanding why it won't hold the value of 'place':
import UIKit
import CoreLocation
import GoogleMaps
import GooglePlaces
class GoogleMapSearchVC : UIViewController, CLLocationManagerDelegate {
var placeQuery: GMSPlace?
func loadCurrentPosition() {
print("Loading Positions and Coords")
// Invoke Callback method to get GMSPlacesLiklihood
placesClient.currentPlace(callback: { (placeLikelihoodList, error) -> Void in
if let error = error {
print("Pick Place error: \(error.localizedDescription)")
return
}
if let placeLikelihoodList = placeLikelihoodList {
let place = placeLikelihoodList.likelihoods.first?.place
if let place = place {
self.updateMap(newLocation: place)
// updateMap function moves camera to current location.
self.placeQuery = place
// If I print(self.placeQuery) here, it works fine, but later on placeQuery returns nil.
}
}
})
}
func doSomethingWithPlace() {
print(self.placeQuery?coordinate.latitude)
// Returns 'nil'
}
}
Thank you in advance for any help, very much appreciated.

No, there shouldn't be any "lifetime" issues. placeQuery is bound to the lifetime of your view controller instance.
Just a stupid guess (sorry if that was obvious): Are you sure that doSomethingWithPlace() accesses the variable after the callback has returned? Since you're setting it only in the asynchronous callback, the variable will not be set when loadCurrentPosition() returns.
If that's not the issue, here's a debugging tip to find out where this value is set back to nil: You can set a breakpoint at the line of the variable declaration and the debugger will break in the setter. If you're more into "print debugging", you can also add a didSet clause:
var placeQuery: GMSPlace? {
didSet {
print("setting placeQuery from \(oldValue) to \(placeQuery)")
}
}

Related

ApplescriptObjC method with a parameter

When I try to pass a parameter from Swift into an AppleScriptObjC method I get an error in the console saying
unrecognized selector sent to object
I'm not very knowledgeable when it comes to using a Swift-AppleScriptObjC bridge, but I'm using the method set out here.
I can get ApplescriptObjC to return an argument, but the function doesn't work if it has a parameter. So in the below examples, the method/function getPlaylists() works but when I try to call playPlaylist from say the AppDelegate I get the error message.
Applescript file:
script iTunesBridge
property parent : class "NSObject"
to getPlaylists() -- () -> [NSString]
tell application "Music"
set theList to (name of playlists)
return theList
end tell
end getPlaylists
to playPlaylist:plist -- (NSString) -> ()
tell application "Music"
play playlist (plist as string)
end tell
end playPlaylist
end script
Swift file:
import Cocoa
#objc(NSObject) protocol iTunesBridge {
func getPlaylists() -> [NSString]
func choosePlaylist(plist: NSString)
}
I think it's how I've structured playPlaylist in the AppleScript file but I've tried a number of different ways and all result in the same error.
I've found a solution, but have no idea how it works. If anyone could enlighten me I would really appreciate it!
I create two functions in ApplescriptObjC, one to get the playlist, one to set the playlist. In the bridge file, I set a variable that is { get set } and then list the function to set the playlist. In my view controller (where I'm making the changes from) I create an objc dynamic variable which has a get/set. I can then change that variable and it triggers the AppleScript function to change my playlist... Code as such:
Applescript file:
script iTunesBridge
property parent : class "NSObject"
to playlist()
tell application "Music"
return name of current playlist
end tell
end playlist
to setPlaylist:plist -- (NString) -> ()
tell application "Music"
play playlist (plist as string)
reveal current track
end tell
end setPlaylist:
end script
Bridge Swift file:
import Cocoa
#objc(NSObject) protocol iTunesBridge {
var playlist: NSString { get set }
func setPlaylist(plist: NSString)
}
ViewController:
class MainController: NSViewController {
#objc dynamic var currentPlaylist: NSString! {
get { return self.iTunesBridge.playlist }
set(value) { self.iTunesBridge.playlist = value }
}
}
As I say, I have little idea how and why it works and would really appreciate the answer. For instance, even though at no point in swift do I tie var playlist to the function setPlaylist, it knows to connect them. Set must be the magic word...

Error call function (instance member cannot be used)

It's not a duplicate cause with lazy i have an issu too :
"A C function pointer cannot be formed from a closure that captures context"
In my main class I have "detectChangeMidi" but in this code, when I try to call a function I don't understand why I can't.
(i can't use var too, anything of my class)
I'm not expert in swift, then try to explain to me what's going one.
I use the CoreMidi librarie.
UPDATE :
I replace the code by minimaliste code for better entendement.
import Foundation
import CoreMIDI
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
gestionMidi()
//...
}
func gestionMidi() {
//...
let midiNotif:MIDINotifyProc = detectChangeMidi
MIDIClientCreate("Swift3 Test Client" as CFString, midiNotif, nil, &midiClient)
//...
}
func plop(){
print("bla bla bla")
}
let detectChangeMidi: #convention(c) (UnsafePointer<MIDINotification>, UnsafeMutableRawPointer?) -> Swift.Void =
{ midiNotification,unkown in
var notification = midiNotification.pointee
self.plop() //problem here
//...
}
}
Your entire agenda here is misguided; it is not at all obvious what you can be trying to do. You cannot declare a property or function as being convention(c) and also refer to self. But you don't need to! If your goal is to pass a function as a parameter where a C pointer-to-function is expected, just pass the function. Anyway you'll have a much easier time in Swift if you call MIDIClientCreateWithBlock(_:_:_:) instead.
The problem is with the scope as I can judge from the error message.
Also the thing to get attention to is that you're executing plop() in closure, and that requires self.plop().
also midiNotification,unkown in - unkown seems to be a typo.
Check where you declare the function itself. From this snippet it's hard to understand what's your declaration scope.

In Swift, how to determine what property called a function? is it possible?

I have a struct like,
struct LoginPage {
static let usernameField = Element("#username")
}
and I have a class like,
class LoginView {
func enterCredentails () {
LoginPage.usernameField.waitForExist()
}
}
and the Element api looks like
class Element {
init(...) {
...
}
func waitForExist () {
// print("caller property name")
}
}
...here inside waitForExist() I want to get that property name(usernameField) who triggered this method. so that I can print the error and success message dynamically inside waitForExist() based on the property name.
is this possible? is there any workaround for this?
NOTE: I have tried using Mirror to get all the properties(so that I can store and retrieve the key name based on Element), but it is not returning the static properties (Referred). So I am looking for the alternative solution.
Thanks in advance for helping me out!
I'd recommend the simple approach:
func waitForExist(propertyName: String [or possibly make it an enum]) {
// do what needs to be done
}
I'm assuming your properties call this in their didSet or something; just have each one pass the appropriate value to the waitForExist function.
As for the literal answer to your question, you could probably examine the stack using functions like backtrace(), but ehhhhhh... trust me, you don't really want to do that.

How do I execute code once and only once in Swift?

The answers I've seen so far (1, 2, 3) recommend using GCD's dispatch_once thus:
var token: dispatch_once_t = 0
func test() {
dispatch_once(&token) {
print("This is printed only on the first call to test()")
}
print("This is printed for each call to test()")
}
test()
Output:
This is printed only on the first call to test()
This is printed for each call to test()
But wait a minute. token is a variable, so I could easily do this:
var token: dispatch_once_t = 0
func test() {
dispatch_once(&token) {
print("This is printed only on the first call to test()")
}
print("This is printed for each call to test()")
}
test()
token = 0
test()
Output:
This is printed only on the first call to test()
This is printed for each call to test()
This is printed only on the first call to test()
This is printed for each call to test()
So dispatch_once is of no use if we I can change the value of token! And turning token into a constant is not straightforward as it needs to of type UnsafeMutablePointer<dispatch_once_t>.
So should we give up on dispatch_once in Swift? Is there a safer way to execute code just once?
A man went to the doctor, and said "Doctor, it hurts when I stamp on my foot". The doctor replied, "So stop doing it".
If you deliberately alter your dispatch token, then yes - you'll be able to execute the code twice. But if you work around the logic designed to prevent multiple execution in any way, you'll be able to do it. dispatch_once is still the best method to ensure code is only executed once, as it handles all the (very) complex corner cases around initialisation and race conditions that a simple boolean won't cover.
If you're worried that someone might accidentally reset the token, you can wrap it up in a method and make it as obvious as it can be what the consequences are. Something like the following will scope the token to the method, and prevent anyone from changing it without serious effort:
func willRunOnce() -> () {
struct TokenContainer {
static var token : dispatch_once_t = 0
}
dispatch_once(&TokenContainer.token) {
print("This is printed only on the first call")
}
}
Static properties initialized by a closure are run lazily and at most once, so this prints only once, in spite of being called twice:
/*
run like:
swift once.swift
swift once.swift run
to see both cases
*/
class Once {
static let run: Void = {
print("Behold! \(__FUNCTION__) runs!")
return ()
}()
}
if Process.arguments.indexOf("run") != nil {
let _ = Once.run
let _ = Once.run
print("Called twice, but only printed \"Behold\" once, as desired.")
} else {
print("Note how it's run lazily, so you won't see the \"Behold\" text now.")
}
Example runs:
~/W/WhenDoesStaticDefaultRun> swift once.swift
Note how it's run lazily, so you won't see the "Behold" text now.
~/W/WhenDoesStaticDefaultRun> swift once.swift run
Behold! Once runs!
Called twice, but only printed "Behold" once, as desired.
I think the best approach is to just construct resources lazily as needed. Swift makes this easy.
There are several options. As already mentioned, you can initialize a static property within a type using a closure.
However, the simplest option is to define a global variable (or constant) and initialize it with a closure then reference that variable anywhere the initialization code is required to have happened once:
let resourceInit : Void = {
print("doing once...")
// do something once
}()
Another option is to wrap the type within a function so it reads better when calling. For example:
func doOnce() {
struct Resource {
static var resourceInit : Void = {
print("doing something once...")
}()
}
let _ = Resource.resourceInit
}
You can do variations on this as needed. For example, instead of using the type internal to the function, you can use a private global and internal or public function as needed.
However, I think the best approach is just to determine what resources you need to initialize and create them lazily as global or static properties.
For anyone who stumbles on this thread... We ran into a similar situation at Thumbtack and came up with this: https://www.github.com/thumbtack/Swift-RunOnce. Essentially, it lets you write the following
func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated: Bool)
runOnce {
// One-time code
}
}
I also wrote a blog post explaining how the code works, and explaining why we felt it was worth adding to our codebase.
I found this while searching for something similar: Run code once per app install. The above solutions only work within each app run. If you want to run something once across app launches, do this:
func runOnce() {
if UserDefaults.standard.object(forKey: "run_once_key") == nil {
UserDefaults.standard.set(true, forKey: "run_once_key")
/* run once code */
} else {
/* already ran one time */
}
}
If the app is deleted and re-installed, this will reset.
Use NSUbiquitousKeyValueStore for tracking a value across installs and devices as long as user using same appleID.

EXC_BAD_ACCESS (code=2) when using NSNumberFormatter

I'm having a problem, which I can't figure out for the life of me. I've searched the internet, trying to understand Swifts's EXC_BAD_ACCESS, but nothing seemed to help.
The following code is quite long, but most of the time the comments are all the information needed to understand the item of relevance.
I have a class CalculatorController, which contains the following relevant methods and properties:
import UIKit
class CalculatorController: UIViewController {
// the actual `#IBOutlet` which is never accessed directly
#IBOutlet private weak var _mainDisplay: UILabel!
// an instance of `MainDisplayMicroController`
// holds a reference to `_mainDisplay`
// is used to manipulate `_mainDisplay` in a controlled way
private var mainDisplay: MainDisplayMicroController!
override func viewDidLoad() {
super.viewDidLoad()
// connects `mainDisplay` with `_mainDisplay`
mainDisplay = MainDisplayMicroController(label: _mainDisplay)
// sets `_mainDisplay`'s `text` property to "0"
mainDisplay.content = .Number(0)
//...
}
//...
}
In order to manage _mainDisplay in a certain way, I have created a class MainDisplayMicroController, which on the one hand contains a reference to the the UILabel itself, and on the other hand contains methods and properties, which perform actions on the UILabel:
import UIKit
class MainDisplayMicroController {
// used to express what `label.text` is currently showing
private enum DisplayState {
case ShowingNumber
case ShowingConstant
case ShowingErrorMessage
case Unknown
}
// holds the current state of what `label.text` is showing
private var state = DisplayState.Unknown
// used to pass different types of values in and out of this class
enum ContentType {
case Number(Double)
case Constant(String)
case ErrorMessage(String)
case Unknown(Any?)
}
// holds the reference to the label which is being manipulated/managed
private var label: UILabel?
// makes `label`'s `text` property directly accessible, as `label` is `private`
var text: String? {
get {
return label?.text
}
set {
label?.text = newValue
removeLeadingZeros()
transformToInteger()
}
}
// a property to allow controlled retrieval and manipulation of `label.text`
// uses `ContentType` to make clear what the information in `label.text` is/ is supposed to be
var content: ContentType {
get {
switch state {
case .ShowingNumber:
if let string = text {
if let value = NSNumberFormatter().numberFromString(string)?.doubleValue {
return .Number(value)
}
}
case .ShowingConstant:
if let symbol = text {
return .Constant(symbol)
}
case .ShowingErrorMessage:
if let message = text {
return .ErrorMessage(message)
}
default:
break
}
state = .Unknown
return .Unknown(text)
}
set {
switch newValue {
case .Number(let value):
text = "\(value)"
state = .ShowingNumber
removeLeadingZeros()
transformToInteger()
case .Constant(let symbol):
text = symbol
state = .ShowingConstant
case .ErrorMessage(let message):
text = message
state = .ShowingErrorMessage
case .Unknown(let thing):
text = "Error: Passed unknown value: \(thing)"
state = .ShowingErrorMessage
}
}
}
// removes the ".0" from `label.text`, if it is a whole number
private func transformToInteger() {
if state == .ShowingNumber {
switch content {
case .Number(let value):
if round(value) == value {
var doubleString = "\(value)"
if doubleString.rangeOfString("e") == nil {
dropLast(doubleString)
dropLast(doubleString)
}
text = doubleString
}
default:
break
}
}
}
// removes leading "0"s from `label.text` if they are redundant
private func removeLeadingZeros() {
if state == .ShowingNumber {
switch content {
case .Number(let displayedValue):
content = .Number(displayedValue)
default:
break
}
}
}
//...
}
Now, when I run the code I get the following error:
From what I've read on EXC_BAD_ACCESS, the error often occurs when trying to call methods on released objects. I've tried using NSZombieto check the issue, but I didn't find anything (probably due to my incompetence when using NSZombie).
If I try to follow what is happening by logic, I come to following conclusion:
mainDisplay is set successfully in viewDidLoad()
mainDisplay.content is called
in the content's setter the switch-statement executes the .Number case
text and state are successfully set
removeLeadingZeros() is called
the switch-statement accesses content's getter
the switch-statement in content's getter executes the .ShowingNumber case
the if-statements resolve to true, finally trying to evaluate the NSNumberFormatter expression
the EXC_BAD_ACCESS occurs
Does anyone know why this is happening? Does it have to do with me manipulating an #IBOutlet in a different class?
Any help is greatly appreciated!
Here are links to the complete CalculatorController and MainDisplayMicroController.
Update #1:
As #abdullah suggested I have tried directing the NSNumberFormatter expression in to multiple expressions. I still get the error though:
Update #2:
I've removed all references and external classes, to make it as simple as possible, while maintaining the same functionality.
All of the methods and properties defined in MainDisplayMicroController have been moved to CalculatorModel.
These methods and properties now access the original #IBOutlet, not any reference to it.
But still when trying to run it I get EXC_BAD_ACCESS(code=2) at the same line of code.
I'm just super confused, as it can't have anything to do with weird references, or objects being released too soon anymore.
Here's the complete code for the new CalculatorController.
Update #3:
I've removed the NSNumberFormatter line, by changing it to:
Now I get the following error though:
I assume there's some fundamental problem with the code, so I'm scrapping it. But thanks for all the help, and attempts at figuring this out.
Update #4:
This is what I get when adding a breakpoint on throw for all exceptions:
I don't really see anything in that line that can cause a crash. I suggest you do the following:
Make a clean build (clean, nuke your derived data folder, then build) and see if the crash persists
If the crash persists, set a breakpoint on throw for all exceptions to see which operation in the callstack caused the crash, and take it from there
#WarrenBurton is on to something.
Take your line that crashes out of your big class and run it in the playground and it works fine:
let string = "1.213"
if let value = NSNumberFormatter().numberFromString(string)?.doubleValue
{
println("value = \(value)")
}
Displays the result
value = 1.213
Where is your variable "string" defined in your class?
Notice that string is blue, like a keyword, not black, like other local variables.
I'd try local variable string ==> myString
just to know for sure.
Just 'cuz I was seeing the same thing and noticed no one had commented past your last edit (and maybe a fellow Googler for this issue will see this someday):
For both of our situations the issue is infinite recursion - we're calling a method from itself infinitely. That's the bug. The implication in the crash of NSNumberFormatter is a red herring.