Co oznacza wykrzyknik w języku Swift?

Język programowania w języku Swift zawiera następujący przykład:

class Person {
    let name: String
    init(name: String) { self.name = name }
    var apartment: Apartment?
    deinit { println("\(name) is being deinitialized") }
}

class Apartment {
    let number: Int
    init(number: Int) { self.number = number }
    var tenant: Person?
    deinit { println("Apartment #\(number) is being deinitialized") }
}

var john: Person?
var number73: Apartment?

john = Person(name: "John Appleseed")
number73 = Apartment(number: 73)

//From Apple's “The Swift Programming Language” guide (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html)
W tym celu należy użyć wykrzyknika, aby "rozpakować instancję":
john!.apartment = number73

Co to znaczy "rozpakować instancję"? Dlaczego jest to konieczne? Czym się to różni od wykonywania następujących czynności:

john.apartment = number73

Jestem bardzo nowy w języku Swift. Staram się opanować podstawy na ziemię.


Aktualizacja:
Duży element układanki, którego mi brakowało (Nie podano bezpośrednio w odpowiedziach - przynajmniej nie w momencie pisania tego), to to, że wykonujesz następujące czynności:]}

var john: Person?

To nie znaczy, że "john jest typu Person i może być Zero", jak początkowo myślałem. Po prostu źle zrozumiałem, że Person i Person? są zupełnie odrębnymi typami. Kiedy to zrozumiałem, wszystkie inne ?, ! madness, and The great Odpowiedzi poniżej, miały o wiele więcej sensu.

Author: Cœur, 2014-06-03

22 answers

Co to znaczy "rozpakować instancję"? Dlaczego jest to konieczne?

Z tego co wiem (Dla mnie to też nowość)...

Termin "owinięty" sugeruje, że powinniśmy pomyśleć o zmiennej opcjonalnej jako prezencie, owiniętym błyszczącym papierem, co może (niestety!) be empty .

Gdy "zawinięta", wartość zmiennej opcjonalnej jest enum z dwoma możliwymi wartościami (trochę jak logika logiczna). To wyliczenie opisuje, czy zmienna posiada value (Some(T)), or not (None).

Jeśli istnieje wartość, można ją uzyskać przez "rozpakowanie" zmiennej (uzyskanie T z Some(T)).

Czym różni się john!.apartment = number73 od john.apartment = number73? (Parafrazowane)

Jeśli wpisujesz nazwę zmiennej opcjonalnej (np. tekst john, Bez !), odnosi się to do" zawiniętego " enum( Some / None), a nie do samej wartości (T). Tak więc john nie jest instancją Person i nie ma apartment członka:

john.apartment
// 'Person?' does not have a member named 'apartment'

The rzeczywista wartość Person może być rozpakowana na różne sposoby:

    W przypadku, gdy nie jest to możliwe, nie jest to konieczne, ponieważ nie jest to konieczne.]} Jeśli wartość istnieje, to nie jest to możliwe.]} Jest to metoda, która pozwala na tworzenie łańcuchów, jeśli wartość istnieje.]}

Myślę, że wybierasz jeden z tych sposobów rozpakowania, w zależności od tego, co powinno się wydarzyć w przypadku nil i jak prawdopodobne jest to. Ten język konstrukcja wymusza jawną obsługę nil case, co, jak przypuszczam, poprawia bezpieczeństwo w stosunku do Obj-C (gdzie łatwo jest zapomnieć o obsłudze nil case).

Update :

Wykrzyknik jest również używany w składni do deklarowania "domyślnie rozpakowanych opcji".

W dotychczasowych przykładach zmienna john została zadeklarowana jako var john:Person? i jest opcjonalna. Jeśli chcesz uzyskać rzeczywistą wartość tej zmiennej, musisz ją rozpakować, używając jednej z trzech metod powyżej.

