Swift - closure expression syntax - xcode

i'm working with Alamofire library, i've noticed that they use this syntax
func download(method: Alamofire.Method, URLString: URLStringConvertible, headers: [String : String]? = default, #destination: Alamofire.Request.DownloadFileDestination) -> Alamofire.Request
that takes 4 parameters as input but if you go to the documentation to call the method they use the following
Alamofire.download(.GET, "http://httpbin.org/stream/100") { temporaryURL, response in
let fileManager = NSFileManager.defaultManager()
if let directoryURL = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as? NSURL {
let pathComponent = response.suggestedFilename
return directoryURL.URLByAppendingPathComponent(pathComponent!)
}
return temporaryURL}
that takes only 2 parameters (method: and URLString:) i think that the param headers is optional because provide the default statement.
I don't understand how Destination is handled.
Could you please explain me how the closure is handled?
Why the curl braces is open AFTER the method call and not inside the call after the URLString param?
I really appreciate any help you can provide
Marco

It's the trailing closure technique
If a method accepts a closure as last param
class Foo {
func doSomething(number: Int, word: String, completion: () -> ()) {
}
}
You can call it following the classic way:
Foo().doSomething(1, word: "hello", completion: { () -> () in
// your code here
})
Or using the trailing closure technique:
Foo().doSomething(1, word: "hello") { () -> () in
// your code here
}
The result is the same, it just a more elegant (IMHO) syntax.

Related

didChangeAutomaticCapitalizationNotification not triggered

What am I doing wrong? I don't get this notification. I have this function:
#objc func onAutocorrection (_ notification: Foundation.Notification) {
Swift.print("\(notification)")
}
later in the same class I do use it as follows:
NotificationCenter.default.addObserver(
self,
selector: #selector(onAutocorrection(_:)),
name: NSSpellChecker.didChangeAutomaticCapitalizationNotification,
object: nil)
The addObserver is executed, but the function is never called even when the application is capitalising in an NSTextView.
Why? Many thanks in advance!
It looks like I misunderstood the notification. It is not meant to be triggered when automatic capitalisation happens but when the systems preference of your Mac is changing.
See the comment of ever helpful Willeke and see Notification of autocorrect
In order to get to the intended result of reacting to autocapitalisation did I implement this function in the NSTextViewDelegate:
public func textView(_ view: NSTextView, didCheckTextIn range: NSRange, types checkingTypes: NSTextCheckingTypes, options: [NSSpellChecker.OptionKey : Any] = [:], results: [NSTextCheckingResult], orthography: NSOrthography, wordCount: Int) -> [NSTextCheckingResult] {
if !range.contains(0){
return results
}
var newResult = [NSTextCheckingResult]()
for result in results {
if let textToChange = view.string[range].components(separatedBy: " ").first, let replacement = result.replacementString?.components(separatedBy: " ").first {
let firstLetterCap = textToChange.capitalizingFirstLetter()
if replacement == firstLetterCap {
continue //don't add to results
}
}
newResult.append(result)
}
return newResult
}
This function will prevent that the first character will be capitalised.
Ultimately, I check whether the capitalised version of the first word of the range that must include position "0" is equal to the first word of the replacement string. And if it is then I remove that result/suggestion from the result list.

How to make a CompletionHandler with Firebase Swift 3

I need to get some informations from Firebase to out it on UIViewCell. But the problem is that the function return before he get all the value. I know that's because it's asynchronous, i tried to make a completion Handler like that:
static func hardProcessingWithString(input: String, completion: #escaping (_ result: String) -> Void) {
Database.database().reference().child("Player_1").observe(.value) {
(firDataSnapshot) in
completion((firDataSnapshot.value as? String)!)
}
}
This is how i try to get the value :
var myVar: String!
hardProcessingWithString(input: "commands"){
(result: String) in
myVar = result
}
I get this error when I call the function:
Could not cast value of type '__NSDictionaryM' (0x102e292b0) to 'NSString' (0x102434c60).
Here's my Firebase database:
Or if you know how to make a Promise with Firebase let me know!
Step 1:
Create a swift file like Constant.swift. Then place the below code inside it
typealias DownloadComplete = () -> ()
Step 2:
Create a function where you want.
func hardProcessingWithString(completed: #escaping DownloadComplete) {
Database.database().reference().child("Player_1").observe (.value, with: { (firDataSnapshot) in
// put your code here
completed()
})
}
Step 3:
when you call above method in your code
hardProcessingWithString() {
// you can get the result here
}

Implementing RxSwift with TRON

