Swift 3 custom parameter types - function

I'm sorry if this has been asked before, I can't find an answer. I would like to create custom parameter types for a function.
Typedef?/Define type
direction
{
LeftToRight,
RightToLeft
};
Function:
class func animateIn (dir:direction)
{
if dir = LeftToRight
{
// animate left to right
}
else
{
// animate right to left
}
}
Call:
animateIn (dir:LeftToRight)

enum seems the perfect candidate for this use. If you plan to have more cases in the enum, a switch statement also seems to be more feasible inside the function.
enum Direction {
case leftToRight, rightToLeft
}
class func animateIn(dir: Direction){
switch dir{
case .leftToRight:
//do something
case .rightToLeft:
//do something
}
}

enum Direction
{
case leftToRight, rightToLeft
}
Function:
class func animateIn(dir:Direction)
{
switch dir {
case .leftToRight:
// animate left to right
default:
// animate right to left
}
}
Call:
animateIn(dir:.leftToRight)

Related

How to use map(ES6) to return a list of functions?(ES6)

How can I use map to return this output
get funcone() { return this.Form.get(funcone"); }
get functwo() { return this.Form.get("functwo"); }
get functhree() { return this.Form.get("functhree"); }
get funcfour() { return this.Form.get("funcfour"); }
I used this array
FormValues=['funcone','functwo','functhree','funcfour'];
And this map
FormValues.map(Value=>{
get Value() { return this.Form.get(Value); }
})
I would appreciate any help!
Presumably you want to define those functions as getters on some object, or class. Let's assume it's a class.
That syntax can't work - it creates a Value getter, rather than funcone getter. Now, while you can define a getter using a variable for the getter's name:
let propName = "foo";
class Foo {
get [propName]() { return "You're getting a foo"; }
}
new Foo().foo
// => "You're getting a foo"
as far as I know, there's no way to make a loop inside the class declaration, nor a way to keep reopening a class and adding new stuff to it like in Ruby, so class definition inside a loop also won't work.
However, class syntax is just a sugar for the older prototypal inheritance, so everything we can do with the class syntax, we can also do without it (though vice versa does not hold). In order to add new stuff to the class, we just need to stick it to the class's prototype object. We can explicitly define a getter method using Object.defineProperty.
class Foo {
constructor() {
this.Form = {
one: 1,
two: 2,
three: 3,
four: 4
}
}
}
let props = ['one', 'two', 'three', 'four'];
props.forEach(propName =>
Object.defineProperty(Foo.prototype, propName, {
get: function() { return this.Form[propName]; }
})
);
new Foo().three
// => 3
It would be almost the same code to give the getters to an object rather than a class; you'd just be defining properties on the object itself, rather than on a prototype.

libGDX unable to perform action

I have a Letter class like this:
class Letter : Label {
val char: Char
var interactable = true
constructor(char: Char) : super(""+char, H.letterStyle()) {
this.char = char
}
fun animateSelect() {
addAction(Actions.scaleTo(3.0f, 3.0f, 0.5f))
}
fun animateUnselect() {
addAction(Actions.scaleTo(3.0f, 3.0f, 0.5f))
}
}
In my touch listener, I have this:
override fun touchDown(event: InputEvent?, x: Float, y: Float, pointer: Int, button: Int): Boolean {
var currentInteractingLetter: Letter? = null
for (letter in letterList) {
if (letter.bound.contains(x, y)) {
currentInteractingLetter = letter
break
}
}
if (currentInteractingLetter == null) {
} else {
selectedLetters.add(currentInteractingLetter)
currentInteractingLetter.animateSelect()
currentInteractingLetter.interactable = false
}
return true
}
The logic is quite straightforward. When user touch any one of the letters, I will invoke animateSelect() function.
When I run it, animateSelect did get called, but there is no scaleUp effect. I have tried to clear all actions before addAction but still the same.
Labels don't directly support scaling.
The easy way to solve this is put the label in a Container, setTransform(true) on the Container, and add your scale action to the Container.
val container= Container<Label>().apply {
isTransform=true
actor=label // Set your Label to container
}
container.addAction(Actions.scaleTo(3.0f, 3.0f, 0.5f))

Can you pass a typed array to a function within an enum in swift?

In a Swift app, I've created an enum with a function that takes an array of CLBeacon objects as it's only argument (i.e., [CLBeacon]). I get no clang errors with the enum, however when I try to use the enum, clang complains that I can't invoke the function with an argument list of ([CLBeacon]). Here's the code:
enum BeaconArrayState {
case NoObjectOnScreen, FirstObjectOnScreen, FirstObjectOffScreen
mutating func check(beacons: [CLBeacon]) -> BeaconArrayState {
switch self {
case FirstObjectOnScreen:
return .FirstObjectOnScreen
case FirstObjectOffScreen:
return .FirstObjectOffScreen
case NoObjectOnScreen:
if beacons.count > 0 {
println("push to screen associated with beacon \(beacons[0].minor)")
}
return .NoObjectOnScreen
}
}
}
var beaconArrayState: BeaconArrayState = .NoObjectOnScreen
func beaconManager(manager: AnyObject!, didRangeBeacons beacons: [AnyObject]!, inRegion region: CLBeaconRegion!) {
let knownBeacons = beacons.filter{$0.proximity != CLProximity.Unknown}
//send updated beacons array to perform parseBeacons
NSNotificationCenter.defaultCenter().postNotificationName("updateNotificationPriorities", object: knownBeacons)
beaconArrayState = BeaconArrayState.check(knownBeacons as [CLBeacon])
}
This gives: the error - Cannot invoke 'check' with argument list of type '([CLBeacon])'
The code in the case statements is irrelevant for now and not yet determined, but why the error on invocation?
The problem with your code is that you are calling check method statically while that function is not static at all. Also check function its not a mutating function so you dont need mutating keyword. To make this work make the follow change beaconArrayState = beaconArrayState.check(knownBeacons as [CLBeacon]) or if you want check method to mutate itself then change it like this :
mutating func check(beacons: [CLBeacon]) {
switch self {
case FirstObjectOnScreen:
self = .NoObjectOnScreen
case FirstObjectOffScreen:
self = .FirstObjectOffScreen
case NoObjectOnScreen:
if beacons.count > 0 {
println("push to screen associated with beacon \(beacons[0].minor)")
}
self = .NoObjectOnScreen
}
}
then just call beaconArrayState.check(knownBeacons as [CLBeacon]) and becaonArrayState will get its new value

Function declaration to return anything, also void?

Is there a way to declare a function such that I don't care about return value? For example I have this Array extension:
extension Array {
func forEach(function: (element: T) -> ()) {
for e in self {
function(element: e)
}
}
}
Now I want to do:
textFields.forEach{$0.resignFirstResponder()}
And I can't because the function is declared to return Void.
This would fix it:
textFields.forEach{$0.resignFirstResponder();return}
But is there a generic way to declare the function such that I can return any value or Void?
Thanks!
If you add a second generic parameter with no constraints, and type the function to return it, then any return value would be accepted:
extension Array {
func forEach<U>(function: (Element) -> U) {
for e in self {
function(e)
}
}
}
func f(i: Int)->Int {
return i * 2
}
func g(i: Int) -> Double {
return Double(0.0)
}
func h(i: Int) {
println("\(i)")
}
let a = [1,2,3]
a.forEach(g) // U will be an Int
a.forEach(f) // U will be a Double
a.forEach(h) // U will be a ()
However, I’d strongly suggest you not do this and use for…in instead.
The only purpose of running a function on an array but not using the return value is for side-effects. When writing in a more imperative style and using side-effects and external state (as opposed to a more declarative functional style) it’s much better to use for…in as a signal that this is what you’re doing.
There are also unpleasant gotchas involved in constructing your own pseudo-control structures. For example, think about this:
// function that does something side-effecty, but
// if it achieves some goal, exist early
func someFunc(a: [Int]) {
a.forEach { i -> () in
// goal achieved early,
// return from func
return
}
assert(false)
}
This is a common practice – cut out of a function early if some goal (or failure) is achieved. But with the forEach structure this is a bit misleading. It looks like a regular loop, but it’s actually a closure, and the return returns from that closure, ready for forEach to call the next one (essentially, it behaves like a continue in a regular loop).
Use map():
let textFields : [UITextField] = [] // or whatever
textFields.map{$0.resignFirstResponder()}
This way you don't have to specify the return type, and you don't need to reinvent map with your forEach extension.

dynamic objects in if condition

how to make if condition which contains dynamic object? i tried this way, but error
function pass(xxx:String,yyy:String,zzz:String)
{
//trace(xxx,yyy,zzz);
if (this[xxx].hitTestObject(this[yyy])) //an original if (obj1.hitTestObject(obj2))
{
trace("right");
}
else
{
trace("fail");
}
}
"this[]" is not work, TypeError: Error #1010: A term is undefined and has no properties.
"this[]" can work if it is outside "if".
Is there any other way for this problem? Thanks before
You should use getChildByName(), if you are transferring names of the MCs, but check if that name is a direct child of this.
function pass(xxx:String,yyy:String,zzz:String):void {
var x=this.getChildByName(xxx);
if (!x) return;
var y=this.getChildByName(yyy);
if (!y) return; // insert similar for zzz here
if (x.hitTestObject(y)) {
trace("right");
}
else
{
trace("fail");
}
}
Otherwise specify what inputs does thje function have.
Unless you have a specific reason to be supplying the object names as Strings, I suggest changing the argument types to DisplayObject:
function pass(a:DisplayObject, b:DisplayObject):void
{
if(a.hitTestObject(b))
{
trace("right");
}
else
{
trace("fail");
}
}
If you need to use the Strings, just do this:
var obj1:DisplayObject = getChildByName("obj1");
var obj2:DisplayObject= getChildByName("obj2");
pass(obj1, obj2);