Gdyby została zadeklarowana jako var john:Person!, zmienna byłaby domyślnie rozpakowana Opcjonalnie (zobacz sekcję z tym nagłówkiem w książce Apple ' a). Nie ma potrzeby rozpakowywania tego rodzaju zmiennej podczas uzyskiwania dostępu do wartości, a john może być używana bez dodatkowej składni. Ale książka Apple mówi:

Domyślnie rozpakowane opcje nie powinny być używane, gdy istnieje możliwość, że zmienna stanie się Zerowa W późniejszym momencie. Zawsze używaj zwykłego typu opcjonalnego, jeśli musisz sprawdzić wartość nil podczas życia zmiennej.

Aktualizacja 2:

Artykuł" Interesting Swift Features "autorstwa Mike' a Asha daje pewną motywację dla opcjonalnych typów. Myślę, że to świetne, jasne pismo.

Aktualizacja 3:

Kolejny przydatny artykuł o domyślnie rozpakowanym opcjonalnym używaniu wykrzyknika: "Swift and The Last Mile " autorstwa Chrisa Adamsona. Artykuł wyjaśnia że jest to środek pragmatyczny zastosowany przez Apple do deklarowania typów stosowanych przez ich ramy Objective-C, które mogą zawierać zero. Deklarowanie typu jako opcjonalnego (za pomocą ?) lub domyślnie rozpakowanego (za pomocą !) jest "kompromitacją między bezpieczeństwem a wygodą". W przykładach podanych w artykule, Apple zdecydowało się zadeklarować typy jako domyślnie rozpakowane, dzięki czemu kod wywołujący jest wygodniejszy, ale mniej bezpieczny.

[[25]}być może Apple przeczesać ich frameworki w przyszłości, usunięcie niepewności niedokładnie rozpakowanych ("prawdopodobnie nigdy zero") parametrów i zastąpienie ich opcjonalnymi ("z pewnością może być Zero w szczególności [miejmy nadzieję, udokumentowane!] okoliczności") lub standardowe deklaracje nieobowiązkowe ("is never nil"), oparte na dokładnym zachowaniu ich kodu Objective-C.
 494
Author: Ashley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-04 11:28:24

Oto co myślę jest różnica:

var john: Person?

Oznacza, że john może być zerowy

john?.apartment = number73

Kompilator zinterpretuje tę linię jako:

if john != nil {
    john.apartment = number73
}

While

john!.apartment = number73

Kompilator zinterpretuje tę linię jako po prostu:

john.apartment = number73

Stąd używanie ! rozpakuje instrukcję if I sprawi, że będzie działać szybciej, ale jeśli john ma wartość nil, wtedy wystąpi błąd runtime.

Więc zawinięcie tutaj nie oznacza, że jest owinięte pamięcią, ale oznacza, że jest owinięte kodem, w tym przypadku jest owinięte z instrukcją if, a ponieważ Apple przywiązuje szczególną uwagę do wydajności w czasie wykonywania, chcą dać ci sposób, aby aplikacja działała z najlepszą możliwą wydajnością.

Update:

Wracając do tej odpowiedzi po 4 latach, ponieważ uzyskałem z niej najwyższą reputację w Stackoverflow :) Trochę źle zrozumiałem znaczenie rozpakowywania w tym czasie. Teraz po 4 latach wierzę, że sens rozpakowywania tutaj jest rozszerzenie kodu z jego oryginalnej kompaktowej formy. Oznacza to również usunięcie niejasności wokół tego obiektu, ponieważ nie jesteśmy pewni z definicji, że jest zerowy lub nie. Tak jak odpowiedź Ashley powyżej, pomyśl o tym jak o prezencie, który nie może zawierać nic w sobie. Ale nadal uważam, że rozpakowywanie to rozpakowywanie kodu, a nie rozpakowywanie oparte na pamięci jako użycie enum.

 119
Author: Amr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-11 20:01:28

TL;DR

Co oznacza wykrzyknik w języku Swift?

