Objective C ^ Declare block in Swift [duplicate] - objective-c

I am trying to rewrite from Objective-C to Swift, I cannot work out the syntax or understand the docs
Here is a simplified example in Objective-C I wrote:
[UIView animateWithDuration:10.0 animations:^{self.navigationController.toolbar.frame = CGRectMake(0,10,0,10);}];
How do I write this in Swift?
This is the template autocomplete gives:
UIView.animateWithDuration(duration: NSTimeInterval, animations: (() -> Void))

This is the swift closure format:
{(parameter:type, parameter: type, ...) -> returntype in
//do stuff
}
This is what you should do:
//The animation closure will take no parameters and return void (nothing).
UIView.animateWithDuration(duration: NSTimeInterval, animations: {() -> Void in
//Animate anything.
})
Here is the documentation for closures.

Since the expected argument types and return type to the animations argument are known the compiler can infer them without a problem. This should work (though I don't have the playground available right at the moment:
UIView.animateWithDuration(10.0, animations: {
self.navigationController.toolbar.frame = CGRect(x:0.0, y:10.0, width:10.0, height:0.0)
})
for more info about closures see the chapter in the swift docs
note about CGRect() - the developer docs show CGRect() being used in swift code. Perhaps it requires an import?
update for comments: you can also use a trailing closure like so:
UIView.animateWithDuration(10.0) {
self.navigationController.toolbar.frame = CGRect(x:0.0, y:10.0, width:10.0, height:0.0)
}

Following code can guide to write your own block.
class func testFunc(completion: ((list : NSArray!) -> Void)?) {
//--- block code.
if completion! != nil {
completion! (list: NSArray())
}
}
and you can call it like -
className.testFunc {
(list: NSArray!) -> Void in
}

You can basically write it in 3 identical ways:
write what to do right in the closure/code block:
UIView.animateWithDuration(10.0) {
self.navigationController.toolbar.frame = CGRect(x:0.0, y:10.0, width:10.0, height:0.0)
}
This is also known as trailing closure ( You can only do trailing closure if the closure parameter is the last parameter)
This doesn't mean the parameter 'animations' is no longer written. It is written but just as in the format of above.
Write exactly within the lines, most developers avoid such, because it's a little buggy to write with all the parenthesis and braces.
UIView.animateWithDuration(10.0, animations: {
self.navigationController.toolbar.frame = CGRect(x:0.0, y:10.0, width:10.0, height:0.0)
})
(Contrary to trailing closure you wrote name ie 'animations')
This is known as inline closure
Write in a more modular sense
UIView.animateWithDuration(duration: NSTimeInterval, animations: animatingFunc)
func animatingFunc() {
self.navigationController.toolbar.frame = CGRect(x:0.0, y:10.0, width:10.0, height:0.0)
}
Remember the type of the parameter 'animations' was () -> Void
Exactly as what we are doing, animatingFunc takes no parameters ie '()' and returns nothing ie 'void'
(In Swift, functions are types and can be passed in as parameters)
Some might say this is more readable some might say trailing closure is...
Side note1
You can also do nothing ( which really doesn't make sense but in many other handlers/animations/completion handlers you may not want to do anything)
UIView.animateWithDuration(duration: NSTimeInterval, animations: nil)
Side note2
Closures becomes more interesting when you have to capture a value. See this simple demonstration.
For more information about Swift closures see Apple's Documentation

How Do I Declare a Closure in Swift?
As a variable:
var closureName: (ParameterTypes) -> ReturnType
As an optional variable:
var closureName: ((ParameterTypes) -> ReturnType)?
As a type alias:
typealias ClosureType = (ParameterTypes) -> ReturnType
As a constant:
let closureName: ClosureType = { ... }
As a parameter to another function:
funcName(parameter: (ParameterTypes) -> ReturnType)
Note: if the passed-in closure is going to outlive the scope of the method, e.g. if you are saving it to a property, it needs to be annotated with #escaping.
As an argument to a function call:
funcName({ (ParameterTypes) -> ReturnType in statements })
As a function parameter:
array.sorted(by: { (item1: Int, item2: Int) -> Bool in return item1 < item2 })
As a function parameter with implied types:
array.sorted(by: { (item1, item2) -> Bool in return item1 < item2 })
As a function parameter with implied return type:
array.sorted(by: { (item1, item2) in return item1 < item2 })
As the last function parameter:
array.sorted { (item1, item2) in return item1 < item2 }
As the last parameter, using shorthand argument names:
array.sorted { return $0 < $1 }
As the last parameter, with an implied return value:
array.sorted { $0 < $1 }
As the last parameter, as a reference to an existing function:
array.sorted(by: <)
As a function parameter with explicit capture semantics:
array.sorted(by: { [unowned self] (item1: Int, item2: Int) -> Bool in return item1 < item2 })
As a function parameter with explicit capture semantics and inferred parameters / return type:
array.sorted(by: { [unowned self] in return $0 < $1 })
This site is not intended to be an exhaustive list of all possible uses of closures. ref: http://goshdarnclosuresyntax.com/

Related

Understanding a lambda construct that contains dot followed by brackets

This is the function declaration for rememberCoilPainter:
#Composable
fun rememberCoilPainter(
request: Any?,
imageLoader: ImageLoader = CoilPainterDefaults.defaultImageLoader(),
shouldRefetchOnSizeChange: ShouldRefetchOnSizeChange = ShouldRefetchOnSizeChange { _, _ -> false },
requestBuilder: (ImageRequest.Builder.(size: IntSize) -> ImageRequest.Builder)? = null,
fadeIn: Boolean = false,
fadeInDurationMs: Int = LoadPainterDefaults.FadeInTransitionDuration,
#DrawableRes previewPlaceholder: Int = 0,
): LoadPainter<Any> {
}
The line of code I am having difficulty understanding is:
requestBuilder: (ImageRequest.Builder.(size: IntSize) -> ImageRequest.Builder)? = null
A dot appears after Builder followed by (size: IntSize)
This is the first time I've seen this construct in Kotlin and am not sure how to interpret it. This is a lambda. Normally the dot after an object refers to a sub component of a class or a package. But the ( ) after the dot isn't clear.
How do I implement the requestBuilder parameter?
This is a function with receiver type as described here: https://kotlinlang.org/docs/lambdas.html#function-types
Function types can optionally have an additional receiver type, which is specified before a dot in the notation: the type A.(B) -> C represents functions that can be called on a receiver object of A with a parameter of B and return a value of C. Function literals with receiver are often used along with these types.
It could be tricky to understand at first, but this is like you are providing a function/lambda that is a method of ImageRequest.Builder. Or in other words: your lambda receives one additional parameter of type ImageRequest.Builder and it is available in the lambda as this.
You can provide requestBuilder as any other lambda, but note that inside it you will have access to properties and methods of ImageRequest.Builder object that was provided to you.
What you are looking at is a "function literal with receiver". Speaking generically, a type A.(B) -> C represents a function that can be called on a receiver object of A with a parameter of B and return a value of C. Or in your example:
requestBuilder: (ImageRequest.Builder.(size: IntSize) -> ImageRequest.Builder)?
We have a function requestBuilder which can be called on a ImageRequest.Builder with a parameter size: IntSize and returns another ImageRequest.Builder.
Calling this function is just like calling any other function with a lambda as a parameter. The difference: You have access to ImageRequest.Builder as this inside your lambda block.
Hope the following example helps understand lambdas with receiver type:
data class Person(val name: String)
fun getPrefixSafely(
prefixLength: Int,
person: Person?,
getPrefix: Person.(Int) -> String): String
{
if (person?.name?.length ?: 0 < prefixLength) return ""
return person?.getPrefix(prefixLength).orEmpty()
}
// Here is how getPrefixSafely can be called
getPrefixSafely(
prefixLength = 2,
person = Person("name"),
getPrefix = { x -> this.name.take(x) }
)
How do I implement the requestBuilder parameter?
Hope this part of the code snippet answers the above:
getPrefix = { x -> this.name.take(x) }
PS: These lambdas with receiver types are similar to extension functions IMO.

What is it about Kotlin's fold that allows me to put the operation function after the closing parentheses?

What is it about Iterable.fold(...) in Kotlin that allows me to put the operation function after the closing parentheses?
val numbers = listOf(5, 2, 10, 4)
// operation function passed as the second param of fold
val sumDoubled1 = numbers.fold(0, { sum, n -> sum + n * 2 })
println(sumDoubled1)
// operation function after the closing paren of fold
val sumDoubled2 = numbers.fold(0) { sum, n -> sum + n * 2 }
println(sumDoubled2)
Further to Pavneet's answer, the rationale behind this that it allows you to write what look like language extensions.  For example:
repeat (10) {
// Do something
}
That looks like a new type of loop structure; but it's really just a function called repeat() that takes two parameters; an integer, and a lambda.
Also, if the lambda is the only parameter, you can omit the parens entirely, e.g.:
repeatForever {
// Do something
}
(repeat() is in the standard library; repeatForever() is left as an exercise for the reader :-)
The ability to neaten some inline method calls, such as someValue.takeIf{ it > 0 } is just a nice side-effect of that.
It is called Passing trailing lambdas means, if a methods takes last parameter input as function(aka method literal) then it can be placed outside that method call though you can also place it inside the brackets as well. A simple example would be:
fun main() {
processInput("Lambda", { println(it) })
processInput("Passing trailing lambda") { println(it) }
processInput("Passing trailing lambda with named param") { input -> println(input) }
}
fun processInput(input:String, method:(str:String)->Unit){
method(input.toUpperCase()) // additional logic
}
Output:
LAMBDA
PASSING TRAILING LAMBDA
PASSING TRAILING LAMBDA WITH NAMED PARAM

kotlin object conversion in lambdas convert

I'm trying to have this compiling:
val criteriaList = aList.stream().map { dateRange -> {
Criteria.where("KEY").`is`(dateRange) } }.toList().toTypedArray()
Criteria().orOperator(*criteriaList)
But:
Criteria().orOperator(*criteriaList)
Currently does not compile:
Type mismatch.
Required:
Array<(out) Criteria!>!
Found:
Array<(() → Criteria!)!>
Why?
You are mapping your dateRange to a () -> Criteria.
You do not need to wrap what is following after -> with curly braces. Check also the Kotlin reference regarding Lambda expression syntax:
val sum = { x: Int, y: Int -> x + y }
A lambda expression is always surrounded by curly braces [...], the body goes after an -> sign. If the inferred return type of the lambda is not
Unit, the last (or possibly single) expression inside the lambda body is treated as the return value.
So you could just write the following instead:
.map { dateRange -> Criteria.where("KEY").`is`(dateRange) }
Note also that you do not really need to call stream(), but you can directly call map on it (except it wouldn't be a real List in the first place).
So your code could probably be simplified to something like:
val criteriaList = aList.map { dateRange -> Criteria.where("KEY").`is`(dateRange) }
.toTypedArray()
or
val criteriaList = aList.map { Criteria.where("KEY").`is`(it) }
.toTypedArray()

Extending existing type testing.T for adding extra checks

I realize I could pass the testing.T type to the functions that need to deal with the testing interfaces. But how about extending the struct and using it? I know I can type extend but this doesn't work unfortunately:
package test
import "testing"
type testingT testing.T
func (t *testingT) assert(val int) {
if val == 0 {
t.Errorf("%d is zero", val)
}
}
func TestSomething(t *testingT) {
t.assert(0)
}
One solution is embedding as you can see in eduncan911's answer. It's great if you want to add other fields to the new struct.
However, this is not a requirement. Creating a new type having testing.T as its underlying type (just as you did) is just enough:
type myT testing.T
func (t *myT) assert(val int) {
if val == 0 {
t.Errorf("%d is zero", val)
}
}
Using it
In TestSomething() we can't just call t.assert(0) because assert() is not a method of testing.T but our myT type. So we need a value of type myT on which we can call myT.assert().
We can't use type assertion to convert a testing.T to our myT type though, because type assertion requires the expression to be of interface type! And t is not an interface type, it's a concrete type: *testing.T.
The solution is really simple, we can use simple type conversion because myT and testing.T has the same underlying type:
my := myT(*t) // Conversion valid, but not yet enough, read on...
The above works, and we can call:
my.assert(0)
But when running tests, it won't fail! Why is that? It's because the above *t dereferencing, conversion and assignment will make a copy, and my will be of type myT but will be a copy of *t, and so when we call myT.assert(), it gets a pointer, but a pointer to the copy. And when myT.assert() calls t.Errorf(), it will register the error on a copy, so the testing framework will not see this Errorf() call.
The "final" solution is simple: use type conversion, but don't convert *t, but t itself (which is a pointer). Of course *t cannot be converted to myT, only to *myT. And this type needs to be parenthesized (to avoid ambiguity):
func TestSomething(t *testing.T) {
my := (*myT)(t)
my.assert(0)
}
And now we're happy, everything works as expected.
Note: You can also call myT.assert() in one line if you don't want to call multiple methods of myT:
func TestSomething(t *testing.T) {
(*myT)(t).assert(0)
}
You can use embedding which would allow you to add your owner methods:
package test
import "testing"
type testingT struct {
*testing.T
}
func (t *testingT) assert(val int) {
if val == 0 {
t.Errorf("%d is zero", val)
}
}
func TestSomething(t *testing.T) {
t2 := &testingT{t}
t2.assert(0)
}
Prepare custom testing struct:
type T testing.T
func (t *T) AssertEqualsInt(expected, actual int) {
if actual != expected {
// Correct point for file and line where happened error
t.Helper()
t.Errorf("Values not equal expected: %d, got: %d", expected, actual)
}
}
func (t *T) AssertEqualsString(expected, actual string) {
if actual != expected {
t.Helper()
t.Errorf("Values not equal expected: %s, got: %s", expected, actual)
}
}
Than use it in testing:
func TestFooBarBaz(t *testing.T) {
(*T)(t).AssertEqualsInt(0, 10)
(*T)(t).AssertEqualsString("foo", "bar")
}

Customize 'at' with extra parameters for the closure?

Is it possible to specify some optional parameter(s) to the 'at' closure on the page like this:
class ManagerDashboardClientsPage extends Page {
static at = { year, geo ->
if (year) {
GebUtil.selectedYear == year
}
title.endsWith('Dashboard: Clients')
}
}
so that I can write both
at ManagerDashboardClientsPage
and
at ManagerDashboardClientsPage(2013, 'North East')
Currently the first one breaks with
No signature of method: page.ManagerDashboardClientsPage$__clinit__closure1.doCall() is applicable for argument types: () values: []
Possible solutions: doCall(java.lang.Object, java.lang.Object), call(), call([Ljava.lang.Object;), call(java.lang.Object), call(java.lang.Object, java.lang.Object), equals(java.lang.Object)
groovy.lang.MissingMethodException: No signature of method: page.ManagerDashboardClientsPage$__clinit__closure1.doCall() is applicable for argument types: () values: []
Possible solutions: doCall(java.lang.Object, java.lang.Object), call(), call([Ljava.lang.Object;), call(java.lang.Object), call(java.lang.Object, java.lang.Object), equals(java.lang.Object)
at geb.Page.verifyThisPageAtOnly(Page.groovy:165)
at geb.Page.verifyAt(Page.groovy:133)
at geb.Browser.doAt(Browser.groovy:358)
at geb.Browser.at(Browser.groovy:289)
at geb.spock.GebSpec.methodMissing(GebSpec.groovy:51)
at spec.ManagerDashboardClientsSpec.login as CEO(ManagerDashboardClientsSpec.groovy:16)
In Groovy you can set default values for optional closure parameters, like so:
static at = { year=null, geo=null ->
...
}
I think that'll clear ya up. :)
update
Ok, I know you don't need it anymore, but I made this for my own use when I was learning Groovy, and I thought someone might find it helpful:
{ -> ... } a closure with exactly zero parameters. Groovy will blow up if you call it with params.
{ ... } a closure with one optional parameter, named "it"
{ foo -> ... } a closure with one parameter named "foo" (foo can be any type)
{ foo, bar, baz -> ... } a closure with 3 parameters named "foo", "bar" and "baz"
{ String foo -> ... } You can specify the type of the parameters if you like