Swift - Chuỗi tùy chọn

Quá trình truy vấn, gọi thuộc tính, chỉ số con và phương thức trên một tùy chọn có thể là 'nil' được định nghĩa là chuỗi tùy chọn. Chuỗi tùy chọn trả về hai giá trị -

  • nếu tùy chọn chứa 'giá trị' thì việc gọi thuộc tính, phương thức và chỉ số con liên quan của nó sẽ trả về giá trị

  • nếu tùy chọn chứa giá trị 'nil', tất cả thuộc tính, phương thức và chỉ số con liên quan của nó sẽ trả về nil

Vì nhiều truy vấn đến các phương thức, thuộc tính và chỉ số con được nhóm lại với nhau, việc không thành một chuỗi sẽ ảnh hưởng đến toàn bộ chuỗi và dẫn đến giá trị 'nil'.

Chuỗi tùy chọn như một biện pháp thay thế cho việc buộc mở gói

Chuỗi tùy chọn được chỉ định sau giá trị tùy chọn bằng '?' để gọi một thuộc tính, phương thức hoặc chỉ số con khi giá trị tùy chọn trả về một số giá trị.

Chuỗi tùy chọn '?' Truy cập vào các phương thức, thuộc tính và chỉ số phụ để buộc Unwrapping
? được đặt sau giá trị tùy chọn để gọi thuộc tính, phương thức hoặc chỉ số con ! được đặt sau giá trị tùy chọn để gọi thuộc tính, phương thức hoặc chỉ số con để buộc bỏ gói giá trị
Không thành công khi tùy chọn là 'nil' Việc mở gói cưỡng bức gây ra lỗi thời gian chạy khi tùy chọn là 'nil'

Chương trình Chuỗi tùy chọn với '!'

class ElectionPoll {
   var candidate: Pollbooth?
}

lass Pollbooth {
   var name = "MP"
}

let cand = ElectionPoll()
let candname = cand.candidate!.name

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

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

Chương trình trên tuyên bố 'cuộc thăm dò bầu cử' là tên lớp và chứa 'ứng cử viên' làm chức năng thành viên. Lớp con được khai báo là 'gian hàng thăm dò ý kiến' và 'tên' là chức năng thành viên của nó được khởi tạo là 'MP'. Lời gọi đến lớp siêu được khởi tạo bằng cách tạo một thể hiện 'cand' với tùy chọn '!'. Vì các giá trị không được khai báo trong lớp cơ sở của nó, nên giá trị 'nil' được lưu trữ do đó trả về một lỗi nghiêm trọng do thủ tục buộc mở gói.

Chương trình cho Chuỗi tùy chọn với '?'

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")
}

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

Candidate name cannot be retreived

Chương trình ở trên khai báo 'cuộc thăm dò bầu cử' là tên lớp và chứa 'ứng cử viên' làm chức năng thành viên. Lớp con được khai báo là 'gian hàng thăm dò ý kiến' và 'tên' là chức năng thành viên của nó được khởi tạo là 'MP'. Lời gọi đến lớp siêu được khởi tạo bằng cách tạo một thể hiện 'cand' với tùy chọn '?'. Vì các giá trị không được khai báo trong lớp cơ sở nên giá trị 'nil' được lưu trữ và in trong bảng điều khiển bởi khối xử lý khác.

Xác định các lớp mô hình cho các thuộc tính truy cập và chuỗi tùy chọn

Ngôn ngữ Swift 4 cũng cung cấp khái niệm về chuỗi tùy chọn, để khai báo nhiều lớp con dưới dạng các lớp mô hình. Khái niệm này sẽ rất hữu ích để định nghĩa các mô hình phức tạp và để truy cập các thuộc tính, phương thức và thuộc tính con subscript.

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")
}

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

Rectangle Area is not specified

Phương thức gọi thông qua chuỗi tùy chọn

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")
}

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

Area of circle is not specified

Hàm circleprint () được khai báo bên trong lớp con circle () được gọi bằng cách tạo một thể hiện có tên là "circlename". Hàm sẽ trả về một giá trị nếu nó chứa một số giá trị, nếu không nó sẽ trả về một số thông báo in do người dùng xác định bằng cách kiểm tra câu lệnh 'if circlename.print? .Circleprint ()! = Nil'.

Truy cập các đăng ký thông qua Chuỗi tùy chọn

Chuỗi tùy chọn được sử dụng để đặt và truy xuất một giá trị chỉ số con để xác thực xem liệu lệnh gọi đến chỉ số con đó có trả về giá trị hay không. '?' được đặt trước dấu ngoặc nhọn chỉ số con để truy cập giá trị tùy chọn trên chỉ số con cụ thể.

Chương trình 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.")
}

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

Radius is not specified.

Trong chương trình trên, các giá trị cá thể cho hàm thành viên 'radiusName' không được chỉ định. Do đó, lệnh gọi của chương trình tới hàm sẽ chỉ trả về một phần khác trong khi để trả về các giá trị mà chúng ta phải xác định các giá trị cho hàm thành viên cụ thể.

Chương trình 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.")
}

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

Radius is measured in Units.

Trong chương trình trên, các giá trị cá thể cho hàm thành viên 'radiusName' được chỉ định. Do đó, chương trình gọi hàm sẽ trả về giá trị.

Truy cập các đăng ký thuộc loại tùy chọn

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])

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

Optional(35)
Optional(78)
Optional(78)
Optional(101)
Optional(90)
Optional(44)
Optional(56)

Có thể truy cập các giá trị tùy chọn cho chỉ số phụ bằng cách tham chiếu các giá trị chỉ số phụ của chúng. Nó có thể được truy cập dưới dạng chỉ số dưới [0], chỉ số dưới [1], v.v. Các giá trị chỉ số dưới mặc định cho 'bán kính' lần đầu tiên được gán là [35, 45, 78, 101] và cho 'Vòng tròn' [90, 45, 56]] . Sau đó, các giá trị chỉ số con được thay đổi như Radius [0] thành 78 và Circle [1] thành 45.

Liên kết nhiều cấp độ chuỗi

Nhiều lớp con cũng có thể được liên kết với các phương thức, thuộc tính và chỉ số con siêu lớp của nó bằng chuỗi tùy chọn.

Nhiều chuỗi tùy chọn có thể được liên kết -

Nếu loại truy xuất không phải là tùy chọn, chuỗi tùy chọn sẽ trả về một giá trị tùy chọn. Ví dụ: nếu Chuỗi thông qua chuỗi tùy chọn, nó sẽ trả về Chuỗi? Giá trị

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.")
}

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

Radius is not specified.

Trong chương trình trên, các giá trị cá thể cho hàm thành viên 'radiusName' không được chỉ định. Do đó, lệnh gọi của chương trình tới hàm sẽ chỉ trả về một phần khác trong khi trả về các giá trị mà chúng ta phải xác định các giá trị cho hàm thành viên cụ thể.

Nếu kiểu truy xuất đã là tùy chọn, thì chuỗi tùy chọn cũng sẽ trả về một giá trị tùy chọn. Ví dụ nếu String? Được truy cập thông qua chuỗi tùy chọn, nó sẽ trả về Chuỗi? Giá trị..

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.")
}

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

Radius is measured in Units.

Trong chương trình trên, các giá trị cá thể cho hàm thành viên 'radiusName' được chỉ định. Do đó, lệnh gọi chương trình đến hàm sẽ trả về giá trị.

Chuỗi trên các phương pháp có giá trị trả lại tùy chọn

Chuỗi tùy chọn cũng được sử dụng để truy cập các phương thức được xác định của lớp con.

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")
}

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

Area of circle is not specified