Wykrzyknik skutecznie mówi: "Wiem, że to opcjonalne zdecydowanie ma wartość; proszę go użyć."Jest to znane jako wymuszone rozpakowanie wartości opcjonalnej:

Przykład

let possibleString: String? = "An optional string."
print(possibleString!) // requires an exclamation mark to access its value
// prints "An optional string."

let assumedString: String! = "An implicitly unwrapped optional string."
print(assumedString)  // no exclamation mark is needed to access its value
// prints "An implicitly unwrapped optional string."

Źródło: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_399

 62
Author: Alex Nolasco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-29 16:36:15

If john were a optional var (declared thusly)

var john: Person?

Wtedy byłoby możliwe, aby john nie miał żadnej wartości (w języku Objective, nil value)

Wykrzyknik w zasadzie mówi kompilatorowi "wiem, że to ma wartość, nie musisz tego testować". Jeśli nie chcesz go używać, możesz go warunkowo przetestować:

if let otherPerson = john {
    otherPerson.apartment = number73
}

Wnętrze tego będzie oceniać tylko wtedy, gdy john ma wartość.

 37
Author: Ben Gottlieb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-03 15:06:11

Niektóre duże perspektywy obrazu, aby dodać do innych przydatnych, ale bardziej skoncentrowanych na szczegółach odpowiedzi:

W języku Swift wykrzyknik pojawia się w kilku kontekstach:]}
  • przymusowe rozpakowywanie: let name = nameLabel!.text
  • domyślnie rozpakowane opcje: var logo: UIImageView!
  • Wymuszony casting: logo.image = thing as! UIImage
  • nieobsługiwane wyjątki: try! NSJSONSerialization.JSONObjectWithData(data, [])

Każdy z nich jest inną konstrukcją językową o innym znaczeniu, ale wszystkie mają trzy ważne rzeczy w często:

1. Wykrzykniki omijają kontrolę bezpieczeństwa Swifta w czasie kompilacji.

Kiedy używasz ! w języku Swift, zasadniczo mówisz: "Hej, kompilatorze, wiem, że uważasz, że błąd może się tutaj zdarzyć, ale ja {38]}wiem {39]} z całkowitą pewnością, że nigdy nie nastąpi."

Nie wszystkie poprawne kody mieszczą się w polu systemu typu kompilacji Swifta-lub dowolnego języka, jeśli o to chodzi. Są sytuacje, w których można logicznie udowodnij, że błąd nigdy się nie wydarzy, ale nie możesz udowodnić tego kompilatorowi. Dlatego projektanci Swifta dodali te funkcje w pierwszej kolejności.

Jednakże, gdy używasz !, wykluczasz ścieżkę odzyskiwania dla błędu, co oznacza, że...]}

2. Wykrzykniki to potencjalne awarie.

Wykrzyknik mówi również: "Hej Swift, jestem więc pewien, że ten błąd nigdy się nie zdarzy, że lepiej dla Ciebie awaria całej aplikacji niż jest dla mnie, aby zakodować ścieżkę odzyskiwania dla niego."

To niebezpieczne twierdzenie. To Może być poprawne: w kodzie krytycznym misji, gdzie ciężko myślałeś o niezmiennikach kodu, może być tak, że fałszywe wyjście jest gorsze niż awaria.

Jednakże, kiedy widzę ! na wolności, rzadko używa się go tak uważnie. Zamiast tego, zbyt często oznacza to: "ta wartość była opcjonalna i tak naprawdę nie myślałem zbyt mocno o dlaczego to może być nil lub jak poprawnie poradzić sobie z tą sytuacją, ale dodanie ! sprawiło, że się skompilowało ... więc mój kod jest poprawny, prawda?"

[[19]}Strzeż się arogancji wykrzyknika. Zamiast ...

3. Wykrzykniki najlepiej stosować oszczędnie.