I am trying to start using RxSwift, therefore I tried to create a function that does a request and I tried to implement the rxResult() function that comes with TRON, the HTTP library I use. But the documentation on this is not very detailed. Can anyone point me in the right direction on what I am doing wrong? This is the function I have written:
static func readAllWithRx() {
let token = UserDefaults.standard.value(forKey: Constants.kTokenUserDefaultsKey) as! String
let url = URL(string: "api/url")!
let request: APIRequest<AssessmentResponse, MyAppError> = APIHelper.tron.request(url.absoluteString)
_ = request.rxResult().subscribe(onNext: { AssessmentResponse in
print("RX AssessmentResponse \(AssessmentResponse)")
}, onError: { Error in
}, onCompleted: {
}, onDisposed: {
})
}
Finally I try to call this request within my Controller using:
let read = Assessments.readAllWithRx()
There’re 2 things at the beginning:
let read = Assessments.readAllWithRx() assumes the function returns something synchronously
Implementation of readAllWithRx you posted doesn’t return anything.
I’ve never used TRON, but as far as I can see, its rxResult() returns an Observable<T> where T is a type of the response. In this case, to get asynchronously AssesmentResponse, you need to subscribe to the observable (as you already did by the way).
Here's an example - an updated implementation of your readAllWithRx (won’t compiled probably, writing code in notepad):
static func readAllWithRx() -> Observable<AssessmentResponse> {
let token = UserDefaults.standard.value(forKey: Constants.kTokenUserDefaultsKey) as! String
let url = URL(string: "api/url")!
let request: APIRequest<AssessmentResponse, MyAppError> = APIHelper.tron.request(url.absoluteString)
return request.rxResult()
}
then, if you need to get AssessmentResponse somewhere in the code:
Assessments.readAllWithRx().subscribe(onNext: { result in
// your response here
print(result)
})

Cannot invoke 'dataTask' with an argument list of type

I have this vanilla piece of code I virtually use everywhere in my code:
let configuration = URLSessionConfiguration.default
let session = URLSession(configuration:configuration)
let listTask = session.dataTask(with: theRequest, completionHandler: {[weak self](data, response, error) in
})
Yet in one particular class the compiler complaints:
Cannot invoke 'dataTask' with an argument list of type '(with:
URLRequest, completionHandler: (Data?, URLResponse?, Error?) -> ())'
Expected an argument list of type '(with: URLRequest, completionHandler: > (Data?, URLResponse?, Error?) -> Void)'
How does it infer the return value of the closure to be () instead of the expected Void? I copied the code from other classes repeatedly lest I wrote something wrongly.
For some reason adding:
return ()
at the end of the closure, as suggested on the Apple forum, fixed the issue.
tried in xcode 8 beta 6 with swift 3 playground
let configuration = URLSessionConfiguration.default
let session = URLSession(configuration:configuration)
let theRequest = URLRequest(url: URL(string: "")!)
let task = session.dataTask(with: URL(string: "")!) { (data:Data?, response:URLResponse?, error:Error?) in
}
let task1 = session.dataTask(with: theRequest) { (data:Data?, response:URLResponse?, error:Error?) in
}

Swift URL Response is nil

I have created a custom DataManager class. Inside it I want to fetch data in a method and return an NSData object to convert to JSON afterwards.
I have tried to get the data using the completionHandler but no luck:
class func fetchData() -> NSData? {
var session = NSURLSession.sharedSession(),
result = NSData?()
let DataURL : NSURL = NSURL(string: "http://...file.json")!
let sessionTask = session.dataTaskWithURL(DataURL, completionHandler: { (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
result = data
})
sessionTask.resume()
return result
}
The dataTask runs asynchronously. That means that the completion handler closure will not be called by the time you return from fetchData. Thus, result will not have been set yet.
Because of this, you should not try to retrieve data synchronously from an asynchronous method. Instead, you should employ an asynchronous completion handler pattern yourself:
class func fetchData(completion: #escaping (Data?, Error?) -> Void) {
let session = URLSession.shared
let url = URL(string: "http://...file.json")!
let task = session.dataTask(with: url) { data, response, error in
completion(data, error)
}
task.resume()
}
And you'd call it like so:
MyClass.fetchData { data, error in
guard let data = data, error == nil else {
print(error ?? "Unknown error")
return
}
// use `data` here; remember to dispatch UI and model updates to the main queue
}
// but do not try to use `data` here
...
FYI, for the original pre-Swift 3 syntax, see previous revision of this answer.

Resources