prepare(for:sender:) – apelare de doua ori?

Sunt in urmatorul scenariu: un buton din ViewController-ul A – VCA este legat prin segue cu prezentare modala de un ViewController B – VCB.

In VCA am definit metoda prepare(for:sender:)
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "asSegue" {
.....
}

Practic definesc ce anume fac atunci cand se va produce click pe butonul ce va aduce modalul VCB.

Din exces de zel fac urmatoarea greseala: In VCA, deci in ViewControllerul mama spun ca atunci cand se da click pe butonul care are atasat segue sa activez urmatoarea metoda:
performSegue(withIdentifier: "visibilitiesSegue", sender: self)

Totul merge bine si frumos, la click pe butonul din VCA apare modalul VCB, imi fac treaba si e perfect! Numai ca in consola am un pic warning:
Warning: Attempt to present VCB on VCA which is already presenting (null)
Nu m-ar deranja prea tare daca nu as vrea sa am consola curata de warning-uri.

Caut la Apple despre performSegue si aflu ca
“Normally, segues are initiated automatically and not using this method.”

Ce gresesc?

Metoda prepare(for:sender:) este apelata de doua ori, o data automat atunci cand eu dau click si se produce implicit prezentarea lui VCB si a doua oara cand eu i-am specificat faptul ca la click de buton trebuie sa activeze performSegue(withIdentifier:sender:)

Solutia?

Elimin de la executie performSegue(withIdentifier:sender:) deoarece atunci cand se face click pe buton pentru a prezenta VCB automat este executata prepare(for:sender:)

Share Button

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

CGGeometry – SWIFT 3

Mai intai cateva detalii despre componentele CGGeometry:

1. CGPoint – structura ce reprezinta un punct in sistem cartezian.
2. CGRect – structura ce reprezinta un dreptunghi prin locatie si dimensiuni.
3. CGSize – structura ce reprezinta dimensiunile latimii si inaltimii.

Nici una dintre cele trei structuri nu precizeaza tipul unitatii de masura folosita. Cele mai uzuale sunt point-ul si pixel-ul.

Cum folosim elemente CGGeometry in Swift 3:

let frame = CGRect(x: 0, y: 0, width: 20, height: 20)

let point = CGPoint(x: 0, y: 0)

let size = CGSize(width: 20, height: 20)

Combinand toate cele trei putem scoate o frumoasa sintaxa in SWIFT 3:

let rect = CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: 100, height: 100))

In acest ultim exemplu “complex” am folosit un al doilea tip de constructor pentru CGRect.

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

SWIFT – Selector

Selector-ul este in Objective-C și SWIFT un fel aparte de referință a unei metode.
Pentru a înțelege mai bine ce-i cu acest selector, urmărim codul:

class ViewController : UIViewController {
@IBOutlet var b : UIButton!
func viewDidLoad() {
super.viewDidLoad()
self.b.addTarget( // prepare to crash!
self, action: "buttonPressed", for: .touchUpInside)
}
func buttonPressed(_ sender: Any) {
// ...
}
}

self.b este un buton în interfață care atunci când va fi apăsat se va apela metoda addTarget(action:for:)
Aceasta la rândul ei va încerca să apeleze buttonPressed. Însă buttonPressed nu este metodă în SWIFT, numele corect fiind buttonPressed:, ceea ce va duce la crash atunci când se va apăsa pe buton.
Pentru a remedia acest aspect se folosește #selector:


class ViewController : UIViewController {
@IBOutlet var button : UIButton!
func viewDidLoad() {
super.viewDidLoad()
self.b.addTarget(
self, action: #selector(buttonPressed), for: .touchUpInside)
}
func buttonPressed(_ sender: Any) {
// ...
}
}

Share Button