Każdy z tych ! konstruktów ma ? odpowiednik, który zmusza cię do radzenia sobie z przypadkiem błędu/zera:

  • warunkowe rozpakowanie: if let name = nameLabel?.text { ... }
  • opcje: var logo: UIImageView?
  • rzuty warunkowe: logo.image = thing as? UIImage
  • wyjątki Zero-on-failure: try? NSJSONSerialization.JSONObjectWithData(data, [])

Jeśli masz ochotę użyć !, zawsze dobrze jest dokładnie rozważyć, dlaczego nie używasz ? zamiast tego. Czy awaria programu jest naprawdę najlepszą opcją, jeśli operacja ! nie powiedzie się? dlaczego ta wartość jest opcjonalna/niemożliwa?

Czy istnieje rozsądna ścieżka odzyskiwania Twojego kodu w przypadku braku / błędu? Jeśli tak, to koduj.

Jeśli nie może być nil, jeśli błąd nigdy się nie wydarzy, to czy istnieje rozsądny sposób na przerobienie logiki, aby kompilator o tym wiedział? Jeśli tak, zrób to; Twój kod będzie mniej podatny na błędy.

Są chwile, kiedy nie ma rozsądnego sposobu na poradzenie sobie z błędem, a zwykłe zignorowanie błędu-a tym samym Postępowanie z błędnymi danymi-byłoby gorsze niż awaria. te to czas, by użyć siły rozpakowywania.

Okresowo przeszukuję całą bazę kodową pod kątem ! i sprawdzam każde jej użycie. Bardzo nieliczne zwyczaje stawiają na Kontrola. (W chwili pisania tego tekstu cały Framework Siesta ma dokładnie dwa instancje tego.)

Nie oznacza to, że powinieneś nigdy używać ! w swoim kodzie - tylko, że powinieneś używać go uważnie i nigdy nie robić z niego opcji domyślnej.

 25
Author: Paul Cantrell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-20 22:20:56

john jest opcjonalnym var. Więc może zawierać nil wartość. Aby upewnić się, że wartość nie jest zerowa, użyj ! na końcu nazwy var.

Z dokumentacji

"Po upewnieniu się, że opcja zawiera wartość, możesz uzyskać dostęp do jej podstawowej wartości, dodając wykrzyknik (!) na końcu nazwy opcjonalnej. Wykrzyknik skutecznie mówi: "Wiem, że ta opcja zdecydowanie ma wartość; proszę jej użyć."

Inny sposób na check non nil value is

    if let j = json {
        // do something with j
    }
 24
Author: Fry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-19 15:30:21

Oto kilka przykładów:

var name:String = "Hello World"
var word:String?

Gdzie word jest wartością opcjonalną. oznacza, że może zawierać lub nie może zawierać wartości.

word = name 

Tutaj name ma wartość, więc możemy ją przypisać

var cow:String = nil
var dog:String!

Gdzie {[6] } jest rozpakowany oznacza, że musi zawierać wartość

dog = cow

Aplikacja ulegnie awarii, ponieważ przypisujemy nil do unwrapped

 16
Author: Ramkumar chintala,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-01 07:25:53

W tym przypadku...

Var John: Person!

Oznacza to, że początkowo John będzie miał wartość nil, zostanie ona ustawiona i raz ustawiona już nigdy nie będzie Nil-led. Dlatego dla wygody mogę użyć łatwiejszej składni dostępu do opcjonalnego var, ponieważ jest to "Unwrapped optional"

 13
Author: guest,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-24 21:50:01

Jeśli pochodzisz z języka rodziny C, będziesz myśleć o " wskaźniku do obiektu typu X, który może być adresem pamięci 0 (NULL)", a jeśli pochodzisz z dynamicznie wpisywanego języka, będziesz myśleć o "obiekcie, który prawdopodobnie jest typu X, ale może być typu niezdefiniowanego". Żadna z nich nie jest poprawna, chociaż w sposób okrężny pierwsza jest bliska.

