Assigning value to a variable from an asynchronous function - swift

I am trying to add a variable in the String class, of type Bool, that if used on a userName as String, is supposed to check Firebase and return true if the username exists and false if not. In the end I am aiming to use it like this:
username.isUserNameAvailable
The problem is that my Firebase function returns data asynchronously. Therefore in my function below, variable isTaken, is assigned a value after variable availability is returned from the function. Is there a way to fix this?
fileprivate extension String {
var isUserNameAvailable : Bool {
var availability : Bool?
DatabaseManager.system.isUserNameTaken(userName: self, completion: {(isTaken) in
availability = !isTaken
print("isTaken = \(isTaken)")
})
print("availability = \(availability)")
return availability!
}
}

You shouldn't try to treat an asynchronous call as something that is already available.
I would suggest having a method that calls a code block when the Firebase request is finished.
Something like this:
fileprivate extension String {
func isUserNameAvailable(completion: (Bool)->()) {
DatabaseManager.system.isUserNameTaken(userName: self, completion:{(isTaken) in
completion(!isTaken)
})
}
}
You would call it like this:
string.isUserNameAvailable { (available) in
//use the variable
}
It's not exactly what you wanted, but it still simplifies the call while showing a bit more clearly that the call is asynchronous.

Related

How to use an array from another class Swift

having a bit of a dilemma here. My method GetData() stores an array in jsondata1. How would I use that array in another class? I already set it as a subclass of Data. Thanks!
class Data {
let parameters = ["test": ViewController().myinfo]
func GetData() {
AF.request("my url", parameters: parameters).responseDecodable(of: Array<JsonData>.self ) { (response) in
let jsondata1 = response.value
// debugPrint(response)
print(jsondata1)
}
}
}
class Testing : Data {
func AnnualTesting() {
//How would I reference jsondata1 here?
debugPrint(jsondata1)
}
}
A few things...see comments.
class Data {
// This kind of thing is the source of more bugs than I can count.
// Are you *sure* you want to create a brand new ViewController that's connected to nothing?
let parameters = ["test": ViewController().myinfo]
// Declare an instance variable so it's visible to the subclass
// (Not sure what data type you want to use here. I'm calling it a String for convenience.)
var jsondata1: String?
func GetData() {
AF.request("my url", parameters: parameters).responseDecodable(of: Array<JsonData>.self ) { (response) in
// Note that this is filled in asynchronously,
// so isn't available as soon as the function is called.
// Currently you have no way of knowing in other code when the result *is* available.
self.jsondata1 = response.value
// debugPrint(response)
print(jsondata1)
}
}
}
class Testing : Data {
func AnnualTesting() {
//How would I reference jsondata1 here?
debugPrint(jsondata1 ?? "Nothing to see here")
}
}
Your declaration of jsondata1 is in scope of some block.
It is not visible from outside.
You have to declare it in interface of class,
just like you did with variable "parameters".
In general you can access variable from another class if it's declared in interface. It can be declared as instance variable or static (class) variable. And you should have instance of class to access instance var and should not have instance to access class / static variable.
Or as you did, via inheritance.

Check for certain statements in Swift closure

I wrote a function which takes a closure as an argument like this:
func doSome(work: () -> Void = { print("sleeping...") } ) {
work()
}
Now I would like to investigate the work done.
Therefore I want to check if the given closure contains any print statements.
Somehow like this:
func doSome(work: () -> Void = { print("doing hard work...") } ) {
work()
if work.contains(print) {
print("we did some hard work there and printed something!")
}
}
How can I achieve that?
EDIT: What I am trying to achieve
An async function tries to connect to an http server - let's call it connect. It takes a closure as its parameter - called finally. As its name already indicates: the closure gets executed after the connecting attempt.
If the connecting attempt succeeds (http response code == 200), I need to call another function ONCE - let's call it so: once.
The connect function therefore looks like this:
func connect(finally: () -> Void = {}) {
httpRepsonse = asyncRequestToServer()
if httpResponse.statusCode == 200 {
once()
}
// and finally:
finally()
}
Other functions call connect and pass over their statements that they need for the connect function to execute finally.
And here comes the problem: there is one function that needs once executed every time, therefore it passes it over in the finally closure. If the connecting now succeeds, once gets called twice.
That's why I wanted to check the given closure already contains the once call, so I could avoid calling it twice.
Interrogating a closure for its contents is not easily done as far as I know.
You could do a workaround (depending on your needs and implementation of course) using one or more Boolean arguments which you would assign when calling the function, if relevant.
For example:
func doSome(work: () -> Void = { print("doing hard work...")}, containsPrint: Bool = false) {
// Call your work closure
work()
// Check conditions
if containsPrint {
print("We printed some stuff")
}
}
I am aware that this is a rather simple solution but it might provide the required functionality.
Use a global variable that you change whenever you print to the console, and check it inside you doSome(work:)
Short answer: You can't. As Alexander says, Swift does not support this. You would have to add some sort of housekeeping, as suggested in Carpsen90's answer.

