Utilizare XIB – cazul 2 – Views

Cea mai utilizata situatie in care sunt folosite XIB-urile este aceea a view-urilor. In aceasta situatie putem defini, configura si testa un TableViewCell – de exemplu – fara a mai incarca si restul de elemente grafice definite in Storyboard sau alte XIB-uri.
Un exemplu in acest sens:




Cum procedam?
Ca si in cazul ViewController-elor avem urmatorii pasi:

– adaugare XIB file atunci cand adaug un fisier “Cocoa Touch Class”. Se adauga fisierului .swift un fisier .xib cu acelasi nume dar continand “reprezentarea grafica” a clasei derivate.
– clasa adaugata pentru un UITableViewCell-> RequestProfileTableViewCell.swift si .xib file adaugat.
– adaugam continut in RequestProfileTableViewCell.xib si generam IBOutlet/IBAction pentru elementele din .xib in .swift
– daca este cazul -> definim continutul RequestProfileTableViewCell.swift

Din experienta mea, acest ultim pas, cel cu definire de continut este cel mai putin consistent. Foarte important e faptul ca, in prealabil, se definesc IBOutlet/IBAction pentru elementele grafice “desenate” in XIB.

Cum folosim view-ul definit XIB?

In exemplul nostru am definit un UITableViewCell.
Vom folosi acest Cell intr-un TableView atunci cand vom scrie codul pentru delegatul tableView(_:cellForRowAt:) – cam ciudatica aceasta sintaxa folosita in Swift dar cu timpul ea devine inteligibila –

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = Bundle.main.loadNibNamed("RequestProfileTableViewCell", owner: self, options: nil)?.first as! RequestProfileTableViewCell
cell.textLabel?.text = "bubu"
return cell
}

Am bolduit modul de “import” al XIB-ului aferent unei UITableViewCell. Foarte simplu si autocomplete-ul XCode-ului ajuta daca cumva omit vre-un parametru.

Share Button

Utilizare XIB – cazul 1 – View Controller

Situatie: Storyboard-ul este prea plin. Multe ViewController-e incarcate, timp mare de asteptare atunci cand intru in storyboard pentru modificari.
Solutie: adaugare XIB file atunci cand adaug un fisier “Cocoa Touch Class”. Se adauga fisierului .swift un fisier .xib cu acelasi nume dar continand “reprezentarea grafica” a clasei derivate.
Exemplu:
– clasa adaugata pentru un UIViewController -> RequestProfileViewController.swift si .xib file adaugat.
– definim continutul RequestProfileViewController.swift
– adaugam continut in RequestProfileViewController.xib si generam IBOutlet/IBAction pentru elementele din .xib in .swift
– in clasa in care vrem sa utilizam o instanta de RequestProfileViewController trebuie sa adaugam ViewController-ul generat in .xib:

let requestProfileVC = RequestProfileViewController(nibName: "RequestProfileViewController", bundle:nil)
self.addChildViewController(requestProfileVC)
requestProfileVC.view.frame = self.view.frame
self.view.addSubview(requestProfileVC.view)
requestProfileVC.didMove(toParentViewController: self)

Utilizarea addChildViewController este explicata de Matt Neuburg excelent aici.

Share Button

UserNotifications – Swift3 – utilizare

1. Import pentru UserNotifications framework si adaugam UNUserNotificationCenterDelegate in AppDelegate.swift
2. Implementare delegatii specifici pentru UNUserNotificationCenterDelegate in ViewController-ul dedicat sau folosind o extensie:
2.1.func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
print("S-a apasat pe notificare, acum ar trebui implementantat ce anume se doreste dupa ce s-a dat click pe notificare")
}

2.2. func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
print("S-a primit notificare in foreground, definim aici actiunea care se va efectua in foregorund")

}
3. Cerere permisiuni de notificare din partea utilizatorului, de asemenea in AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// register user notification
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options:[.alert, .sound]) { (granted, error) in
}
return true
}

4. Delegarea actiunilor view-ului curent catre delegatii specifici: userNotificationCenter didReceive: si userNotificationCenter willPresent
UNUserNotificationCenter.current().delegate = self
5. Adaugam Observer care va “reactiona” atunci cand selectorul va “cere” sa efectueze o notificare:
NotificationCenter.default.addObserver(self, selector: #selector(numeMetodaNotificare()), name: NSNotification.Name(rawValue: "identificatorNumeNotificare"), object: nil)
6. Implementare metoda care va genera notificare numeMetodaNotificare()
func numeMetodaNotificare(output name:String)
{
let notification = UNMutableNotificationContent()
notification.title = NSString.localizedUserNotificationString(forKey: "Request received", arguments: nil)
notification.body = NSString.localizedUserNotificationString(forKey: "Request is: \(name)!", arguments: nil)
notification.sound = UNNotificationSound.default()
let request = UNNotificationRequest(identifier: "OneSecond", content: notification, trigger: nil)
let center = UNUserNotificationCenter.current()
print("s-a construit notificarea: \(notification.body)")
center.add(request)
}

Share Button

Swift3 – lucrul cu taskuri in background

Avem urmatorul scenariu: o aplicatie player audio care “observa” cand schimbam outputul audio: cand trecem de pe casti pe speaker si viceversa.
Nu intram in detalii aici cum e cu schimbarea rutei audio, poate intr-o discutie viitoare.
Ceea ce vreau sa punctez aici este urmatorul aspect: acest player poate functiona din IOS 8 si in background. Pot asculta muzica si atunci cand blochez ecranul sau comut pe alta aplicatie.
Cum pot permite unei aplicatii scrise in Swift3 sa “lucreze” si in background?

1. pot implementa metoda applicationWillResignActive(_ application: UIApplication)
2. putem inregistra notificarea UIApplicationWillResignActive oriunde in cadrul proiectului nostru Swift.

Cum facem lucrul asta:

1. func applicationWillResignActive(_ application: UIApplication) {
......
DispatchQueue.main.async {
self.backgroundUpdateTask = UIApplication.shared.beginBackgroundTask(expirationHandler: {
self.endBackgroundUpdateTask()
})
.....
}

2. NotificationCenter.default.addObserver(
self,
selector: #selector(appDidEnterBackground(notification:)),
name: .UIApplicationWillResignActive ,
object: nil)

unde definim selectorul astfel:

func appDidEnterBackground(notification: NSNotification) {
var bti:UIBackgroundTaskIdentifier=0
bti=self.app.beginBackgroundTask{
UIApplication.shared.endBackgroundTask(bti)
}

Le-am folosit pe ambele in aplicatii, insa o prefer pe a doua din motiv de claritate a codului. Nu e chiar ok sa abuzez de AppDelegate.

Share Button

Nil-Coalescing Operator – Swift

Nu stiu cum sa-i zic pe romaneste acestui operator ?? in Swift. De doua ori semnul intrebarii ar suna ridicol.
Documentatia Apple spune ca a ?? b este prescurtarea de la
a != nil ? a! : b
Ce ar insemna asta?
Daca a nu este nil atunci forteaza pe a sa devina a! – valoare unwrapped, in caz contrar, adica daca a este nil, a devenind b.

Ca sa intelegem mai bine, dam un mic exemplu:

let defaultColorName = "red"
var userDefinedColorName: String? // defaults to nil
var colorNameToUse = userDefinedColorName ?? defaultColorName
// userDefinedColorName is nil, so colorNameToUse is set to the default of "red"

userDefinedColorName este implicit nil atunci cand se face initializarea.
Var-ul colorNameToUse ia valoarea userDefinedColorName daca nu este nil (nu este cazul) si in acest caz va lua valoarea defaultColorName.

Share Button