Sposób, w jaki powinieneś o tym myśleć, jest tak, jakby to był obiekt w stylu:

struct Optional<T> {
   var isNil:Boolean
   var realObject:T
}

Kiedy testujesz twoja opcjonalna wartość z {[3] }to naprawdę zwraca foo.isNil, a kiedy mówisz foo! to zwraca foo.realObject z twierdzeniem, że foo.isNil == false. Ważne jest, aby to zauważyć, ponieważ jeśli foo rzeczywiście jest nil, gdy robisz foo!, jest to błąd runtime, więc zazwyczaj chcesz zamiast tego użyć warunkowego let, chyba że jesteś pewien, że wartość nie będzie nil. Ten rodzaj oszustwa oznacza, że język może być mocno wpisany bez zmuszania do testowania, czy wartości są wszędzie zerowe.

W praktyka, nie zachowuje się tak naprawdę, ponieważ praca jest wykonywana przez kompilator. Na wysokim poziomie istnieje Typ Foo?, który jest oddzielny od Foo, co uniemożliwia funkcjom akceptującym typ Foo otrzymywanie wartości nil, ale na niskim poziomie opcjonalna wartość nie jest prawdziwym obiektem, ponieważ nie ma żadnych właściwości ani metod; jest prawdopodobne, że w rzeczywistości jest to wskaźnik, który może przez NULL(0) z odpowiednim testem podczas rozpakowywania siły.

Jest inna sytuacja, w której zobaczyłbyś wykrzyknik jest na typie, jak w:

func foo(bar: String!) {
    print(bar)
}
Jest to w przybliżeniu równoznaczne z zaakceptowaniem opcjonalnego z wymuszonym rozpakowaniem, tj.:]}
func foo(bar: String?) {
    print(bar!)
}

Możesz użyć tej metody, aby mieć metodę, która technicznie akceptuje wartość opcjonalną, ale będzie miała błąd runtime, jeśli jest nil. W obecnej wersji Swift to najwyraźniej omija twierdzenie is-not-nil, więc zamiast tego będziesz miał błąd niskiego poziomu. Ogólnie nie jest to dobry pomysł, ale może być przydatny przy konwersji kodu z innego język.

 4
Author: Jim Driscoll,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-19 10:52:24

The ! oznacza, że jesteś siłą rozpakowywania obiektu ! / align = "left" / Więcej informacji można znaleźć w dokumentacji Apples, która znajduje się tutaj: https://developer.apple.com/library/ios/documentation/swift/conceptual/Swift_Programming_Language/TheBasics.html

 3
Author: Henry oscannlain-miller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-16 02:30:05

Jeśli znasz C#, jest to jak typy Nullable, które są również deklarowane za pomocą znaku zapytania:

Person? thisPerson;

I wykrzyknik w tym przypadku jest równoznaczny zWłaściwość Value typu nullable w ten sposób:

thisPerson.Value
 3
Author: Abdurrahman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-20 14:23:42

W celu C zmienne bez wartości były równe "nil"(możliwe było również użycie wartości " nil "takich samych jak 0 I false), stąd możliwe było użycie zmiennych w instrukcjach warunkowych (zmienne o wartościach są takie same jak "TRUE", a te bez wartości były równe "FALSE").

Swift zapewnia bezpieczeństwo typu poprzez podanie "opcjonalnej wartości". tzn. zapobiega powstawaniu błędów przy przypisywaniu zmiennych różnych typów.

Więc w Swift można podać tylko booleany na instrukcje warunkowe.

var hw = "Hello World"

Tutaj, nawet-choć' hw ' jest ciągiem znaków, nie może być użyty w instrukcji if, jak w objective C.

//This is an error

if hw

 {..}

Do tego musi być stworzony jako,

var nhw : String? = "Hello World"

//This is correct

if nhw

 {..}
 2
Author: Gokul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-26 17:56:36