Swift function can be called only once

What is the simplest way to write a piece of code that can be executed only once?
I know a way but has a problem.
first, I write a Boolean variable that has negative value but can be set to positive and cannot change after that
var hasTheFunctionCalled : Bool = false {
didSet{
hasTheFunctionCalled = true
}
}
and then write the function and the code inside it:
func theFunction(){
if !hasTheFunctionCalled{
//do the thing
}
hasTheFunctionCalled = true
}
but the problem is that the variable can be changed from somewhere else in the scope and this solution doesn't really look so simple and concrete.
A simple solution is to take advantage of lazy variables in the following way:
// Declare your "once-only" closure like this
private lazy var myFunction: Void = {
// Do something once
}()
...
// Then to execute it, just call
_ = myFunction
This ensures that the code inside the myFunction closure is only executed the first time that the program runs _ = myFunction
Edit: Another approach is to use so called "dispatch once tokens". This comes from Objective-C and was available in Swift until Swift 3. It is still possible to make it work, however you will need to add a little bit of custom code. You can find more information on this post -> dispatch_once after the Swift 3 GCD API changes
Edit2: Should be _ = myFunction and not _ = myFunction(), as JohnMontgomery pointed out.
You might use a static bool inside a struct nested into the function itself doing so:
func theFunction(){
struct Holder { static var called = false }
if !Holder.called {
Holder.called = true
//do the thing
}
}
One possible technique is to put the code into the initializer of a static type property, which is guaranteed to be lazily initialized only once (even when accessed across multiple threads simultaneously):
func theFunction() {
struct Once {
static let once = Once()
init() {
print("This should be executed only once during the lifetime of the program")
}
}
_ = Once.once
}
(Compare Singleton in the "Using Swift with Cocoa and Objective-C" reference.)
Example:
print("Call #1")
theFunction()
print("Call #2")
theFunction()
print("Done")
Output:
Call #1
This should be executed only once during the lifetime of the program
Call #2
Done
You can do smth like:
class Once {
var already: Bool = false
func run(#noescape block: () -> Void) {
guard !already else { return }
block()
already = true
}
}
and than use it like
class ViewController: UIViewController {
let once = Once()
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
once.run {
cameraMan.setup()
}
}
}
ref: https://dev.to/onmyway133/how-to-run-action-once-in-swift-3k7o
Depending on what you are doing inside your method : you may check if the end result has already been accomplished :
e.g. if you instantiate a class, check if it is different from nil
You can also use UserDefaults, and the knowledge that the default UserDefault Bool is false:
if !UserDefaults.standard.bool(forKey: "ExecuteOnce") {
func()
UserDefaults.standard.set(true, forKey: "ExecuteOnce")
}
This code will execute exactly once.

Swift: Protocol Based Type Construction

