Jestem szybkim nowicjuszem i chodzę w kółkopróbowanie uruchomić opcje. Zrobiłem dużo Googlingu, czytałem Apple Docs itp. Ale zmagam się z tym (uproszczonym) fragmentem z mojego ViewController:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "segueToWebView") {
// check what we"re passing around
print(sender!.urlString) // Optional("http://www.bbc.co.uk")
// do some url validation etc
var destUrl:String
if sender!.urlString == nil{
destUrl = "http://www.google.com"
} else {
destUrl = sender!.urlString // *** Error here ***
}
let targetWebViewController:GDWebViewController = segue.destinationViewController as! GDWebViewController
targetWebViewController.loadURLWithString(destUrl)
targetWebViewController.showsToolbar = true
targetWebViewController.title = sender!.busName // this works correctly too (so isn"t that a String?)
}
}
Błąd jest Cannot assign value of type "String?!" to type "String"
w linii zaznaczonej powyżej. Próbowałem rozpakować to inaczej, ale po prostu nie mogę tego zrozumieć.
Więcej kodu
Nadawca jest niestandardową podklasą UIButton o następującej strukturze:
import UIKit
class TestButton: UIButton {
var urlString: String?
var busName: String?
}
Ustawiłem zmienne jako opcjonalne, ponieważ nie wiem, czy przycisk / nie będzie miał tych właściwości.
Metoda wywoływana po dotknięciu przycisku jest następująca:
func tapTap(sender: TestButton) {
print(sender.busName, sender.urlString) // Optional("My Button") Optional("http://www.bbc.co.uk")
self.performSegueWithIdentifier("segueToWebView", sender: sender)
}
Wiem, że oprzyrządowanie Swift jest częstą przeszkodą dla początkujących, takich jak ja i jest dużo dokumentów na ich temat, ale nie mogę tego zrozumieć, więc każda pomoc byłaby świetna.
Odpowiedzi:
10 dla odpowiedzi № 1Istnieją opcje na trzech poziomach:
- The
sender: AnyObject?
parametr jest opcjonalny. - Wysyłanie dowolnych wiadomości do
AnyObject
zachowuje się podobnie do opcjonalnego łańcuch i zwraca nieopakowane opcje opcjonalne (porównać Dziwne zachowanie AnyObject Swift). - The
var urlString: String?
właściwość jest opcjonalna.
Aby rozwiązać pierwsze dwa opcje, użyj opcjonalnego wiązania / rzutowania do pliku klasa betonu:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "segueToWebView") {
if let button = sender as? TestButton {
// The type of `button` is `TestButton`
// ...
}
}
}
Teraz
var destUrl: String
if button.urlString == nil {
destUrl = "http://www.google.com"
} else {
destUrl = button.urlString!
}
skompilowałaby, ale to jest lepiej obsługiwane z operator zerującego koalescencji:
let destUrl = button.urlString ?? "http://www.google.com"
Pamiętaj, że nie ma wymuszonego rozpakowania !
operator już!
3 dla odpowiedzi № 2
Musisz po prostu zrobić coś takiego:
var destUrl:String
if let durl = sender!.urlString {
destUrl = durl
} else {
destUrl = "http://www.google.com"
}
Problem w kodzie polega na tym, że destUrl to aŁańcuch, ale nadawca! .UrlString jest opcjonalny. Więc nie możesz przypisać jednego do drugiego, musisz odłożyć opcjonalnie przed przypisaniem go albo wymuś to (z!) Albo niech to zrobi. Polecam, jeśli pozwolisz, ale to zależy od ciebie.
3 dla odpowiedzi nr 3
Ręcznie testujesz ciąg znaków dla nil
ale potem zapomnisz go rozwinąć:
var destUrl:String
if sender!.urlString == nil{
destUrl = "http://www.google.com"
} else {
destUrl = sender!.urlString!
}
(Zobacz dodany wykrzyknik.)
Ale rozpakowanie takiego łańcucha jest teraz łatwiejsze:
let destUrl = sender!.urlString ?? "http://www.google.com"
The ??
testy operatora dla zer, rozpakowuje lub zwraca prawą stronę, wszystko w jednym wierszu.