The ! na końcu obiektu mówi, że obiekt jest opcjonalny i rozpakować, jeśli może w przeciwnym razie zwraca zero. Jest to często używane do przechwytywania błędów, które w przeciwnym razie spowodowałyby awarię programu.

 2
Author: cheborneck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-09 06:09:20

W Skrócie (!): Po zadeklarowaniu zmiennej i upewnieniu się, że zmienna zawiera wartość.

let assumedString: String! = "Some message..."
let implicitString: String = assumedString

W przeciwnym razie musiałbyś to zrobić na każdym po przekazaniu wartości...

let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // requires an exclamation mark
 2
Author: En Hui Lim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-07 07:53:49

John jest osobą opcjonalną, co oznacza, że może posiadać wartość lub być zerowe.

john.apartment = number73

Jest używany, jeśli john nie jest opcjonalny. Ponieważ john nigdy nie jest zerowy, możemy być pewni, że nie zadzwoni do mieszkania na zero. While

john!.apartment = number73

Obiecuje kompilatorowi, że john nie jest nil, a następnie rozpakowuje opcję, aby uzyskać wartość Johna i uzyskuje dostęp do własności mieszkania Johna. Użyj tego, jeśli wiesz, że john nie jest nil. Jeśli wywołasz to na zero opcjonalne, pojawi się błąd runtime.

Dokumentacja zawiera ładny przykład użycia tego, gdzie convertedNumber jest opcjonalny.

if convertedNumber {
    println("\(possibleNumber) has an integer value of \(convertedNumber!)")
} else {
    println("\(possibleNumber) could not be converted to an integer")
}
 1
Author: Connor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-03 15:12:04

Mówiąc prościej, wykrzykniki oznaczają, że opcja jest rozpakowywana. Opcjonalna jest zmienna, która może mieć wartość lub nie -- więc możesz sprawdzić, czy zmienna jest pusta, używając instrukcji if let Jak pokazano tutaj, a następnie wymusić jej rozpakowanie. Jeśli wymusisz rozpakowanie opcji, która jest pusta, Twój program ulegnie awarii, więc uważaj! Opcjonalne deklaruje się poprzez umieszczenie znaku zapytania na końcu jednoznacznego przypisania zmiennej, np. I could napisz:

var optionalExample: String?

Ta zmienna nie ma wartości. Gdybym miał go rozpakować, program się zawiesi i Xcode powie Ci, że próbowałeś rozpakować opcję o wartości zero.

Mam nadzieję, że to pomogło.
 1
Author: brimstone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-26 18:25:25

W PROSTYCH SŁOWACH

Użycie wykrzyknika oznacza, że zmienna musi składać się z wartości innej niż nil (nigdy nie będzie nil)

 1
Author: Maninderjit Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-23 13:03:00

Cała historia zaczyna się od funkcji swift zwanej opcjonalnymi varami. Są to zmienne, które mogą mieć wartość lub mogą nie mieć wartości. Ogólnie swift nie pozwala nam używać zmiennej, która nie jest inicjalizowana, ponieważ może to prowadzić do awarii lub nieoczekiwanych powodów, a także serwera zastępczego dla backdoorów. Tak więc w celu zadeklarowania zmiennej, której wartość nie jest wstępnie określona, używamy'?'. Gdy taka zmienna jest zadeklarowana, aby użyć jej jako części jakiegoś wyrażenia, należy ją rozpakować przed ich użyciem rozpakowywanie jest operacją, za pomocą której odkrywana jest wartość zmiennej. dotyczy to obiektów. Bez rozpakowywania jeśli spróbujesz ich użyć, będziesz miał błąd czasu kompilacji. Aby rozpakować zmienną, która jest opcjonalnym var, wykrzyknik"!"jest używany.

Teraz są czasy, kiedy wiesz, że takie opcjonalne zmienne będą przypisane wartości przez system na przykład lub własny program, ale jakiś czas później, na przykład gniazda UI, w takiej sytuacji zamiast deklarować opcjonalna zmienna ze znakiem zapytania"?"używamy"!".