I'm trying to create a protocol in Swift I can use for object construction. The problem I'm running into is that I need to store the type information so the type can be constructed later and returned in a callback. I can't seem to find a way to store it without either crashing the compiler or creating build errors. Here's the basics (a contrived, but working example):
protocol Model {
init(values: [String])
func printValues()
}
struct Request<T:Model> {
let returnType:T.Type
let callback:T -> ()
}
We have a simple protocol that declares a init (for construction) and another func printValues() (for testing). We also define a struct we can use to store the type information and a callback to return the new type when its constructed.
Next we create a constructor:
class Constructor {
var callbacks: [Request<Model>] = []
func construct<T:Model>(type:T.Type, callback: T -> ()) {
callback(type(values: ["value1", "value2"]))
}
func queueRequest<T:Model>(request: Request<T>) {
callbacks.append(request)
}
func next() {
if let request = callbacks.first {
let model = request.returnType(values: ["value1", "value2"])
request.callback(model)
}
}
}
A couple things to note: This causes a compiler crash. It can't figure this out for some reason. The problem appears to be var callbacks: [Request<Model>] = []. If I comment out everything else, the compiler still crashes. Commenting out the var callbacks and the compiler stops crashing.
Also, the func construct works fine. But it doesn't store the type information so it's not so useful to me. I put in there for demonstration.
I found I could prevent the compiler from crashing if I remove the protocol requirement from the Request struct: struct Request<T>. In this case everything works and compiles but I still need to comment out let model = request.returnType(values: ["value1", "value2"]) in func next(). That is also causing a compiler crash.
Here's a usage example:
func construct() {
let constructor = Constructor()
let request = Request(returnType: TypeA.self) { req in req.printValues() }
//This works fine
constructor.construct(TypeA.self) { a in
a.printValues()
}
//This is what I want
constructor.queueRequest(request)
constructor.next() //The callback in the request object should be called and the values should print
}
Does anyone know how I can store type information restricted to a specific protocol to the type can later be constructed dynamically and returned in a callback?
If you want the exact same behavior of next I would suggest to do this:
class Constructor {
// store closures
var callbacks: [[String] -> ()] = []
func construct<T:Model>(type:T.Type, callback: T -> ()) {
callback(type(values: ["value1", "value2"]))
}
func queueRequest<T:Model>(request: Request<T>) {
// some code from the next function so you don't need to store the generic type itself
// **EDIT** changed closure to type [String] -> () in order to call it with different values
callbacks.append({ values in
let model = request.returnType(values: values)
request.callback(model)
})
}
func next(values: [String]) {
callbacks.first?(values)
}
}
Now you can call next with your values. Hopefully this works for you.
EDIT: Made some changes to the closure type and the next function
Unfortunately there is no way to save specific generic types in an array and dynamically call their methods because Swift is a static typed language (and Array has to have unambiguous types).
But hopefully we can express something like this in the future like so:
var callbacks: [Request<T: Model>] = []
Where T could be anything but has to conform to Model for example.
Your queueRequest method shouldn't have to know the generic type the Request it's being passed. Since callbacks is an array of Request<Model> types, the method just needs to know that the request being queued is of the type Request<Model>. It doesn't matter what the generic type is.
This code builds for me in a Playground:
class Constructor {
var callbacks: [Request<Model>] = []
func construct<T:Model>(type:T.Type, callback: T -> ()) {
callback(type(values: ["value1", "value2"]))
}
func queueRequest(request: Request<Model>) {
callbacks.append(request)
}
func next() {
if let request = callbacks.first {
let model = request.returnType(values: ["value1", "value2"])
request.callback(model)
}
}
}
So I found an answer that seems to do exactly what I want. I haven't confirmed this works yet in live code, but it does compile without any errors. Turns out, I needed to add one more level of redirection:
I create another protocol explicitly for object construction:
protocol ModelConstructor {
func constructWith(values:[String])
}
In my Request struct, I conform to this protocol:
struct Request<T:Model> : ModelConstructor {
let returnType:T.Type
let callback:T -> ()
func constructWith(values:[String]) {
let model = returnType(values: values)
callback(model)
}
}
Notice the actual construction is moved into the Request struct. Technically, the Constructor is no longer constructing, but for now I leave its name alone. I can now store the Request struct as ModelConstructor and correctly queue Requests:
class Constructor {
var callbacks: [ModelConstructor] = []
func queueRequest(request: Request<Model>) {
queueRequest(request)
}
func queueRequest(request: ModelConstructor) {
callbacks.append(request)
}
func next() {
if let request = callbacks.first {
request.constructWith(["value1", "value2"])
callbacks.removeAtIndex(0)
}
}
}
Note something special here: I can now successfully "queue" (or store in an array) Request<Model>, but I must do so indirectly by calling queueRequest(request: ModelConstructor). In this case, I'm overloading but that's not necessary. What matters here is that if I try to call callbacks.append(request) in the queueRequest(request: Request<Model>) function, the Swift compiler crashes. Apparently we need to hold the compiler's hand here a little so it can understand what exactly we want.
What I've found is that you cannot separate Type information from Type Construction. It needs to be all in the same place (in this case it's the Request struct). But so long as you keep construction coupled with the Type information, you're free to delay/store the construction until you have the information you need to actually construct the object.

Swift: determine what object called a function?

I am writing some Swift code and I would like to know the class of the object that called the function. I don't want to pass in any parameters. From within the function I want to be able to know who called it.
Any suggestion?
If you want to do that using Swift, you can do this:
func debug(file: String = #file, line: Int = #line, function: String = #function) -> String {
return "\(file):\(line) : \(function)"
}
To access the underlying class of a method from within itself, use the dynamicType property:
self.dynamicType
If you want to know the origin of the original call, you can use NSThread to return debugging information about the stack:
NSThread.callStackSymbols()
This method returns a descriptive array of values that you're used to seeing when exceptions are thrown. The strings represent a backtrace of all current activity on your call stack.
I don't want to be presumptuous, but it seems to me that outside of debugging, there isn't a good reason, conceptually, at least, to know the origin of a specific method call for any and every function. If you need to retrieve the class Type of the last method call on the stack, why not implement an interface that lets you access this information through a straightforward route?
You can use following template to know from which file, line number in file, and function this someFunction is called:
func someFunction(file: String = #file, line: Int = #line, function: String = #function)
{
NSLog("\(file.lastPathComponent):\(line) : \(function)")
}
Swift:
Add a (sender: Anyobject) as parameter to that function, and then print the sender (the function caller) like this:
func yourFunc(sender: AnyObject){
print(sender)
}
Or add a symbolic breakpoint with a po thread to see the stack trace of the caller of the method
The final way, use the follow protocol:
protocol PrefixPrint {
func formatPrint(_ text: String, function: String, line: Int) -> Void
}
extension PrefixPrint {
#inline(__always)
func formatPrint(_ text: String, function: String = #function, line: Int = #line) {
#if DEBUG
print("\(self).\(function).\(line): \(text)")
#endif
}
}
Console like: FootBall.VNSocketManager.init().44: xx
Joining together a couple of answers and comments:
func function(file: String = #file) {
if let url = URL(string: file) {
let className = url.deletingPathExtension().lastPathComponent
print(className)
}
}