Swift-선택적 체인
'nil'일 수있는 옵션에 대한 쿼리, 호출 속성, 첨자 및 메서드는 선택적 체인으로 정의됩니다. 선택적 체인 반환 두 값-
옵션에 '값'이 포함 된 경우 관련 속성, 메서드 및 아래 첨자를 호출하면 값이 반환됩니다.
옵션에 'nil'값이 포함 된 경우 모든 관련 속성, 메서드 및 첨자가 nil을 반환합니다.
메서드, 속성 및 아래 첨자에 대한 여러 쿼리가 함께 그룹화되기 때문에 하나의 체인에 대한 실패는 전체 체인에 영향을 미치고 'nil'값이됩니다.
강제 언 래핑에 대한 대안으로 선택적 체인
선택적 연결은 '?'와 함께 선택적 값 뒤에 지정됩니다. 선택적 값이 일부 값을 반환 할 때 속성, 메서드 또는 아래 첨자를 호출합니다.
선택적 연결 '?' | 메서드, 속성 및 아래 첨자에 대한 액세스 선택적 연결 '!' Unwrapping 강제 |
? 속성, 메서드 또는 아래 첨자를 호출하는 선택적 값 뒤에 배치됩니다. | ! 값의 래핑을 강제로 풀기 위해 속성, 메서드 또는 아래 첨자를 호출하는 선택적 값 뒤에 배치됩니다. |
선택 사항이 'nil'인 경우 정상적으로 실패합니다. | 선택 사항이 'nil'인 경우 강제 래핑 해제는 런타임 오류를 트리거합니다. |
'!'를 사용한 선택적 체인 프로그램
class ElectionPoll {
var candidate: Pollbooth?
}
lass Pollbooth {
var name = "MP"
}
let cand = ElectionPoll()
let candname = cand.candidate!.name
Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.
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
위 프로그램은 '선거 투표'를 클래스 명으로 선언하고 멤버십 기능으로 '후보'를 포함하고있다. 서브 클래스는 '폴 부스'로 선언되고 멤버십 기능으로 '이름'이 '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")
}
Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.
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")
}
Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.
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")
}
Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.
Area of circle is not specified
circle () 하위 클래스 내에서 선언 된 circleprint () 함수는 '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.")
}
Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.
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.")
}
Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.
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])
Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.
Optional(35)
Optional(78)
Optional(78)
Optional(101)
Optional(90)
Optional(44)
Optional(56)
첨자의 선택적 값은 첨자 값을 참조하여 액세스 할 수 있습니다. 아래 첨자 [0], 아래 첨자 [1] 등으로 액세스 할 수 있습니다. '반경'의 기본 아래 첨자 값은 먼저 [35, 45, 78, 101] 및 '원'[90, 45, 56]]으로 할당됩니다. . 그런 다음 아래 첨자 값이 Radius [0]에서 78로, Circle [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.")
}
Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.
Radius is not specified.
위 프로그램에서는 멤버십 함수 'radiusName'의 인스턴스 값이 지정되지 않았습니다. 따라서 함수에 대한 프로그램 호출은 else 부분 만 반환하는 반면 값을 반환하려면 특정 멤버십 함수에 대한 값을 정의해야합니다.
검색 유형이 이미 선택 사항 인 경우 선택적 연결도 선택적 값을 반환합니다. 예를 들어 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.")
}
Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.
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")
}
Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.
Area of circle is not specified