Poate fi atasat un UIGestureRecognizer la mai multe view-uri?

Cei de la Apple spun ca nu: un UIGestureRecognizer poate fi utilizat doar cu un singur view.
Cum trecem peste acest impediment, avand o lista de view-uri, fiecare din aceste view-uri facand aceeasi actiune, sa zicem tiparirea campului tag?

1. generam o functie care va returna un UIGestureRecognizer

func setGestureRecognizer() -> UITapGestureRecognizer {
var gesture = UITapGestureRecognizer()
gesture = UITapGestureRecognizer(target: self, action: #selector(changeImage(sender:)))
return gesture
}

2. definim functia de raspuns in care extragem view-ul senderul UIImageView
func changeImage(sender: UITapGestureRecognizer) {
let tappedImageView = sender.view! as? UIImageView
print("button clicked - \(tappedImageView!.tag)")
}

3. folosim recognizer-ul in view-urile noastre
view1.addGestureRecognizer(setGestureRecognizer())
view2.addGestureRecognizer(setGestureRecognizer())
view3.addGestureRecognizer(setGestureRecognizer())

Share Button

Warning – Expression of type ‘UIViewController?’ is unused

Atunci cand folosesc intr-o alerta pentru ramura de close o expresie de genul: navigationController?.popViewController(animated: true)

XCode 8 imi genereaza un warning de genul: Expression of type ‘UIViewController?’ is unused.

Adica eu iti returnez un UIViewController? si tu nu vrei sa-l folosesti de nici un fel?

Pana la Swift 3 toate functiile aveau implicit “discardable result”. Adica daca nu foloseai explicit outputul functiei, nici o problema.

La Swift 3 dispare aceasta “facilitate” tocmai pentru a preintampina situatiile in care returnul functiei este “uitat” de coderi.

Pentru a remedia acest warning este suficient sa rescriu utilizarea astfel:

let _ = navigationController?.popViewController(animated: true)

Share Button

Map, Filter și Reduce în SWIFT – Update 24.05.2017

UPDATE 24.05.2017
Revin cu un exemplu practic pe care l-am incercat azi cu MAP. In Swift developerii folosesc din ce in ce mai mult MAP in locul clasicului FOR.
Convertesc secventa:
for user in (userList as! [String]) {
let fullMessages = SendReceiveMessages.sharedInstance.loadArchivedMessagesFrom(jid: user )
let last = fullMessages.lastObject as! JSQMessage
usersLastMessageStructArray.append(lastMessagesStruct(username: user, message: last.text, date: last.date))
}

in ceva mult mai swifty

usersLastMessageStructArray = (userList as! [String]).map({user in
let fullMessages = SendReceiveMessages.sharedInstance.loadArchivedMessagesFrom(jid: user )
let last = fullMessages.lastObject as! JSQMessage
return lastMessagesStruct(username: user, message: last.text, date: last.date)
})

Sortez de asemenea intr-un mod swifty acest array de struct-uri:

usersLastMessageStructArray = usersLastMessageStructArray.sorted{$0.date > $1.date}

Metode mai puțin cunoscute pentru array-uri însă extrem de puternice. Practic, cu ajutorul lor, nu mai e nevoie de pus o bucla for in sau foreach pe array.

filter(_:) – preia în noul array elementele din vechiul array în aceeași ordine cu precizarea că pot fi omise elementele care sunt specificate în filtru:
let elevi = [“Marius”, “Serban”, “Maria”]
let eleviM = elevi.filter {$0.hasPrefix(“M”)} // [Marius, Maria]

Un exemplu foarte concludent – formarea unui array de elemente pare din array-ul inițial”
let digits = [1,4,10,15]
let even = digits.filter { $0 % 2 == 0 } // [4, 10]

map(_:) – instanțiază un nou array în care fiecare element este rezultatul trecerii fiecărui element din vechiul vector prin funcția furnizată ca și argument. Interesant e faptul că această funcție poate modifica tipul parametrului

let vector = [1,2,3]
let vectorNou = vector.map {$0 * 2} // [2,4,6]

reduce(_:) – combină toate elementele din array pentru a obține o singură valoare
let litere = [“abc”,”def”,”ghi”]
let text = litere.reduce(“”, combine: +) // “abcdefghi”

sau

let array = [1, 4, 9, 13, 118]
let sum = arr.reduce(0) {$0 + $1} // 145

Share Button

SWIFT – cum folosim Closures?

Closures în SWIFT au fost gândite și folosite ca un exemplu de funcții inline. Din experiența mea, “closures” sunt folosite în completion blocks pentru a notifica faptul că un block și-a terminat activitatea.

Un mic exemplu didactic – Universitatea din Toronto:

func performMagic (spell: String) -> String {
return spell
}

Avem o funcție simplă ce va primi printr-un argument un string și-l va returna.

Vom folosi closure pentru a defini o variabilă ce va “conține” corpul acestei funcții:

var newPerformMagic = {
(spell:String) -> String in
return spell
}

Pnetru a utiliza, e suficient
newPerformMagic(“test de closure”)

Share Button