Swift - необязательная цепочка
Процесс запроса, вызова свойств, индексов и методов для необязательного элемента, который может иметь значение «nil», определяется как необязательное связывание. Необязательная цепочка возвращает два значения -
если необязательный параметр содержит 'значение', тогда вызов его связанного свойства, методов и индексов возвращает значения
если необязательный параметр содержит значение 'nil', все связанные с ним свойства, методы и индексы возвращают значение nil
Поскольку несколько запросов к методам, свойствам и индексам сгруппированы вместе, отказ одной цепочки повлияет на всю цепочку и приведет к значению «ноль».
Дополнительное связывание как альтернатива принудительному разворачиванию
Необязательная цепочка указывается после необязательного значения с помощью '?' для вызова свойства, метода или индекса, когда необязательное значение возвращает некоторые значения.
Необязательная цепочка '?' | Доступ к методам, свойствам и индексам. Дополнительная цепочка '!' заставить распаковывать |
? помещается после необязательного значения для вызова свойства, метода или индекса | ! помещается после необязательного значения для вызова свойства, метода или индекса, чтобы принудительно развернуть значение |
Изящно терпит неудачу, если необязательный параметр равен 'nil' | Принудительное развертывание вызывает ошибку времени выполнения, если необязательный параметр равен 'nil' |
Программа для необязательного связывания с '!'
class ElectionPoll {
var candidate: Pollbooth?
}
lass Pollbooth {
var name = "MP"
}
let cand = ElectionPoll()
let candname = cand.candidate!.name
Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат -
fatal error: unexpectedly found nil while unwrapping an Optional value
0 Swift 4 0x0000000103410b68
llvm::sys::PrintStackTrace(__sFILE*) + 40
1 Swift 4 0x0000000103411054 SignalHandler(int) + 452
2 libsystem_platform.dylib 0x00007fff9176af1a _sigtramp + 26
3 libsystem_platform.dylib 0x000000000000000b _sigtramp + 1854492939
4 libsystem_platform.dylib 0x00000001074a0214 _sigtramp + 1976783636
5 Swift 4 0x0000000102a85c39
llvm::JIT::runFunction(llvm::Function*, std::__1::vector > const&) + 329
6 Swift 4 0x0000000102d320b3
llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*,
std::__1::vector<std::__1::basic_string, std::__1::allocator >,
std::__1::allocator<std::__1::basic_string, std::__1::allocator > > > const&,
char const* const*) + 1523
7 Swift 4 0x000000010296e6ba Swift 4::RunImmediately(Swift
4::CompilerInstance&, std::__1::vector<std::__1::basic_string,
std::__1::allocator >, std::__1::allocator<std::__1::basic_string,
std::__1::allocator > > > const&, Swift 4::IRGenOptions&, Swift 4::SILOptions
const&) + 1066
8 Swift 4 0x000000010275764b frontend_main(llvm::ArrayRef,
char const*, void*) + 5275
9 Swift 4 0x0000000102754a6d main + 1677
10 libdyld.dylib 0x00007fff8bb9e5c9 start + 1
11 libdyld.dylib 0x000000000000000c start + 1950751300
Stack dump:
0. Program arguments:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/
usr/bin/Swift 4 -frontend -interpret - -target x86_64-apple-darwin14.0.0 -
target-cpu core2 -sdk
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/
SDKs/MacOSX10.10.sdk -module-name main
/bin/sh: line 47: 15672 Done cat <<'SWIFT 4'
import Foundation
</std::__1::basic_string</std::__1::basic_string</std::__1::basic_string</std::
__1::basic_string
Вышеупомянутая программа объявляет «избирательный опрос» как имя класса и содержит «кандидат» как функцию принадлежности. Подкласс объявлен как 'poll booth' и 'name' как его функция принадлежности, которая инициализируется как 'MP'. Вызов суперкласса инициализируется путем создания экземпляра cand с необязательным символом «!». Поскольку значения не объявлены в его базовом классе, сохраняется значение 'nil', что возвращает фатальную ошибку в результате процедуры принудительного разворачивания.
Программа для необязательного связывания с '?'
class ElectionPoll {
var candidate: Pollbooth?
}
class Pollbooth {
var name = "MP"
}
let cand = ElectionPoll()
if let candname = cand.candidate?.name {
print("Candidate name is \(candname)")
} else {
print("Candidate name cannot be retreived")
}
Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат -
Candidate name cannot be retreived
Программа выше объявляет «избирательный опрос» как имя класса и содержит «кандидат» как функцию принадлежности. Подкласс объявлен как 'poll booth' и 'name' как его функция принадлежности, которая инициализируется как 'MP'. Вызов суперкласса инициализируется путем создания экземпляра "cand" с необязательным "?". Поскольку значения не объявлены в его базовом классе, значение 'nil' сохраняется и печатается в консоли блоком обработчика else.
Определение классов модели для необязательного связывания и доступа к свойствам
Язык Swift 4 также предоставляет концепцию необязательной цепочки для объявления более одного подкласса как классов модели. Эта концепция будет очень полезна для определения сложных моделей и доступа к подсвойствам свойств, методов и индексов.
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var street: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let rectname = rectangle()
if let rectarea = rectname.print?.cprint {
print("Area of rectangle is \(rectarea)")
} else {
print("Rectangle Area is not specified")
}
Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат -
Rectangle Area is not specified
Вызов методов через необязательную цепочку
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("Area of Circle is: \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let circname = rectangle()
if circname.print?.circleprint() != nil {
print("Area of circle is specified)")
} else {
print("Area of circle is not specified")
}
Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат -
Area of circle is not specified
Функция circleprint (), объявленная внутри подкласса circle (), вызывается путем создания экземпляра с именем circname. Функция вернет значение, если оно содержит какое-либо значение, в противном случае она вернет определенное пользователем сообщение печати, проверив оператор 'if circname.print? .Circleprint ()! = Nil'.
Доступ к индексам через опциональную цепочку
Необязательная цепочка используется для установки и извлечения значения индекса, чтобы проверить, возвращает ли вызов этого индекса значение. '?' помещается перед фигурными скобками нижнего индекса для доступа к необязательному значению в конкретном нижнем индексе.
Программа 1
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let circname = rectangle()
if let radiusName = circname.print?[0].radiusname {
print("The first room name is \(radiusName).")
} else {
print("Radius is not specified.")
}
Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат -
Radius is not specified.
В приведенной выше программе значения экземпляра для функции принадлежности "radiusName" не указаны. Следовательно, программный вызов функции вернет только остальную часть, тогда как для возврата значений мы должны определить значения для конкретной функции принадлежности.
Программа 2
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")
let printing = circle()
printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing
if let radiusName = circname.print?[0].radiusname {
print("Radius is measured in \(radiusName).")
} else {
print("Radius is not specified.")
}
Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат -
Radius is measured in Units.
В приведенной выше программе указаны значения экземпляра для функции принадлежности "radiusName". Следовательно, программный вызов функции теперь будет возвращать значения.
Доступ к индексам необязательного типа
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")
let printing = circle()
printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing
var area = ["Radius": [35, 45, 78, 101], "Circle": [90, 45, 56]]
area["Radius"]?[1] = 78
area["Circle"]?[1]--
print(area["Radius"]?[0])
print(area["Radius"]?[1])
print(area["Radius"]?[2])
print(area["Radius"]?[3])
print(area["Circle"]?[0])
print(area["Circle"]?[1])
print(area["Circle"]?[2])
Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат -
Optional(35)
Optional(78)
Optional(78)
Optional(101)
Optional(90)
Optional(44)
Optional(56)
К необязательным значениям индексов можно получить доступ, указав их значения индексов. Доступ к нему можно получить как нижний индекс [0], нижний индекс [1] и т. Д. Значения нижнего индекса по умолчанию для «радиуса» сначала назначаются как [35, 45, 78, 101] и для «Круг» [90, 45, 56]] . Затем значения нижнего индекса изменяются с Радиуса [0] на 78 и Круг [1] на 45.
Связывание нескольких уровней цепочки
Несколько подклассов также могут быть связаны с его методами, свойствами и индексами суперкласса с помощью необязательной цепочки.
Можно связать несколько опциональных цепочек -
Если тип получения не является необязательным, необязательная цепочка вернет необязательное значение. Например, если String через необязательную цепочку вернет String? Значение
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let circname = rectangle()
if let radiusName = circname.print?[0].radiusname {
print("The first room name is \(radiusName).")
} else {
print("Radius is not specified.")
}
Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат -
Radius is not specified.
В приведенной выше программе значения экземпляра для функции принадлежности "radiusName" не указаны. Следовательно, программный вызов функции вернет только другую часть, тогда как для возврата значений мы должны определить значения для конкретной функции принадлежности.
Если тип получения уже является необязательным, то необязательное связывание также вернет необязательное значение. Например, если String? Доступен через необязательную цепочку, он вернет String? Значение..
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")
let printing = circle()
printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing
if let radiusName = circname.print?[0].radiusname {
print("Radius is measured in \(radiusName).")
} else {
print("Radius is not specified.")
}
Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат -
Radius is measured in Units.
В приведенной выше программе указаны значения экземпляра для функции принадлежности "radiusName". Следовательно, программный вызов функции теперь будет возвращать значения.
Цепочка методов с дополнительными возвращаемыми значениями
Необязательная цепочка также используется для доступа к методам, определенным подклассами.
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("Area of Circle is: \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let circname = rectangle()
if circname.print?.circleprint() != nil {
print("Area of circle is specified)")
} else {
print("Area of circle is not specified")
}
Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат -
Area of circle is not specified