Tak więc system wie, że ta zmienna, która jest zadeklarowana przez"!"jest opcjonalny w tej chwili i nie ma wartości, ale otrzyma wartość w późniejszym okresie życia.

Tak więc wykrzyknik ma dwa różne zastosowania, 1. Aby zadeklarować zmienną, która będzie opcjonalna i otrzyma wartość zdecydowanie później 2. Aby rozpakować opcjonalną zmienną przed użyciem jej w wyrażeniu.

Powyższe opisy unika zbyt wielu mam nadzieję, że TECHNICZNE.

 1
Author: vishal dharankar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-19 11:02:42

Jeśli użyjesz go jako opcji, rozpakuje opcję i zobaczy, czy coś tam jest. Jeśli użyjesz go w instrukcji if-else is to kod dla NOT. Na przykład,

if (myNumber != 3){
 // if myNumber is NOT 3 do whatever is inside these brackets.
)
 1
Author: Andy Lebowitz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-14 03:13:12

Zmienna opcjonalna może zawierać wartość lub może nie być

Case 1: var myVar:String? = "Something"

Case 2: var myVar:String? = nil

Teraz, jeśli zapytasz myVar!, każesz kompilatorowi zwracać wartość w przypadku 1 zwróci "Something"

W przypadku 2 to się rozbije.

To znaczy ! mark zmusi kompilator do zwrócenia wartości, nawet jeśli jej tam nie ma. dlatego nazwa wymusza rozpakowywanie.
 1
Author: Ashish Pisey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-18 04:29:03
Simple the Optional variable allows nil to be stored.

var str : String? = nil

str = "Data"

To convert Optional to the Specific DataType, We unwrap the variable using the keyword "!"

func get(message : String){
   return
}

get(message : str!)  // Unwapped to pass as String
 0
Author: jeff ayan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-19 08:01:03

ZAPYTAJ SIEBIE

  • czy typ person? masz apartment członka / własność? Lub
  • czy typ person masz apartment członka / własność?
Jeśli nie możesz odpowiedzieć na to pytanie, Czytaj dalej]}

aby zrozumieć, możesz potrzebować super-podstawowego poziomu zrozumienia generyków . Zobacz tutaj . Wiele rzeczy w języku Swift jest pisanych przy użyciu generyków. Opcje zawarte

The poniższy kod został udostępniony z tego filmu. Gorąco polecam obejrzeć pierwsze 5 minut

Opcjonalny jest enum z tylko 2 przypadkami

enum Optional<T>{
    case None
    case Some(T)
}

let x: String? = nil //actually means:

let x = Optional<String>.None

let x :String? = "hello" //actually means:

let x = Optional<String>.Some("hello")

var y = x! // actually means:

switch x {
case .Some(let value): y = value
case .None: // Raise an exception
}

Opcjonalne oprawa:

let x:String? = something
if let y = x {
    // do something with y
}
//Actually means:

switch x{
case .Some(let y): print)(y) // or whatever else you like using 
case .None: break
}

Kiedy mówisz var john: Person? masz na myśli takie:

enum Optional<Person>{
case .None
case .Some(Person)
}

Czy powyższy enum ma jakąś właściwość o nazwie apartment? Widzisz to gdzieś? To jest Nie tam w ogóle! Jednak jeśli rozpakujesz go ie do person! wtedy możesz ... to co robi pod maską to: Optional<Person>.Some(Person(name: "John Appleseed"))


Gdybyś zdefiniował var john: Person zamiast: var john: Person? wtedy nie musiałbyś już używać !, ponieważ Person samo w sobie ma element apartment


Jako przyszła dyskusja na temat dlaczego używanie ! do rozpakowania jest czasami nie zalecane zobacz to Q & A {22]}

 -1
Author: Honey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-12 18:45:40