目录

Swift - 快速指南

Swift - Overview

Swift 4是Apple Inc为iOS和OS X开发开发的一种新编程语言。 Swift 4采用了C和Objective-C中最好的,没有C兼容性的限制。

  • Swift 4使用安全的编程模式。

  • Swift 4提供现代编程功能。

  • Swift 4提供类似Objective-C的语法。

  • Swift 4是编写iOS和OS X应用程序的绝佳方式。

  • Swift 4提供对现有Cocoa框架的无缝访问。

  • Swift 4统一了语言的程序和面向对象部分。

  • Swift 4不需要单独的库导入来支持输入/输出或字符串处理等功能。

Swift 4使用与Mac OS和iOS上现有Obj-C系统相同的运行时,这使得Swift 4程序可以在许多现有的iOS 6和OS X 10.8平台上运行。

Swift 4带有游乐场功能,Swift 4程序员可以编写代码并执行它以立即查看结果。

Swift的第一个公开发布于2010年发布Chris Lattner花了将近14年的时间才拿出第一个正式版本,后来得到了许多其他贡献者的支持。 Swift 4已包含在Xcode 6 beta中。

Swift设计师从各种其他流行语言中获取了想法,例如Objective-C,Rust,Haskell,Ruby,Python,C#和CLU。

Swift - Environment

本地环境设置 (Local Environment Setup)

Swift 4为学习目的提供了一个Playground平台,我们将设置相同的平台。 您需要xCode软件才能在Playground中启动Swift 4编码。 一旦熟悉了Swift 4的概念,就可以使用xCode IDE进行iSO/OS x应用程序开发。

首先,我们认为您已在Apple Developer网站上拥有一个帐户。 登录后,请转到以下链接 - Apple Developers下载

这将列出一些可用的软件如下 -

软件列表

现在选择xCode并通过单击光盘映像附近的给定链接下载它。 下载dmg文件后,只需双击它并按照给定的说明进行安装即可。 最后,按照给定的说明将xCode图标拖放到Application文件夹中。

Xcode中

现在您已在计算机上安装了xCode。 接下来,从Application文件夹中打开Xcode,并在接受条款和条件后继续。 如果一切正常,您将看到以下屏幕 -

打开Xcode

选择Get started with a playground选项并输入游乐场的名称,然后选择iOS作为平台。 最后,您将获得Playground窗口,如下所示 -

游乐场的窗户

以下是从默认的Swift 4 Playground Window获取的代码。

import UIKit
var str = "Hello, playground"

如果你为OS X程序创建相同的程序,那么它将包含import Cocoa,程序将如下所示 -

import Cocoa
var str = "Hello, playground"

加载上述程序时,它应在Playground结果区域(右侧)显示以下结果。

Hello, playground

恭喜,您已准备好Swift 4编程环境,您可以继续学习“IOWIKI”。

Swift - Basic Syntax

我们在设置环境时已经看过一段Swift 4程序。 让我们再次开始使用以下Hello, World! 为OS X playground创建的程序,包括import Cocoa ,如下所示 -

/* My first program in Swift 4 */
var myString = "Hello, World!"
print(myString)

如果你为iOS游乐场创建相同的程序,那么它将包含import UIKit ,程序将如下所示 -

import UIKit
var myString = "Hello, World!"
print(myString)

当我们使用适当的游乐场运行上述程序时,我们将得到以下结果 -

Hello, World!

现在让我们看一下Swift 4程序的基本结构,这样您就可以轻松理解Swift 4编程语言的基本构建块。

在Swift 4中导入

您可以使用import语句将任何Objective-C框架(或C库)直接导入到Swift 4程序中。 例如,上面的import cocoa语句使得构成所有OS X的开发层的所有Cocoa库,API和运行时都可以在Swift 4中使用。

Cocoa是在Objective-C中实现的,它是C的超集,因此很容易将C甚至C ++混合到Swift 4应用程序中。

Swift 4中的标记

Swift 4程序由各种令牌组成,令牌可以是关键字,标识符,常量,字符串文字或符号。 例如,以下Swift 4语句由三个标记组成 -

print("test!")
The individual tokens are:
print("test!")

注释 (Comments)

评论就像在Swift 4程序中帮助文本一样。 它们被编译器忽略。 多行注释以/ *开头,并以字符* /结尾,如下所示 -

/* My first program in Swift 4 */

多行注释可以嵌套在Swift 4中。以下是Swift 4中的有效注释 -

/* My first program in Swift 4 is Hello, World!
/* Where as second program is Hello, Swift 4! */ */

在注释的开头使用//编写单行注释。

// My first program in Swift 4

分号(Semicolons)

Swift 4不要求你在代码中的每个语句后键入分号(;),尽管它是可选的; 如果你使用分号,那么编译器不会抱怨它。

但是,如果在同一行中使用多个语句,则需要使用分号作为分隔符,否则编译器将引发语法错误。 你可以写上面的Hello,World! 计划如下 -

/* My first program in Swift 4 */
var myString = "Hello, World!"; print(myString)

标识符 (Identifiers)

Swift 4标识符是用于标识变量,函数或任何其他用户定义项的名称。 标识符以字母A到Z或a到z或下划线_开头,后跟零个或多个字母,下划线和数字(0到9)。

Swift 4不允许在标识符中包含特殊字符,如@,$和%。 Swift 4是一种case sensitive编程语言。 因此,人力和人力是Swift 4中的两个不同标识符。以下是可接受标识符的一些示例 -

Azad        zara   abc   move_name   a_123
myname50    _temp  j     a23b9       retVal

要使用保留字作为标识符,您需要在它之前和之后放置一个反引号(`)。 例如, class不是有效的标识符,但`class`是有效的。

关键字 (Keywords)

Swift 4中保留了以下关键字。这些保留字不能用作常量或变量或任何其他标识符名称,除非它们用反引号转义 -

声明中使用的关键字

ClassdeinitEnumextension
FuncimportInitinternal
Letoperatorprivateprotocol
publicstaticstructsubscript
typealiasvar

报表中使用的关键字

breakcasecontinuedefault
doelsefallthroughfor
ifinreturnswitch
wherewhile

表达式和类型中使用的关键字

asdynamicTypefalseis
nilselfSelfsuper
true_COLUMN__FILE__FUNCTION_
_LINE_

在特定情境中使用的关键字

associativityconveniencedynamicdidSet
finalgetinfixinout
lazyleftmutatingnone
nonmutatingoptionaloverridepostfix
precedenceprefixProtocolrequired
rightsetTypeunowned
weakwillSet

Whitespaces

只包含空格(可能带有注释)的行称为空行,Swift 4编译器完全忽略它。

Whitespace是Swift 4中用来描述空格,制表符,换行符和注释的术语。 空格将语句的一部分与另一部分分开,并使编译器能够识别语句中的一个元素(如int)的结束位置以及下一个元素的开始位置。 因此,在以下声明中 -

var age

varage之间必须至少有一个空格字符(通常是空格),以便编译器能够区分它们。 另一方面,在以下声明中 -

int fruit = apples + oranges   //get the total fruits

水果和=之间,或者=和苹果之间不需要空格字符,尽管您可以自由地包含一些以提高可读性。

运算符两侧的空间应相等,例如。

int fruit = apples +oranges    //is a wrong statement
int fruit = apples + oranges   //is a Correct statement

Literals

文字是整数,浮点数或字符串类型的值的源代码表示。 以下是文字的例子 -

92               // Integer literal
4.24159          // Floating-point literal
"Hello, World!"  // String literal

在Swift中打印

要在swift中打印任何内容,我们都有'print'关键字。

打印有三种不同的属性。

Items - 要打印的项目

Separator - 项目之间的Separator

Terminator - 行应该结束的值,让我们看一个例子和语法。

print("Items to print", separator: "Value " , terminator: "Value")
// E.g. of print statement.
print("Value one")
// prints "Value one \n" Adds, \n as terminator and " " as separator by
default.
print("Value one","Value two", separator: " Next Value" , terminator: " End")
//prints "Value one Next Value Value two End"

在上面的代码中,第一个print语句默认添加\ n,newline Feed作为终结符,而在第二个print语句中我们给出了“End”作为终结符,因此它将打印“End”而不是\ n。

我们可以根据我们的要求提供我们的定制分离器和终结器。

Swift - Data Types

在使用任何编程语言进行编程时,您需要使用不同类型的变量来存储信息。 变量只是用于存储值的保留内存位置。 这意味着在创建变量时,会在内存中保留一些空间。

您可能希望存储各种数据类型的信息,如字符串,字符,宽字符,整数,浮点,布尔值等。根据变量的数据类型,操作系统分配内存并决定可以在保留中存储的内容记忆。

(类型)

Swift 4为程序员提供了丰富的内置和用户定义的数据类型。 在声明变量时,最常见的是以下类型的基本数据类型 -

  • Int or UInt - 用于整数。 更具体地说,您可以使用Int32,Int64来定义32位或64位有符号整数,而使用UInt32或UInt64来定义32位或64位无符号整数变量。 例如,42和-23。

  • Float - 用于表示32位浮点数和小数点较小的数字。 例如,3.14159,0.1和-273.158。

  • Double - 用于表示64位浮点数,并在浮点值必须非常大时使用。 例如,3.14159,0.1和-273.158。

  • Bool - 这表示布尔值,该值为true或false。

  • String - 这是一个有序的字符集合。 例如,“Hello,World!”

  • Character - 这是一个单字符字符串文字。 例如,“C”

  • Optional - 这表示可以包含值或不包含值的变量。

  • Tuples - 用于在单个复合值中对多个值进行分组。

我们在此列出了与Integer类型相关的几个要点 -

  • 在32位平台上,Int与Int32的大小相同。

  • 在64位平台上,Int与Int64的大小相同。

  • 在32位平台上,UInt与UInt32的大小相同。

  • 在64位平台上,UInt与UInt64的大小相同。

  • Int8,Int16,Int32,Int64可用于表示8位,16位,32位和64位有符号整数形式。

  • UInt8,UInt16,UInt32和UInt64可用于表示无符号整数的8位,16位,32位和64位形式。

约束值

下表显示了变量类型,将值存储在内存中所需的内存量,以及可以存储在此类变量中的最大值和最小值。

类型 典型的位宽 典型范围
Int81byte-127 to 127
UInt81byte 0到255
Int324bytes-2147483648 to 2147483647
UInt324bytes0 to 4294967295
Int648bytes-9223372036854775808 to 9223372036854775807
UInt648bytes0 to 18446744073709551615
Float4bytes 1.2E-38至3.4E + 38(~6位)
Double8bytes 2.3E-308至1.7E + 308(~15位)

键入别名

您可以使用typealias为现有类型创建新名称。 以下是使用typealias定义新类型的简单语法 -

typealias newname = type

例如,以下行指示编译器FeetInt另一个名称 -

typealias Feet = Int

现在,以下声明完全合法,并创建一个名为distance的整数变量 -

typealias Feet = Int
var distance: Feet = 100
print(distance)

当我们使用playground运行上述程序时,我们得到以下结果。

100

类型安全

Swift 4是一种类型安全的语言,这意味着如果你的代码的一部分需要一个String,你就不能错误地将它传递给Int。

由于Swift 4是类型安全的,它在编译代码时执行类型检查,并将任何不匹配的类型标记为错误。

var varA = 42
varA = "This is hello"
print(varA)

当我们编译上面的程序时,它会产生以下编译时错误。

main.swift:2:8: error: cannot assign value of type 'String' to type 'Int'
varA = "This is hello"

类型推断

类型推断使编译器能够在编译代码时自动推断出特定表达式的类型,只需检查您提供的值即可。 Swift 4使用类型推断来计算出适当的类型,如下所示。

// varA is inferred to be of type Int
var varA = 42
print(varA)
// varB is inferred to be of type Double
var varB = 3.14159
print(varB)
// varC is also inferred to be of type Double
var varC = 3 + 0.14159
print(varC)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

42
3.14159
3.14159

Swift - Variables

变量为我们提供了程序可以操作的命名存储。 Swift 4中的每个变量都有一个特定的类型,它决定了变量内存的大小和布局; 可存储在该内存中的值范围; 以及可以应用于变量的操作集。

Swift 4支持以下基本类型的变量 -

  • Int or UInt - 用于整数。 更具体地说,您可以使用Int32,Int64来定义32位或64位有符号整数,而使用UInt32或UInt64来定义32位或64位无符号整数变量。 例如,42和-23。

  • Float - 用于表示32位浮点数。 它用于保存小数点较小的数字。 例如,3.14159,0.1和-273.158。

  • Double - 用于表示64位浮点数,并在浮点值必须非常大时使用。 例如3.14159,0.1和-273.158。

  • Bool - 这表示布尔值,该值为true或false。

  • String - 这是一个有序的字符集合。 例如,“Hello,World!”

  • Character - 这是一个单字符字符串文字。 例如,“C”

Swift 4还允许定义各种其他类型的变量,我们将在后续章节中介绍这些变量,例如Optional, Array, Dictionaries, Structures,Classes

以下部分将介绍如何在Swift 4编程中声明和使用各种类型的变量。

变量声明 (Variable Declaration)

变量声明告诉编译器为变量创建存储的位置和数量。 在使用变量之前,必须使用var关键字声明它们,如下所示 -

var variableName = <initial value>

以下示例显示如何在Swift 4中声明变量 -

var varA = 42
print(varA)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

42

输入注释

您可以在声明变量时提供type annotation ,以明确变量可以存储的值的类型。 这是语法 -

var variableName:<data type> = <optional initial value>

以下示例说明如何使用Annotation在Swift 4中声明变量。 这里需要注意的是,如果我们不使用类型注释,那么必须为变量提供初始值,否则我们可以使用类型注释声明我们的变量。

var varA = 42
print(varA)
var varB:Float
varB = 3.14159
print(varB)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

42
3.1415901184082

命名变量 (Naming Variables)

变量的名称可以由字母,数字和下划线字符组成。 它必须以字母或下划线开头。 大写和小写字母是不同的,因为Swift 4是区分大小写的编程语言。

您可以使用简单或Unicode字符来命名变量。 以下示例显示了如何命名变量 -

var _var = "Hello, Swift 4!"
print(_var)
var 你好 = "Hello,World!"
print(你好)

当我们使用playground运行上述程序时,我们得到以下结果。

Hello, Swift 4!
Hello,World!

打印变量

您可以使用打印功能打印常量或变量的当前值。 您可以通过在括号中包装名称来插入变量值,并在左括号前用反斜杠转义它:以下是有效的示例 -

var varA = "Godzilla"
var varB = 1000.00
print("Value of \(varA) is more than \(varB) millions")

当我们使用playground运行上述程序时,我们得到以下结果。

Value of Godzilla is more than 1000.0 millions

Swift - Optionals

Swift 4还引入了Optionals类型,它处理缺少值。 Optionals说“有一个值,它等于x”或“根本没有值”。

一个Optional本身就是一种类型,实际上是Swift 4的新超级动力枚举之一。 它有两个可能的值, NoneSome(T) ,其中T是Swift 4中可用的正确数据类型的关联值。

这是一个可选的整数声明 -

var perhapsInt: Int?

这是一个可选的String声明 -

var perhapsStr: String?

上面的声明相当于将它显式初始化为nil ,这意味着没有价值 -

var perhapsStr: String? = nil

让我们通过以下示例来了解选项如何在Swift 4中工作 -

var myString:String? = nil
if myString != nil {
   print(myString)
} else {
   print("myString has nil value")
}

当我们使用游乐场运行上述程序时,我们得到以下结果 -

myString has nil value

Optionals类似于在Objective-C中使用nil和指针,但它们适用于任何类型,而不仅仅是类。

强制打开

如果您将变量定义为optional ,那么要从此变量中获取值,您必须将其unwrap 。 这只是意味着在变量的末尾添加一个感叹号。

我们举一个简单的例子 -

var myString:String?
myString = "Hello, Swift 4!"
if myString != nil {
   print(myString)
} else {
   print("myString has nil value")
}

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Optional("Hello, Swift 4!")

现在让我们应用展开来获取变量的正确值 -

var myString:String?
myString = "Hello, Swift 4!"
if myString != nil {
   print( myString! )
} else {
   print("myString has nil value")
}

当我们使用playground运行上述程序时,我们得到以下结果。

Hello, Swift 4!

自动解包

您可以使用感叹号而不是问号声明可选变量。 此类可选变量将自动解包,您无需在变量末尾使用任何其他感叹号来获取指定的值。 我们举一个简单的例子 -

var myString:String!
myString = "Hello, Swift 4!"
if myString != nil {
   print(myString)
} else {
   print("myString has nil value")
}

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Hello, Swift 4!

可选绑定

使用可选绑定来确定可选项是否包含值,如果是,则使该值可用作临时常量或变量。

if语句的可选绑定如下 -

if let constantName = someOptional {
   statements
}

让我们举一个简单的例子来理解可选绑定的用法 -

var myString:String?
myString = "Hello, Swift 4!"
if let yourString = myString {
   print("Your string has - \(yourString)")
} else {
   print("Your string does not have a value")
}

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Your string has - Hello, Swift 4!

Swift - Tuples

Swift 4还引入了Tuples类型,用于在单个复合值中对多个值进行分组。

元组中的值可以是任何类型,并且不需要是相同类型。

例如,(“IOWIKI”,123)是一个具有两个值的元组,一个是字符串Type,另一个是整数类型。 这是一个合法的命令。

当没有实现服务器上的某些东西时,让ImplementationError =(501,“Not implemented”)是一个错误,它返回两个值。 错误代码和说明。

您可以根据需要从任意数量的不同数据类型创建元组。

这是元组声明的语法 -

var TupleName = (Value1, value2,… any number of values)

这是一个元组声明 -

var error501 = (501, “Not implemented”)

您可以使用从0开始的索引号访问元组的值。

以下是访问元组值的示例 -

print(“The code is\(error501.0)”)
print(“The definition of error is\(error501.1)”)

您可以在声明时命名元组的变量,也可以使用它们的名称来调用它们

var error501 = (errorCode: 501, description: “Not Implemented”)
print(error501.errorCode)   // prints 501.

元组有助于从函数返回多个值。 例如,Web应用程序可能会返回类型(“String”,Int)的元组,以显示加载是成功还是失败。

通过在元组中返回不同的值,我们可以根据不同的元组类型做出决策。

Note - 元组对临时值很有用,不适用于复杂数据。

Swift - Constants

常量是指程序在执行期间不会改变的固定值。 常量可以是任何基本数据类型,如integer constant, a floating constant, a character constant, or a string literal 。 还有enumeration constants

Constants被视为与常规变量一样,除了它们的值在定义后无法修改的事实。

常数宣言

在使用常量之前,必须使用let关键字声明它们,如下所示 -

let constantName = <initial value>

下面是一个简单的例子,展示如何在Swift 4中声明一个常量 -

let constA = 42
print(constA)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

42

输入注释

您可以在声明常量时提供type annotation ,以明确常量可以存储的值的类型。 以下是语法 -

var constantName:<data type> = <optional initial value>

以下示例显示如何使用Annotation在Swift 4中声明常量。 这里需要注意的是,在创建常量时必须提供初始值 -

let constA = 42
print(constA)
let constB:Float = 3.14159
print(constB)

当我们使用playground运行上述程序时,我们得到以下结果。

42
3.1415901184082

命名常量

常量的名称可以由字母,数字和下划线字符组成。 它必须以字母或下划线开头。 大写和小写字母是不同的,因为Swift 4是区分大小写的编程语言。

您可以使用简单或Unicode字符来命名变量。 以下是有效的例子 -

let _const = "Hello, Swift 4!"
print(_const)
let 你好 = "Hello,World!"
print(你好)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Hello, Swift 4!
Hello,World!

印刷常数

您可以使用print功能print常量或变量的当前值。 您可以通过在括号中包装名称来插入变量值,并在左括号前用反斜杠转义它:以下是有效的示例 -

let constA = "Godzilla"
let constB = 1000.00
print("Value of \(constA) is more than \(constB) millions")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Value of Godzilla is more than 1000.0 millions

Swift - Literals

文字是整数,浮点数或字符串类型的值的源代码表示。 以下是文字的例子 -

42                // Integer literal
3.14159           // Floating-point literal
"Hello, world!"   // String literal

整型常量 (Integer Literals)

整数文字可以是十进制,二进制,八进制或十六进制常量。 二进制文字以0b开头,八进制文字以0o开头,十六进制文字以0x开头,十进制没有。

以下是整数文字的一些示例 -

let decimalInteger = 17         // 17 in decimal notation
let binaryInteger = 0b10001     // 17 in binary notation
let octalInteger = 0o21         // 17 in octal notation
let hexadecimalInteger = 0x11   // 17 in hexadecimal notation

浮点型常量 (Floating-point Literals)

浮点文字有一个整数部分,一个小数点,一个小数部分和一个指数部分。 您可以以十进制形式或十六进制形式表示浮点文字。

十进制浮点文字由一系列十进制数字组成,后跟小数部分,十进制指数或两者。

十六进制浮点文字由0x前缀组成,后跟可选的十六进制小数,后跟十六进制指数。

以下是浮点文字的一些示例 -

let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0

字符串常量 (String Literals)

字符串文字是由双引号括起来的字符序列,其形式如下 -

"characters"

字符串文字不能包含未转义的双引号(“),未转义的反斜杠(\),回车符或换行符。使用以下转义序列可以在字符串文字中包含特殊字符 -

逃脱序列 含义
\0 Null Character
\\\character
\bBackspace
\fForm feed
\nNewline
\rCarriage return
\t 水平标签
\v 垂直标签
\' 单引号
\" 双引号
\000 八进制数字为一到三位数
\xhh... 十六进制数字的一个或多个数字

以下示例显示如何使用一些字符串文字 -

let stringL = "Hello\tWorld\n\nHello\'Swift 4\'"
print(stringL)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Hello World
Hello'Swift 4'

布尔文字

有三个布尔文字,它们是标准Swift 4关键字的一部分 -

  • true表示true。

  • false表示false。

  • 值为nil表示无值。

Swift - Operators

运算符是一个符号,告诉编译器执行特定的数学或逻辑操作。 Objective-C内置运算符丰富,提供以下类型的运算符 -

  • 算术运算符
  • 比较运算符
  • 逻辑运算符
  • 按位运算符
  • 分配运算符
  • 范围运算符
  • 其它运算符

本教程将逐一解释算术,关系,逻辑,按位,赋值和其他运算符。

算术运算符 (Arithmetic Operators)

下表显示了Swift 4语言支持的所有算术运算符。 假设变量A保持10,变量B保持20,则 -

操作者 描述
+ 添加两个操作数 A + B将给出30
从第一个减去第二个操作数 A - B将给-10
* 将两个操作数相乘 A * B将给出200
/Divides numerator by denominator B/A会给2
% 模数运算符和整数/浮点除法后的余数 B%A将给出0

比较运算符 (Comparison Operators)

下表显示了Swift 4语言支持的所有关系运算符。 假设变量A保持10,变量B保持20,则 -

操作者 描述
== 检查两个操作数的值是否相等; 如果是,则条件成立。 (A == B)不是真的。
!= 检查两个操作数的值是否相等; 如果值不相等,则条件成立。 (A!= B)是真的。
> 检查左操作数的值是否大于右操作数的值; 如果是,则条件成立。 (A> B)不是真的。
< 检查左操作数的值是否小于右操作数的值; 如果是,则条件成立。 (A < B) 为真
>= 检查左操作数的值是否大于或等于右操作数的值; 如果是,则条件成立。 (A> = B)不是真的。
<= 检查左操作数的值是否小于或等于右操作数的值; 如果是,则条件成立。 (A <= B)是真的。

逻辑运算符 (Logical Operators)

下表显示了Swift 4语言支持的所有逻辑运算符。 假设变量A保持1而变量B保持0,则 -

操作者 描述
&& 称为逻辑AND运算符。 如果两个操作数都不为零,则条件成立。 (A && B)是假的。
|| 称为逻辑OR运算符。 如果两个操作数中的任何一个非零,则条件变为真。 (A || B)是真的。
! 称为逻辑非运算符。 用于反转其操作数的逻辑状态。 如果条件为真,则Logical NOT运算符将使其为false。 !(A && B)是真的。

按位运算符 (Bitwise Operators)

按位运算符处理位并执行逐位操作。 &,|和^的真值表如下 -

p q p&Q p | Q p ^ Q
00000
01011
11110
10011
Assume A = 60; and B = 13;
In binary format, they will be as follows:
A = 0011 1100
B = 0000 1101
-----------------
A & B = 0000 1100
A|B = 0011 1101
A^B = 0011 0001
~A = 1100 0011

下表列出了Swift 4语言支持的按位运算符。 假设变量A保持60,变量B保持13,则7-

操作者 描述
& 二进制AND运算符将一个位复制到结果中(如果它存在于两个操作数中)。 (A&B)将给出12,即0000 1100
| 二进制OR运算符复制一个位,如果它存在于任一操作数中。 (A | B)将给出61,即0011 1101
^ 二进制异或运算符复制该位,如果它在一个操作数中设置但不是两者都设置。 (A ^ B)将给出49,即0011 0001
~ 二元一元补语运算符是一元的,具有“翻转”位的效果。 (~A)将给出-61,即2的补码形式的1100 0011。
<< 二进制左移运算符。 左操作数值向左移动右操作数指定的位数。 (A << 2将给出240,即1111 0000
>> 二进制右移运算符。 左操作数值向右移动右操作数指定的位数。 A >> 2将给出15,即0000 1111

赋值操作符 (Assignment Operators)

SSwift 4支持以下赋值运算符 -

操作者 描述
= 简单赋值运算符,将右侧操作数的值分配给左侧操作数 C = A + B将A + B的值分配给C
+= 添加AND赋值运算符,它将右操作数添加到左操作数并将结果赋给左操作数 C + = A等于C = C + A.
-= 减去AND赋值运算符,它从左操作数中减去右操作数,并将结果赋给左操作数 C - = A相当于C = C - A.
*= 乘以AND赋值运算符,它将右操作数与左操作数相乘,并将结果赋给左操作数 C * = A等于C = C * A.
/= 除以AND赋值运算符,它将左操作数除以右操作数,并将结果赋给左操作数 C/= A相当于C = C/A.
%= 模数AND赋值运算符,它使用两个操作数获取模数,并将结果赋给左操作数 C%= A等于C = C%A
<<= 左移AND赋值运算符 C << = 2与C = C << 2相同
>>= 右移AND赋值运算符 C >> = 2与C = C >> 2相同
&= 按位AND赋值运算符 C&= 2与C = C&2相同
^= 按位异或和赋值运算符 C ^ = 2与C = C ^ 2相同
|= 按位包含OR和赋值运算符 C | = 2与C = C |相同 2

范围运算符

Swift 4包括两个范围运算符,它们是表示一系列值的快捷方式。 下表解释了这两个运算符。

操作者 描述
封闭范围 (a ... b)定义从a到b的范围,并包括值a和b。 1 ... 5给出1,2,3,4和5
Half-Open Range (a .. 1 .. <5给出1,2,3和4
单侧范围

a ...,定义从元素到结尾的范围

... a,定义从start到a的范围

1 ...给出1,2,3 ......元素的结尾

...... 2开始......到1,2

其它运算符

Swift 4支持其他一些重要的运算符,包括range和? :如下表所示。

操作者 描述
Unary Minus(一元减号) 可以使用前缀来切换数值的符号 - -3 or -4
Unary Plus (一元加号) 返回它操作的值,不做任何更改。 +6 gives 6
Ternary Conditional 条件? X:Y 如果条件为真? 然后是值X:否则为Y值

运算符优先

运算符优先级确定表达式中的术语分组。 这会影响表达式的计算方式。 某些运算符的优先级高于其他运算符; 例如,乘法运算符的优先级高于加法运算符。

例如,x = 7 + 3 * 2; 这里,x被赋值为13,而不是20,因为operator *的优先级高于+,所以它首先乘以3 * 2然后加到7中。

此处,具有最高优先级的运算符显示在表的顶部,具有最低优先级的运算符显示在底部。 在表达式中,将首先评估更高优先级的运算符。

操作者 描述
主表达式运算符 ()[]。 expr ++ expr-- left-to-right
一元运算符

*&+ - ! 〜++ expr --expr

* /%

+ -

>> <<

<> <=> =

==!=

right-to-left
二元运算符

&

^

|

&&

||

left-to-right
三元运算符 ?:right-to-left
分配运算符 = + = - = * =/=%= >> = << =&= ^ = | = right-to-left
Comma,left-to-right

Swift - Decision Making

决策结构要求程序员指定程序要评估或测试的一个或多个条件,以及在条件被确定为true要执行的语句,以及可选的,如果条件要执行的其他语句被认定是false

以下是大多数编程语言中的典型决策结构的一般性 -

做决定

Swift 4提供以下类型的决策声明。 单击以下链接以检查其详细信息。

Sr.No 声明和说明
1 if 语句

if语句由一个布尔表达式后跟一个或多个语句组成。

2 if...else 语句

if语句后面可以跟一个可选的else语句,该语句在布尔表达式为false时执行。

3 if ... else if ... else Statement

if语句后面可以跟一个else if if语句,这对于使用单个if ... else if语句测试各种条件非常有用。

4 嵌套if语句

您可以在另一个if或else if语句中使用if或else if语句。

5 switch 语句

switch语句允许测试变量与值列表的相等性。

(The ? : Operator)

我们覆盖了conditional operator ? : conditional operator ? :在前一章中可以用来替换if...else语句。 它有以下一般形式 -

Exp1 ? Exp2 : Exp3;

Exp1,Exp2和Exp3是表达式。 注意结肠的使用和放置。

一个值? 表达式的确定方式如下:评估Exp1。 如果是,那么Exp2会被评估并成为整个值吗? 表达。 如果Exp1为false,则计算Exp3,其值将成为表达式的值。

Swift - Loops

可能存在需要多次执行代码块的情况。 通常,语句按顺序执行:首先执行函数中的第一个语句,然后执行第二个语句,依此类推。

编程语言提供各种控制结构,允许更复杂的执行路径。

循环语句允许我们多次执行语句或语句组。 以下是大多数编程语言中循环语句的一般说法 -

循环

Swift 4编程语言提供以下类型的循环来处理循环要求。 单击以下链接以检查其详细信息。

Sr.No 循环类型和描述
1 for-in

此循环为范围,序列,集合或进展中的每个项执行一组语句。

2 while 循环

在给定条件为真时重复语句或语句组。 它在执行循环体之前测试条件。

3 重复... while循环

像while语句一样,除了它测试循环体末尾的条件。

循环控制语句 (Loop Control Statements)

循环控制语句将执行从其正常序列更改。 当执行离开作用域时,将销毁在该作用域中创建的所有自动对象。

Swift 4支持以下控制语句。 单击以下链接以检查其详细信息。

Sr.No 控制声明和描述
1 continue statement

该语句告诉循环停止它正在做什么,并在循环的下一次迭代开始时再次启动。

2 break statement

终止循环语句并将执行转移到循环后的语句。

3 fallthrough statement

fallthrough语句模拟了Swift 4切换到C风格切换的行为。

Swift - Strings

Swift 4中的字符串是一个有序的字符集合,例如“Hello,World!”。 它们由Swift 4数据类型String表示,后者又表示Character类型值的集合。

创建一个字符串

您可以使用字符串文字或创建String类的实例来创建String,如下所示 -

// String creation using String literal
var stringA = "Hello, Swift 4!"
print( stringA )
// String creation using String instance
var stringB = String("Hello, Swift 4!")
print( stringB )
//Multiple line string
let stringC = """
Hey this is a
example of multiple Line
string by iowiki 
"""
print(stringC)

编译并执行上述代码时,会产生以下结果

Hello, Swift 4!
Hello, Swift 4!
Hey this is a
example of multiple Line
string by iowiki

空字符串

您可以通过使用空字符串文字或创建String类的实例来创建空String,如下所示。 您还可以使用布尔属性isEmpty检查字符串是否为空。

// Empty string creation using String literal
var stringA = ""
if stringA.isEmpty {
   print( "stringA is empty" )
} else {
   print( "stringA is not empty" )
}
// Empty string creation using String instance
let stringB = String()
if stringB.isEmpty {
   print( "stringB is empty" )
} else {
   print( "stringB is not empty" )
}

编译并执行上述代码时,会产生以下结果 -

stringA is empty
stringB is empty

字符串常量

您可以通过将String分配给变量来指定是否可以修改(或变异)String,或者通过使用let关键字将其分配给常量来保持它是常量 - 如下所示 -

// stringA can be modified
var stringA = "Hello, Swift 4!"
stringA + = "--Readers--"
print( stringA )
// stringB can not be modified
let stringB = String("Hello, Swift 4!")
stringB + = "--Readers--"
print( stringB )

编译并执行上述代码时,会产生以下结果 -

Playground execution failed: error: <EXPR>:10:1: error: 'String' is not
convertible to '@lvalue UInt8'
stringB + = "--Readers--"

字符串插值

字符串插值是一种通过在字符串文字中包含它们的值,从常量,变量,文字和表达式的混合构造新的String值的方法。

插入到字符串文字中的每个项目(变量或常量)都包含在一对括号中,前缀为反斜杠。 这是一个简单的例子 -

var varA = 20
let constA = 100
var varC:Float = 20.0
var stringA = "\(varA) times \(constA) is equal to \(varC * 100)"
print( stringA )

编译并执行上述代码时,会产生以下结果 -

20 times 100 is equal to 2000.0

字符串连接 (String Concatenation)

您可以使用+运算符来连接两个字符串或字符串和一个字符,或两个字符。 这是一个简单的例子 -

let constA = "Hello,"
let constB = "World!"
var stringA = constA + constB
print( stringA )

编译并执行上述代码时,会产生以下结果 -

Hello,World!

String Length

Swift 4字符串没有length属性,但您可以使用global count()函数来计算字符串中的字符数。 这是一个简单的例子 -

var varA = "Hello, Swift 4!"
print( "\(varA), length is \((varA.count))" )

编译并执行上述代码时,会产生以下结果 -

Hello, Swift 4!, length is 15

字符串比较

您可以使用==运算符来比较两个字符串变量或常量。 这是一个简单的例子 -

var varA = "Hello, Swift 4!"
var varB = "Hello, World!"
if varA == varB {
   print( "\(varA) and \(varB) are equal" )
} else {
   print( "\(varA) and \(varB) are not equal" )
}

编译并执行上述代码时,会产生以下结果 -

Hello, Swift 4! and Hello, World! are not equal

字符串迭代

字符串又是swift 4中的值集合,因此我们可以使用循环遍历字符串。 -

for chars in "ThisString" {
   print(chars, terminator: " ")
}

编译并执行上述代码时,会产生以下结果 -

T h i s S t r i n g

Unicode字符串

您可以通过迭代其utf8和utf16属性来访问String的UTF-8和UTF-16表示,如以下示例所示 -

var unicodeString = "Dog???"
print("UTF-8 Codes: ")
for code in unicodeString.utf8 {
   print("\(code) ")
}
print("\n")
print("UTF-16 Codes: ")
for code in unicodeString.utf16 {
   print("\(code) ")
}

编译并执行上述代码时,会产生以下结果 -

UTF-8 Codes: 
68 
111 
103 
63 
63 
63 
UTF-16 Codes: 
68 
111 
103 
63 
63 
63 

字符串函数和运算符

Swift 4支持与字符串相关的各种方法和运算符 -

Sr.No 功能/运算符和目的
1

isEmpty

一个布尔值,用于确定字符串是否为空。

2

hasPrefix(prefix: String)

用于检查给定参数字符串是否作为字符串前缀存在的函数。

3

hasSuffix(suffix: String)

用于检查给定参数字符串是否作为字符串后缀存在的函数。

4

toInt()

将数字String值转换为Integer的函数。

5

count()

用于计算字符串中字符数的全局函数。

6

utf8

返回字符串的UTF-8表示的属性。

7

utf16

用于返回字符串的UTF-16表示的属性。

8

unicodeScalars

返回字符串的Unicode标量表示的属性。

9

+

运算符连接两个字符串,或字符串和字符,或两个字符。

10

+=

运算符将字符串或字符附加到现有字符串。

11

==

运算符确定两个字符串的相等性。

12

<

运算符执行词典比较以确定一个字符串的评估是否小于另一个字符串。

13

startIndex

获取字符串起始索引的值。

14

endIndex

获取字符串结束索引的值。

15

Indices

逐个访问权限。 即字符串的所有字符一个接一个。

16

insert("Value", at: position)

在某个位置插入值。

17

remove(at: position)

removeSubrange(range)

删除某个位置的值,或从字符串中删除一系列值。

18

reversed()

返回字符串的反转

Swift - Characters

Swift中的字符是单字符字符串文字,由数据类型Character寻址。 看一下下面的例子。 它使用两个字符常量 -

let char1: Character = "A"
let char2: Character = "B"
print("Value of char1 \(char1)")
print("Value of char2 \(char2)")

编译并执行上述代码时,会产生以下结果 -

Value of char1 A
Value of char2 B

如果您尝试在Character类型变量或常量中存储多个字符,则Swift 4将不允许这样做。 尝试在Swift 4 Playground中键入以下示例,即使在编译之前也会出现错误。

// Following is wrong in Swift 4
let char: Character = "AB"
print("Value of char \(char)")

空字符变量

无法创建一个空的Character变量或常量,它将具有空值。 以下语法不可能 -

// Following is wrong in Swift 4
let char1: Character = ""
var char2: Character = ""
print("Value of char1 \(char1)")
print("Value of char2 \(char2)")

从字符串访问字符

正如在讨论Swift 4的字符串时所解释的那样,String表示指定顺序的Character值集合。 因此,我们可以通过使用for-in循环遍历该字符串来访问给定String中的单个字符 -

for ch in "Hello" {
   print(ch)
}

编译并执行上述代码时,会产生以下结果 -

H
e
l
l
o

用字符连接字符串

下面的示例演示了如何将Swift 4的Character与Swift 4的String连接起来。

var varA:String = "Hello "
let varB:Character = "G"
varA.append( varB )
print("Value of varC = \(varA)")

编译并执行上述代码时,会产生以下结果 -

Value of varC = Hello G

Swift - Arrays

Swift 4数组用于存储相同类型的有序值列表。 Swift 4进行了严格的检查,即使是错误的,也不允许你在数组中输入错误的类型。

如果将已创建的数组分配给变量,则它总是可变的,这意味着您可以通过添加,删除或更改其项来更改它; 但是如果将数组赋值给常量,那么该数组是不可变的,并且其大小和内容不能更改。

创建数组 (Creating Arrays)

您可以使用以下初始化语法创建某个类型的空数组 -

var someArray = [SomeType]()

以下是创建给定大小a *的数组并使用值初始化它的语法 -

var someArray = [SomeType](count: NumbeOfElements, repeatedValue: InitialValue)

您可以使用以下语句创建一个具有3个元素且初始值为零的Int类型的空数组 -

var someInts = [Int](count: 3, repeatedValue: 0)

下面是另一个示例,用于创建三个元素的数组并为该数组分配三个值 -

var someInts:[Int] = [10, 20, 30]

访问数组

您可以使用subscript标语法从数组中检索值,并在数组名称后面的方括号内传递要检索的值的索引,如下所示 -

var someVar = someArray[index]

这里, index从0开始,这意味着可以使用索引作为0访问第一个元素,可以使用索引作为1访问第二个元素,依此类推。 以下示例显示如何创建,初始化和访问数组 -

var someInts = [Int](count: 3, repeatedValue: 10)
var someVar = someInts[0]
print( "Value of first element is \(someVar)" )
print( "Value of second element is \(someInts[1])" )
print( "Value of third element is \(someInts[2])" )

编译并执行上述代码时,会产生以下结果 -

Value of first element is 10
Value of second element is 10
Value of third element is 10

修改数组

您可以使用append()方法或附加赋值运算符(+ =)在数组末尾添加新项。 看一下下面的例子。 在这里,我们首先创建一个空数组,然后将新元素添加到同一个数组中 -

var someInts = [Int]()
someInts.append(20)
someInts.append(30)
someInts += [40]
var someVar = someInts[0]
print( "Value of first element is \(someVar)" )
print( "Value of second element is \(someInts[1])" )
print( "Value of third element is \(someInts[2])" )

编译并执行上述代码时,会产生以下结果 -

Value of first element is 20
Value of second element is 30
Value of third element is 40

您可以通过在给定索引处分配新值来修改Array的现有元素,如以下示例所示 -

var someInts = [Int]()
someInts.append(20)
someInts.append(30)
someInts += [40]
// Modify last element
someInts[2] = 50
var someVar = someInts[0]
print( "Value of first element is \(someVar)" )
print( "Value of second element is \(someInts[1])" )
print( "Value of third element is \(someInts[2])" )

编译并执行上述代码时,会产生以下结果 -

Value of first element is 20
Value of second element is 30
Value of third element is 50

迭代数组

您可以使用for-in循环迭代数组中的整个值集,如以下示例所示 -

var someStrs = [String]()
someStrs.append("Apple")
someStrs.append("Amazon")
someStrs += ["Google"]
for item in someStrs {
   print(item)
}

编译并执行上述代码时,会产生以下结果 -

Apple
Amazon
Google

您可以使用enumerate()函数返回项目的索引及其值,如下例所示 -

var someStrs = [String]()
someStrs.append("Apple")
someStrs.append("Amazon")
someStrs += ["Google"]
for (index, item) in someStrs.enumerated() {
   print("Value at index = \(index) is \(item)")
}

编译并执行上述代码时,会产生以下结果 -

Value at index = 0 is Apple
Value at index = 1 is Amazon
Value at index = 2 is Google

添加两个数组

您可以使用加法运算符(+)添加两个相同类型的数组,这将产生一个新数组,其中包含来自两个数组的值的组合,如下所示 -

var intsA = [Int](count:2, repeatedValue: 2)
var intsB = [Int](count:3, repeatedValue: 1)
var intsC = intsA + intsB
for item in intsC {
   print(item)
}

编译并执行上述代码时,会产生以下结果 -

2
2
1
1
1

计数属性

您可以使用数组的只读count属性来查找下面显示的数组中的项目数 -

var intsA = [Int](count:2, repeatedValue: 2)
var intsB = [Int](count:3, repeatedValue: 1)
var intsC = intsA + intsB
print("Total items in intsA = \(intsA.count)")
print("Total items in intsB = \(intsB.count)")
print("Total items in intsC = \(intsC.count)")

编译并执行上述代码时,会产生以下结果 -

Total items in intsA = 2
Total items in intsB = 3
Total items in intsC = 5

空财产

您可以使用数组的只读empty属性来查明数组是否为空,如下所示 -

var intsA = [Int](count:2, repeatedValue: 2)
var intsB = [Int](count:3, repeatedValue: 1)
var intsC = [Int]()
print("intsA.isEmpty = \(intsA.isEmpty)")
print("intsB.isEmpty = \(intsB.isEmpty)")
print("intsC.isEmpty = \(intsC.isEmpty)")

编译并执行上述代码时,会产生以下结果 -

intsA.isEmpty = false
intsB.isEmpty = false
intsC.isEmpty = true

Swift - Sets

Swift 4 sets用于存储相同类型的不同值,但它们没有像数组那样的明确排序。

如果元素的排序不是问题,或者如果要确保没有重复值,则可以使用集而不是数组。 (集只允许不同的值。)

类型必须是可以清除的,才能存储在一个集合中。 哈希值是对于相等对象相等的Int值。 例如,如果x == y,则x.hashvalue == y.hashvalue

默认情况下,所有基本swift值都是可散列类型,可以用作设置值。

创建集

您可以使用以下初始化语法创建某个类型的空集 -

var someSet = Set<Character>()     //Character can be replaced by data type of set.

访问和修改集

您可以使用其方法和属性访问或修改集合 -

“count”方法可用于显示集合中的元素数量。

someSet.count        // prints the number of elements

“insert”方法可用于在set中插入值。

someSet.insert("c")   // adds the element to Set.

同样,isEmpty可用于检查set是否为空。

someSet.isEmpty       // returns true or false depending on the set Elements.

“remove”方法可用于删除set中的值。

someSet.remove("c")     // removes a element , removeAll() can be used to remove all elements

“contains”方法可用于检查集合中是否存在值。

someSet.contains("c")     // to check if set contains this value.

迭代一个集合

您可以使用for-in循环遍历集合 -

for items in someSet {
   print(someSet)
}
//Swift sets are not in an ordered way, to iterate over a set in ordered way use
for items in someSet.sorted() {
   print(someSet)
}  

执行设置操作

您可以在swift集上执行基本的集合操作。

以下是执行集合操作的方法 -

  • Intersection
  • Union
  • subtracting
let evens: Set = [10,12,14,16,18]
let odds: Set = [5,7,9,11,13]
let primes = [2,3,5,7]
odds.union(evens).sorted()
// [5,7,9,10,11,12,13,14,16,18]
odds.intersection(evens).sorted()
//[]
odds.subtracting(primes).sorted()
//[9, 11, 13]

Swift - Dictionaries

Swift 4 dictionaries用于存储相同类型的无序值列表。 Swift 4进行了严格的检查,即使是错误也不允许你在字典中输入错误的类型。

Swift 4字典使用称为key唯一标识符来存储值,以后可以通过相同的密钥引用和查找该值。 与数组中的项目不同, dictionary项目没有指定的顺序。 当您需要根据标识符查找值时,可以使用dictionary

字典键可以是整数,也可以是没有限制的字符串,但它在字典中应该是唯一的。

如果将创建的字典分配给变量,则它始终是可变的,这意味着您可以通过添加,删除或更改其项来更改它。 但是如果将字典分配给常量,那么该字典是不可变的,并且其大小和内容不能更改。

创建字典

您可以使用以下初始化语法创建特定类型的空字典 -

var someDict = [KeyType: ValueType]()

您可以使用以下简单语法创建一个空字典,其键将是Int类型,关联的值将是字符串 -

var someDict = [Int: String]()

这是一个从一组给定值创建字典的示例 -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]

基于序列的初始化

Swift 4允许您从数组创建Dictionary(键值对)。

var cities = [“Delhi”,”Bangalore”,”Hyderabad”]

您可以使用以下简单语法创建一个空字典,其键将是Int类型,关联的值将是字符串 -

var Distance = [2000,10, 620]

这是一个从一组给定值创建字典的示例 -

let cityDistanceDict = Dictionary(uniqueKeysWithValues: zip(cities, Distance))

上面的代码行将创建一个字典,其中Cities为键,Distance为Value -

Filtering

Swift 4允许您过滤字典中的值。

var closeCities = cityDistanceDict.filter { $0.value < 1000 }

如果我们运行上面的代码,我们的closeCities字典将是。

["Bangalore" : 10 , "Hyderabad" : 620]

字典分组

Swift 4允许您创建Dictionary值的分组。

var cities = ["Delhi","Bangalore","Hyderabad","Dehradun","Bihar"]

您可以使用以下简单语法根据第一个字母对字典值进行分组。

var GroupedCities = Dictionary(grouping: cities ) { $0.first! }

上面代码的结果将是

["D" :["Delhi","Dehradun"], "B" : ["Bengaluru","Bihar"], "H" : ["Hyderabad"]]

访问词典

您可以使用下标语法从字典中检索值,并在字典名称后面的方括号内传递要检索的值的键,如下所示 -

var someVar = someDict[key]

让我们检查以下示例来创建,初始化和访问字典中的值 -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var someVar = someDict[1]
print( "Value of key = 1 is \(someVar)" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )

编译并执行上述代码时,会产生以下结果 -

Value of key = 1 is Optional("One")
Value of key = 2 is Optional("Two")
Value of key = 3 is Optional("Three")

修改词典

您可以使用updateValue(forKey:)方法将现有值添加到字典的给定键。 此方法返回字典值类型的可选值。 这是一个简单的例子 -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var oldVal = someDict.updateValue("New value of one", forKey: 1)
var someVar = someDict[1]
print( "Old value of key = 1 is \(oldVal)" )
print( "Value of key = 1 is \(someVar)" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )

编译并执行上述代码时,会产生以下结果 -

Old value of key = 1 is Optional("One")
Value of key = 1 is Optional("New value of one")
Value of key = 2 is Optional("Two")
Value of key = 3 is Optional("Three")

您可以通过在给定键上分配新值来修改字典的现有元素,如以下示例所示 -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var oldVal = someDict[1]
someDict[1] = "New value of one"
var someVar = someDict[1]
print( "Old value of key = 1 is \(oldVal)" )
print( "Value of key = 1 is \(someVar)" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )

编译并执行上述代码时,会产生以下结果 -

Old value of key = 1 is Optional("One")
Value of key = 1 is Optional("New value of one")
Value of key = 2 is Optional("Two")
Value of key = 3 is Optional("Three")

删除键值对

您可以使用removeValueForKey()方法从字典中删除键值对。 此方法删除键值对(如果存在)并返回已删除的值,如果不存在值则返回nil。 这是一个简单的例子 -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var removedValue = someDict.removeValue(forKey: 2)
print( "Value of key = 1 is \(someDict[1])" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )

编译并执行上述代码时,会产生以下结果 -

Value of key = 1 is Optional("One")
Value of key = 2 is nil
Value of key = 3 is Optional("Three")

您还可以使用下标语法通过为该键指定值nil来从字典中删除键值对。 这是一个简单的例子 -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
someDict[2] = nil
print( "Value of key = 1 is \(someDict[1])" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )

编译并执行上述代码时,会产生以下结果 -

Value of key = 1 is Optional("One")
Value of key = 2 is nil
Value of key = 3 is Optional("Three")

迭代字典

您可以使用for-in循环迭代Dictionary中的整组键值对,如以下示例所示 -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
for (index, keyValue) in someDict.enumerated() {
   print("Dictionary key \(index) - Dictionary value \(keyValue)")
}

编译并执行上述代码时,会产生以下结果 -

Dictionary key 2 - Dictionary value Two
Dictionary key 3 - Dictionary value Three
Dictionary key 1 - Dictionary value One

您可以使用enumerate()函数返回项目的索引及其(键,值)对,如下例所示 -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
for (key, value) in someDict.enumerated() {
   print("Dictionary key \(key) - Dictionary value \(value)")
}

编译并执行上述代码时,会产生以下结果 -

Dictionary key 0 - Dictionary value (key: 2, value: "Two")
Dictionary key 1 - Dictionary value (key: 3, value: "Three")
Dictionary key 2 - Dictionary value (key: 1, value: "One")

转换为数组

您可以从给定字典中提取键值对列表,以便为键和值构建单独的数组。 这是一个例子 -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
let dictKeys = [Int](someDict.keys)
let dictValues = [String](someDict.values)
print("Print Dictionary Keys")
for (key) in dictKeys {
   print("\(key)")
}
print("Print Dictionary Values")
for (value) in dictValues {
   print("\(value)")
}

编译并执行上述代码时,会产生以下结果 -

Print Dictionary Keys
2
3
1
Print Dictionary Values
Two
Three
One

计数属性

您可以使用字典的只读count属性来查找字典中的项目数,如下所示 -

var someDict1:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var someDict2:[Int:String] = [4:"Four", 5:"Five"]
print("Total items in someDict1 = \(someDict1.count)")
print("Total items in someDict2 = \(someDict2.count)")

编译并执行上述代码时,会产生以下结果 -

Total items in someDict1 = 3
Total items in someDict2 = 2

空财产

您可以使用字典的只读empty属性来查明字典是否为空,如下所示 -

var someDict1:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var someDict2:[Int:String] = [4:"Four", 5:"Five"]
var someDict3:[Int:String] = [Int:String]()
print("someDict1 = \(someDict1.isEmpty)")
print("someDict2 = \(someDict2.isEmpty)")
print("someDict3 = \(someDict3.isEmpty)")

编译并执行上述代码时,会产生以下结果 -

someDict1 = false
someDict2 = false
someDict3 = true

Swift - 函数

函数是组合在一起执行特定任务的一组语句。 Swift 4函数可以像简单的C函数一样简单,也可以像Objective C语言函数一样复杂。 它允许我们在函数调用中传递本地和全局参数值。

  • Function Declaration - 告诉编译器函数的名称,返回类型和参数。

  • Function Definition - 它提供Function Definition的实际主体。

Swift 4函数包含参数类型及其返回类型。

函数定义 (Function Definition)

在Swift 4中,函数由“func”关键字定义。 当一个函数被新定义时,它可能需要一个或多个值作为函数的输入'参数',它将处理主体中的函数并将值作为输出'返回类型'传递回函数。

每个函数都有一个函数名称,它描述了函数执行的任务。 要使用函数,可以使用其名称“调用”该函数,并传递与函数参数类型匹配的输入值(称为参数)。 函数参数也称为“元组”。

函数的参数必须始终以与函数参数列表相同的顺序提供,返回值后跟→。

语法 (Syntax)

func funcname(Parameters) -> returntype {
   Statement1
   Statement2
   ---
   Statement N
   return parameters
}

看看下面的代码。 学生的名字被声明为在函数'student'中声明的字符串数据类型,当调用该函数时,它将返回学生的姓名。

func student(name: String) -> String {
   return name
}
print(student(name: "First Program"))
print(student(name: "About Functions"))

当我们使用游乐场运行上述程序时,我们得到以下结果 -

First Program
About Functions

调用一个函数 (Calling a Function)

让我们假设我们定义了一个名为'display'的函数来考虑例如显示数字,一个函数名为'display'的函数首先用参数'no1'初始化,该参数保存整数数据类型。 然后将参数'no1'分配给参数'a',此后将指向相同的数据类型整数。 现在参数'a'返回给函数。 这里display()函数将保存整数值,并在每次调用函数时返回整数值。

func display(no1: Int) -> Int {
   let a = no1
   return a
}
print(display(no1: 100))
print(display(no1: 200))

当我们使用游乐场运行上述程序时,我们得到以下结果 -

100
200

参数和返回值

Swift 4提供灵活的函数参数及其从简单到复杂值的返回值。 与C和Objective C类似,Swift 4中的函数也可以采用多种形式。

带参数的函数

通过将其参数值传递给函数体来访问函数。 我们可以将单个参数值作为元组传递给函数内的元组。

func mult(no1: Int, no2: Int) -> Int {
   return no1*no2
}
print(mult(no1: 2, no2: 20))
print(mult(no1: 3, no2: 15))
print(mult(no1: 4, no2: 30))

当我们使用游乐场运行上述程序时,我们得到以下结果 -

40
45
120

没有参数的函数

我们也可能没有任何参数的功能。

语法 (Syntax)

func funcname() -> datatype {
   return datatype
}

以下是具有不带参数的函数的示例 -

func votersname() -> String {
   return "Alice"
}
print(votersname()) 

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Alice

具有返回值的函数

函数还用于将字符串,整数和浮点数据类型值作为返回类型返回。 为了找出给定数组函数中的最大和最小数字,使用大小整数数据类型声明'ls'。

初始化数组以保存整数值。 然后处理该数组,并读取数组中的每个值并比较其先前的值。 当值小于前一个值时,它存储在'small'参数中,否则它存储在'large'参数中,并通过调用函数返回值。

func ls(array: [Int]) -> (large: Int, small: Int) {
   var lar = array[0]
   var sma = array[0]
   for i in array[1..<array.count] {
      if i < sma {
         sma = i
      } else if i > lar {
         lar = i
      }
   }
   return (lar, sma)
}
let num = ls(array: [40,12,-5,78,98])
print("Largest number is: \(num.large) and smallest number is: \(num.small)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Largest number is: 98 and smallest number is: -5

没有返回值的函数

某些函数可能在函数内声明了参数而没有任何返回值。 以下程序将ab声明为sum()函数的参数。 在函数本身内部,通过调用函数调用sum()来传递参数ab的值,并打印其值,从而消除返回值。

func sum(a: Int, b: Int) {
   let a = a + b
   let b = a - b
   print(a, b)
}
sum(a: 20, b: 10)
sum(a: 40, b: 10)
sum(a: 24, b: 6)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

30 20
50 40
30 24

具有可选返回类型的函数

Swift 4引入了“可选”功能,通过引入安全措施来消除问题。 例如,我们将函数值返回类型声明为整数,但是当函数返回字符串值或nil值时会发生什么。 在这种情况下,编译器将返回错误值。 引入'可选'来摆脱这些问题。

可选函数将采用两种形式'value'和'nil'。 我们会提到'Optionals'和关键保留字符'?' 检查元组是返回值还是nil值。

func minMax(array: [Int]) -> (min: Int, max: Int)? {
   if array.isEmpty { return nil }
   var currentMin = array[0]
   var currentMax = array[0]
   for value in array[1..<array.count] {
      if value < currentMin {
         currentMin = value
      } else if value > currentMax {
         currentMax = value
      }
   }
   return (currentMin, currentMax)
}
if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
   print("min is \(bounds.min) and max is \(bounds.max)")
}

在使用游乐场运行上述程序的时候,得到以下的结果 -

min is -6 and max is 109

''Optionals'用于检查'nil'或垃圾值,从而在调试时耗费大量时间,并使代码对用户有效且可读。

功能本地Vs外部参数名称

本地参数名称

仅在函数内部访问本地参数名称。

func sample(number: Int) {
   print(number)
}

这里, func样本参数号被声明为内部变量,因为它是由函数sample()在内部访问的。 这里'number'被声明为局部变量,但是变量的引用是在函数外部使用以下语句 -

func sample(number: Int) {
   print(number)
}
sample(number: 1)
sample(number: 2)
sample(number: 3)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

1
2
3

外部参数名称

外部参数名称允许我们命名函数参数以使其目的更清晰。 例如,您可以在下面命名两个函数参数,然后按如下方式调用该函数 -

func pow(firstArg a: Int, secondArg b: Int) -> Int {
   var res = a
   for _ in 1..<b {
      res = res * a
   }
   print(res)
   return res
}
pow(firstArg:5, secondArg:3)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

125

变量参数

当我们想要定义具有多个参数的函数时,我们可以将成员声明为'variadic'参数。 可以在参数名称后面的(···)将参数指定为可变参数。

func vari<N>(members: N...){
   for i in members {
      print(i)
   }
}
vari(members: 4,3,5)
vari(members: 4.5, 3.1, 5.6)
vari(members: "Swift 4", "Enumerations", "Closures")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

4
3
5
4.5
3.1
5.6
Swift 4
Enumerations
Closures

常量,变量和I/O参数

默认情况下,函数将参数视为“常量”,而用户也可以将函数的参数声明为变量。 我们已经讨论过'let'关键字用于声明常量参数,变量参数用'var'关键字定义。

Swift 4中的I/O参数提供了保留参数值的功能,即使在函数调用后修改了它的值。 在函数参数定义的开头,声明'inout'关键字保留成员值。

它派生关键字'inout',因为它的值被'in'传递给函数,并且它的值由其函数体访问和修改,并且它返回'out'返回函数以修改原始参数。

变量仅作为输入输出参数的参数传递,因为它的值仅在函数内外被修改。 因此,无需将字符串和文字声明为输入输出参数。 变量名前的'&'表示我们将参数传递给in-out参数。

func temp(a1: inout Int, b1: inout Int) {
   let t = a1
   a1 = b1
   b1 = t
}
var no = 2
var co = 10
temp(a1: &no, b1: &co)
print("Swapped values are \(no), \(co)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Swapped values are 10, 2

功能类型及其用法

通过考虑输入参数并输出所需结果,每个功能都遵循特定功能。

func inputs(no1: Int, no2: Int) -> Int {
   return no1/no2
}

以下是一个例子 -

func inputs(no1: Int, no2: Int) -> Int {
   return no1/no2
}
print(inputs(no1: 20, no2: 10))
print(inputs(no1: 36, no2: 6))

当我们使用游乐场运行上述程序时,我们得到以下结果 -

2
6

这里函数初始化为两个参数no1no2作为整数数据类型,其返回类型也声明为'int'

Func inputstr(name: String) -> String {
   return name
}

这里函数声明为string数据类型。

函数也可能具有void数据类型,并且此类函数不会返回任何内容。

func inputstr() {
   print("Swift 4 Functions")
   print("Types and its Usage")
}
inputstr()

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Swift 4 Functions
Types and its Usage

上述函数声明为void函数,没有参数且没有返回值。

使用函数类型

函数首先使用整数,浮点或字符串类型参数传递,然后将其作为常量或变量传递给函数,如下所述。

var addition: (Int, Int) -> Int = sum

这里sum是一个具有'a'和'b'整数变量的函数名,现在它被声明为函数名加法的变量。 此后,addition和sum函数都具有相同数量的参数,声明为整数数据类型,并且还返回整数值作为引用。

func sum(a: Int, b: Int) -> Int {
   return a + b
}
var addition: (Int, Int) -> Int = sum
print("Result: \(addition(40, 89))")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Result: 129

函数类型作为参数类型和返回类型

我们还可以将函数本身作为参数类型传递给另一个函数。

func sum(a: Int, b: Int) -> Int {
   return a + b
}
var addition: (Int, Int) -> Int = sum
print("Result: \(addition(40, 89))")
func another(addition: (Int, Int) -> Int, a: Int, b: Int) {
   print("Result: \(addition(a, b))")
}
another(sum, 10, 20)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Result: 129
Result: 30

嵌套函数

嵌套函数提供了通过调用inside函数来调用外部函数的工具。

func calcDecrement(forDecrement total: Int) -> () -> Int {
   var overallDecrement = 0
   func decrementer() -> Int {
      overallDecrement -= total
      return overallDecrement
   }
   return decrementer
}
let decrem = calcDecrement(forDecrement: 30)
print(decrem())

当我们使用游乐场运行上述程序时,我们得到以下结果 -

-30

Swift - Closures

Swift 4中的闭包类似于组织为块的自包含函数,并且像C和Objective C语言一样调用。 在函数内定义的常量和变量引用被捕获并存储在闭包中。 函数被视为闭包的特殊情况,它采用以下三种形式 -

全球职能 嵌套函数 关闭表达式
有一个名字。 不捕获任何值 有一个名字。 从封闭函数中捕获值 未命名的Closures从相邻块中捕获值

Swift 4语言中的Closure表达式遵循清晰,优化和轻量级的语法风格,包括。

  • 从上下文中推断参数和返回值类型。
  • 单表达式闭包的隐式返回。
  • 速记参数名称和
  • Trailing closure syntax

语法 (Syntax)

以下是定义闭包的通用语法,该闭包接受参数并返回数据类型 -

{
   (parameters) −> return type in
   statements
}

以下是一个简单的例子 -

let studname = { print("Welcome to Swift Closures") }
studname()

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Welcome to Swift Closures

以下闭包接受两个参数并返回Bool值 -

{     
   (Int, Int) −> Bool in
   Statement1
   Statement 2
   ---
   Statement n
}

以下是一个简单的例子 -

let divide = {
   (val1: Int, val2: Int) -> Int in 
   return val1/val2 
}
let result = divide(200, 20)
print (result)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

10

闭包中的表达式

嵌套函数提供了一种命名和定义代码块的便捷方式。 而不是表示整个函数声明和名称构造用于表示更短的函数。 通过闭包表达式实现在具有集中语法的清晰简短语句中表示函数。

升序订单计划

对字符串进行排序是通过Swift 4s密钥保留功能“已排序”实现的,该功能已在标准库中提供。 该函数将按升序对给定字符串进行排序,并返回具有旧数组中提到的相同大小和数据类型的新数组中的元素。 旧阵列保持不变。

在排序函数中表示两个参数 -

  • 已知类型的值表示为数组。

  • 数组内容(Int,Int)并返回一个布尔值(Bool)如果数组正确排序,它将返回true值,否则返回false。

编写带有输入字符串的普通函数并将其传递给已排序函数,以将字符串排序为新数组,如下所示 -

func ascend(s1: String, s2: String) -> Bool {
   return s1 > s2
}
let stringcmp = ascend(s1: "Swift 4", s2: "great")
print (stringcmp)

在使用游乐场运行上述程序的时候,得到以下的结果 -

true

要为冰淇淋分类的初始数组给出为“Swift 4”和“great”。 将数组排序的函数声明为字符串数据类型,其返回类型称为布尔值。 两个字符串都按升序进行比较和排序,并存储在一个新数组中。 如果成功执行排序,则函数将返回true值,否则返回false。

闭包表达式语法使用 -

  • 常数参数,
  • 变量参数,和
  • inout参数。

Closure表达式不支持默认值。 变量参数和元组也可以用作参数类型和返回类型。

let sum = {
   (no1: Int, no2: Int) -> Int in 
   return no1 + no2 
}
let digits = sum(10, 20)
print(digits)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

30

函数语句中提到的参数和返回类型声明也可以用带有'in'关键字的内联闭包表达式函数表示。 一旦声明参数和返回类型'in'关键字用于表示闭包的主体。

单表达式隐式返回

这里,sorted函数的第二个参数的函数类型清楚地表明闭包必须返回一个Bool值。 因为闭包的主体包含一个返回Bool值的表达式(s1> s2),所以没有歧义,并且可以省略return关键字。

要在表达式中返回单表达式语句,请在其声明部分中省略'return'关键字。

var count:[Int] = [5, 10, -6, 75, 20]
let descending = count.sorted(by: { n1, n2 in n1 > n2 })
let ascending = count.sorted(by: { n1, n2 in n1 < n2 })
print(descending)
print(ascending)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

[75, 20, 10, 5, -6]
[-6, 5, 10, 20, 75]

语句本身清楚地定义当string1大于字符串2时返回true否则为false因此这里省略return语句。

已知类型闭包

考虑添加两个数字。 我们知道add将返回整数数据类型。 因此,已知的类型闭包被声明为 -

let sub = {
   (no1: Int, no2: Int) -> Int in 
   return no1 - no2 
}
let digits = sub(10, 20)
print(digits)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

-10

将速记参数名称声明为闭包

Swift 4自动为内联闭包提供简写参数名称,可用于通过名称$ 0,$ 1,$ 2等来引用闭包参数的值。

var shorthand: (String, String) -> String
shorthand = { $1 }
print(shorthand("100", "200"))

这里,$ 0和$ 1引用闭包的第一个和第二个String参数。

当我们使用游乐场运行上述程序时,我们得到以下结果 -

200

Swift 4通过表示$ 0,$ 1,$ 2 --- $ n,便于用户将Inline闭包表示为简写参数名称。

当我们在闭包表达式中表示简写参数名称时,在定义部分中省略了闭包参数列表。 根据函数类型,将派生简写参数名称。 由于在表达式主体中定义了速记参数,因此省略了'in'关键字。

闭包作为操作符函数 (Closures as Operator Functions)

Swift 4提供了一种通过仅提供运算符函数作为闭包来访问成员的简便方法。 在前面的示例中,关键字'Bool'用于在字符串相等时返回'true',否则返回'false'。

关闭时的运算符函数使表达式更简单 -

let numb = [98, -20, -30, 42, 18, 35]
var sortedNumbers = numb.sorted ({
   (left: Int, right: Int) -> Bool in
   return left < right
})
let asc = numb.sorted(<)
print(asc)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

[-30, -20, 18, 35, 42, 98]

关闭作为预告片

在“Trailing Closures”的帮助下声明将函数的最终参数传递给闭包表达式。 它用{}写在function()之外。 当无法在单行上内联编写函数时,需要使用它。

reversed = sorted(names) { $0 > $1}

其中{$ 0> $ 1}表示为在(名称)外部声明的尾随闭包。

import Foundation
var letters = ["North", "East", "West", "South"]
let twoletters = letters.map({ 
   (state: String) -> String in
   return state.substringToIndex(advance(state.startIndex, 2)).uppercaseString
})
let stletters = letters.map() { 
   $0.substringToIndex(advance($0.startIndex, 2)).uppercaseString 
}
print(stletters)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

[NO, EA, WE, SO]

捕获值和引用类型

在Swift 4中,捕获常量和变量值是在闭包的帮助下完成的。 它进一步引用和修改闭包体内的那些常量和变量的值,即使变量不再存在。

通过在其他函数的主体中编写函数来使用嵌套函数来捕获常量和变量值。

嵌套函数捕获 -

  • 外部函数参数。
  • 捕获外部函数中定义的常量和变量。

在Swift 4中,当在函数内声明常量或变量时,闭包也会自动创建对这些变量的引用。 它还提供了将两个以上变量作为同一个闭包引用的工具,如下所示 -

let decrem = calcDecrement(forDecrement: 18)
decrem()

这里的oneDecrement和Decrement变量都指向与闭包引用相同的内存块。

func calcDecrement(forDecrement total: Int) -> () -> Int {
   var overallDecrement = 100
   func decrementer() -> Int {
      overallDecrement -= total
      print(overallDecrement)
      return overallDecrement
   }
   return decrementer
}
let decrem = calcDecrement(forDecrement: 18)
decrem()
decrem()
decrem()

当我们使用游乐场运行上述程序时,我们得到以下结果 -

82
64
46

当每次调用外部函数calcDecrement时,它会调用decrementer()函数并将值递减18并在外部函数calcDecrement的帮助下返回结果。 这里calcDecrement充当闭包。

即使函数decrementer()没有任何参数,默认情况下,闭包通过捕获其现有值来引用变量'overallDecrement'和'total'。 指定变量的值副本与新的decrementer()函数一起存储。 Swift 4通过在不使用变量时分配和释放内存空间来处理内存管理功能。

Swift - Enumerations

枚举是用户定义的数据类型,由一组相关值组成。 关键字enum用于定义枚举数据类型。

枚举功能

Swift 4中的枚举也类似于C和Objective C的结构。

  • 它在类中声明,并且通过该类的实例访问其值。

  • 使用枚举初始化器定义初始成员值。

  • 通过确保标准协议功能,还可以扩展其功能。

语法 (Syntax)

使用enum关键字引入枚举,并将其整个定义放在一对括号中 -

enum enumname {
   // enumeration values are described here
}

例如,您可以按如下方式定义星期几的枚举 -

enum DaysofaWeek {
   case Sunday
   case Monday
   ---
   case Saturday
}

例子 (Example)

enum names {
   case Swift
   case Closures
}
var lang = names.Closures
lang = .Closures
switch lang {
   case .Swift:
      print("Welcome to Swift")
   case .Closures:
      print("Welcome to Closures")
   default:
      print("Introduction")
}

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Welcome to Closures

Swift 4枚举不会像C和Objective C那样为其成员分配默认值。相反,成员由其枚举名称显式定义。 枚举名称应以大写字母开头(例如:enum DaysofaWeek)。

var weekDay = DaysofaWeek.Sunday 

这里枚举名称'DaysofaWeek'被分配给变量weekday.Sunday。 它通知编译器数据类型属于Sunday将被分配给该特定类的后续枚举成员。 一旦定义了枚举成员数据类型,就可以通过传递值和进一步计算来访问成员。

Enumeration with Switch 语句

Swift 4'Twitch'语句也遵循多路选择。 根据指定的条件,在特定时间仅访问一个变量。 switch语句中的默认情况用于捕获未指定的情况。

enum Climate {
   case India
   case America
   case Africa
   case Australia
}
var season = Climate.America
season = .America
switch season {
   case .India:
      print("Climate is Hot")
   case .America:
      print("Climate is Cold")
   case .Africa:
      print("Climate is Moderate")
   case .Australia:
      print("Climate is Rainy")
}

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Climate is Cold

该计划首先将气候定义为枚举名称。 然后,其成员如“印度”,“美国”,“非洲”和“澳大利亚”被宣布属于“气候”类。 现在,美国成员被分配到季节变量。 此外,Switch case将看到与.America相对应的值,它将分支到该特定语句。 输出将显示为“气候寒冷”。 同样,可以通过switch语句访问所有成员。 当条件不满足时,默认打印“气候不可预测”。

枚举可以进一步分类为关联值和原始值。

关联值与原始值之间的差异

Associated ValuesRaw Values
不同的数据类型 相同的数据类型
Ex: enum {10,0.8,"Hello"}Ex: enum {10,35,50}
值基于常量或变量创建 Prepopulated Values
每次声明时都会变化 会员价值相同

具有相关值的枚举

enum Student {
   case Name(String)
   case Mark(Int,Int,Int)
}
var studDetails = Student.Name("Swift 4")
var studMarks = Student.Mark(98,97,95)
switch studMarks {
   case .Name(let studName):
      print("Student name is: \(studName).")
   case .Mark(let Mark1, let Mark2, let Mark3):
      print("Student Marks are: \(Mark1),\(Mark2),\(Mark3).")
}

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Student Marks are: 98,97,95.

例如,考虑访问三个主题中的学生姓名和标记,枚举名称被声明为学生,枚举类中的成员是属于字符串数据类型的名称,标记表示为数据类型Integer的mark1,mark2和mark3。 访问学生姓名或他们得分的分数

var studDetails = Student.Name("Swift")
var studMarks = Student.Mark(98,97,95)

现在,如果执行该案例块,则开关案例将打印学生姓名,否则将打印学生保护的标记。 如果两个条件都失败,则将执行默认块。

具有原始价值的枚举

原始值可以是字符串,字符或任何整数或浮点数类型。 每个原始值在其枚举声明中必须是唯一的。 当整数用于原始值时,如果没有为某些枚举成员指定值,则它们会自动递增。

enum Month: Int {
   case January = 1, February, March, April, May, June, July, August,
      September, October, November, December
}
let yearMonth = Month.May.rawValue
print("Value of the Month is: \(yearMonth).")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Value of the Month is: 5.

Swift - Structures

Swift 4提供了一个灵活的构建块,它使用构造作为结构。 通过利用这些结构,可以定义构造方法和属性。

与C和Objective C不同

  • 结构不需要实现文件和接口。

  • Structure允许我们创建单个文件并将其界面自动扩展到其他块。

在Structure中,通过返回旧值的副本来复制变量值并在后续代码中传递,以便不能更改这些值。

语法 (Syntax)

Structures are defined with a 'Struct' Keyword.
struct nameStruct {
   Definition 1
   Definition 2
   ---
   Definition N
}

结构的定义

例如,假设我们必须访问包含三个科目标记的学生记录,并找出三个科目的总数。 这里markStruct用于初始化具有三个标记的结构作为数据类型'Int'。

struct MarkStruct {
   var mark1: Int
   var mark2: Int
   var mark3: Int
}

访问结构及其属性

结构的成员可以通过其结构名称访问。 结构的实例由'let'关键字初始化。

struct studentMarks {
   var mark1 = 100
   var mark2 = 200
   var mark3 = 300
}
let marks = studentMarks()
print("Mark1 is \(marks.mark1)")
print("Mark2 is \(marks.mark2)")
print("Mark3 is \(marks.mark3)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Mark1 is 100
Mark2 is 200
Mark3 is 300

学生标记的结构名称为“studentMarks”。 结构成员初始化为具有整数类型值的mark1,mark2,mark3。 然后结构studentMarks()通过'let'关键字传递给'marks'。 此后'标记'将包含结构成员值。 现在通过'。'访问结构成员值来打印值。 以其初始化的名称。

struct MarksStruct {
   var mark: Int
   init(mark: Int) {
      self.mark = mark
   }
}
var aStruct = MarksStruct(mark: 98)
var bStruct = aStruct     // aStruct and bStruct are two structs with the same value!
bStruct.mark = 97
print(aStruct.mark)      // 98
print(bStruct.mark)      // 97

当我们使用游乐场运行上述程序时,我们得到以下结果 -

98
97

结构的最佳使用实践

Swift 4语言提供了将结构定义为用于构建功能块的自定义数据类型的功能。 结构的实例通过其值传递给定义的块以进行进一步操作。

需要有结构

  • 封装简单数据值。

  • 通过“值”而不是“引用”复制封装数据及其关联属性。

  • “复制”和“参考”的结构。

Swift 4中的结构传递其成员的值而不是其引用。

struct markStruct {
   var mark1: Int
   var mark2: Int
   var mark3: Int
   init(mark1: Int, mark2: Int, mark3: Int) {
      self.mark1 = mark1
      self.mark2 = mark2
      self.mark3 = mark3
   }
}
var marks = markStruct(mark1: 98, mark2: 96, mark3:100)
print(marks.mark1)
print(marks.mark2)
print(marks.mark3)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

98
96
100

另一个例子

struct markStruct {
   var mark1: Int
   var mark2: Int
   var mark3: Int
   init(mark1: Int, mark2: Int, mark3: Int) {
      self.mark1 = mark1
      self.mark2 = mark2
      self.mark3 = mark3
   }
}
var fail = markStruct(mark1: 34, mark2: 42, mark3: 13)
print(fail.mark1)
print(fail.mark2)
print(fail.mark3)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

34
42
13

首先定义结构'markStruct',其成员为mark1,mark2和mark3。 现在,成员类的变量被初始化为保存整数值。 然后使用“self”关键字创建结构成员的副本。 一旦创建了结构成员的副本,结构块及其参数标记就会传递给'marks'变量,该变量现在将保存学生标记。 然后将标记打印为98,96,100。对于相同结构成员的下一步骤,使用另一个名为“fail”的实例来指向具有不同标记的相同结构成员。 然后结果打印为34,42,13。这清楚地解释了结构将具有成员变量的副本,然后将成员传递给它们即将到来的功能块。

Swift - Classes

Swift 4中的类是灵活构造的构建块。 与常量,变量和函数类似,用户可以定义类属性和方法。 Swift 4为我们提供了一些功能,在声明类时,用户无需创建接口或实现文件。 Swift 4允许我们将类创建为单个文件,并且一旦初始化类,默认情况下将创建外部接口。

有类的好处

  • 继承获取另一个类的属性

  • 类型转换使用户可以在运行时检查类类型

  • Deinitializers负责释放内存资源

  • 引用计数允许类实例具有多个引用

类和结构的共同特征

  • 定义属性以存储值
  • 定义下标用于提供对值的访问
  • 初始化方法以改进功能
  • 初始状态由初始化程序定义
  • 功能扩展超出默认值
  • 确认协议功能标准

语法 (Syntax)

Class classname {
   Definition 1
   Definition 2
   --- 
   Definition N
}

类定义

class student {
   var studname: String
   var mark: Int 
   var mark2: Int 
}

创建实例的语法

let studrecord = student()

例子 (Example)

class MarksStruct {
   var mark: Int
   init(mark: Int) {
      self.mark = mark
   }
}
class studentMarks {
   var mark = 300
}
let marks = studentMarks()
print("Mark is \(marks.mark)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Mark is 300

访问类属性作为引用类型

可以通过'。'访问类属性。 句法。 属性名称以'。'分隔。 在实例名称之后。

class MarksStruct {
   var mark: Int
   init(mark: Int) {
      self.mark = mark
   }
}
class studentMarks {
   var mark1 = 300
   var mark2 = 400
   var mark3 = 900
}
let marks = studentMarks()
print("Mark1 is \(marks.mark1)")
print("Mark2 is \(marks.mark2)")
print("Mark3 is \(marks.mark3)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Mark1 is 300
Mark2 is 400
Mark3 is 900

类标识运算符

Swift 4中的类指的是指向单个实例的多个常量和变量。 要了解指向特定类实例的常量和变量,请使用标识符运算符。 类实例始终通过引用传递。 在类中,NSString,NSArray和NSDictionary实例始终作为对现有实例的引用而不是作为副本进行分配和传递。

与运算符相同 与运算符不一致
Operator used is (===)Operator used is (!==)
当两个常量或变量指向同一个实例时返回true 当两个常量或变量指向不同的实例时返回true
class SampleClass: Equatable {
   let myProperty: String
   init(s: String) {
      myProperty = s
   }
}
func ==(lhs: SampleClass, rhs: SampleClass) -> Bool {
   return lhs.myProperty == rhs.myProperty
}
let spClass1 = SampleClass(s: "Hello")
let spClass2 = SampleClass(s: "Hello")
spClass1 === spClass2 // false
print("\(spClass1)")
spClass1 !== spClass2 // true
print("\(spClass2)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

main.SampleClass
main.SampleClass

Swift - Properties

Swift 4语言为类,枚举或结构提供关联值的属性。 属性可以进一步分为存储属性和计算属性。

存储属性和计算属性之间的差异

存储的财产 计算财产
将常量和变量值存储为实例 计算值而不是存储值
由类和结构提供 由类,枚举和结构提供

Stored和Computed属性都与实例类型相关联。 当属性与其类型值相关联时,它将被定义为“类型属性”。 存储和计算属性通常与特定类型的实例相关联。 但是,属性也可以与类型本身相关联。 这些属性称为类型属性。 还使用了财产观察员

  • 观察存储属性的值
  • 观察从超类派生的继承子类的属性

存储属性

Swift 4引入了Stored Property概念来存储常量和变量的实例。 常量的存储属性由'let'关键字定义,变量的存储属性由'var'关键字定义。

  • 在定义期间,存储属性提供“默认值”
  • 在初始化期间,用户可以初始化和修改初始值
struct Number {
   var digits: Int
   let pi = 3.1415
}
var n = Number(digits: 12345)
n.digits = 67
print("\(n.digits)")
print("\(n.pi)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

67
3.1415

考虑上面代码中的以下行 -

let pi = 3.1415

这里,变量pi被初始化为具有实例pi = 3.1415的存储属性值。 因此,每当引用实例时,它将仅保持值3.1415。

存储属性的另一种方法是具有常量结构。 因此,结构的整个实例将被视为“常量的存储属性”。

struct Number {
   var digits: Int
   let numbers = 3.1415
}
var n = Number(digits: 12345)
n.digits = 67
print("\(n.digits)")
print("\(n.numbers)")
n.numbers = 8.7

当我们使用游乐场运行上述程序时,我们得到以下结果 -

error: cannot assign to 'numbers' in 'n'
n.numbers = 8.7

它不会将'number'重新初始化为8.7,而是返回一条错误消息,指示'number'被声明为常量。

懒惰的存储属性

Swift 4提供了一个名为“Lazy Stored Property”的灵活属性,它不会在第一次初始化变量时计算初始值。 在变量声明之前使用'lazy'修饰符将其作为惰性存储属性。

使用懒惰属性 -

  • 延迟对象创建。
  • 当属性依赖于类的其他部分时,尚未知道
class sample {
   lazy var no = number()    // `var` declaration is required.
}
class number {
   var name = "Swift 4"
}
var firstsample = sample()
print(firstsample.no.name)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Swift 4

实例变量

在Objective C中,Stored属性还有用于备份目的的实例变量,用于存储在stored属性中声明的值。

Swift 4将这两个概念集成到一个“存储属性”声明中。 而不是具有相应的实例变量和备份值“存储属性”包含通过变量名称,数据类型和内存管理功能在变量属性的单个位置中定义的所有集成信息。

计算属性

而不是存储值计算属性提供了getter和可选的setter来间接检索和设置其他属性和值。

class sample {
   var no1 = 0.0, no2 = 0.0
   var length = 300.0, breadth = 150.0
   var middle: (Double, Double) {
      get {
         return (length/2, breadth/2)
      }
      set(axis){
         no1 = axis.0 - (length/2)
         no2 = axis.1 - (breadth/2)
      }
   }
}
var result = sample()
print(result.middle)
result.middle = (0.0, 10.0)
print(result.no1)
print(result.no2)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

(150.0, 75.0)
-150.0
-65.0

当computed属性将新值保留为undefined时,将为该特定变量设置默认值。

计算属性为只读属性

compute属性中的只读属性被定义为具有getter但没有setter的属性。 它始终用于返回值。 变量通过'。'进一步访问。 语法但不能设置为其他值。

class film {
   var head = ""
   var duration = 0.0
   var metaInfo: [String:String] {
      return [
         "head": self.head,
         "duration":"\(self.duration)"
      ]
   }
}
var movie = film()
movie.head = "Swift 4 Properties"
movie.duration = 3.09
print(movie.metaInfo["head"]!)
print(movie.metaInfo["duration"]!)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Swift 4 Properties
3.09

计算属性作为属性观察者

在Swift 4中观察和响应属性值使用Property Observers。 每次设置属性值时,都会调用属性观察者。 除了延迟存储的属性,我们可以通过方法'覆盖'将属性观察者添加到'inherited'属性。

属性观察者可以由任何一个来定义

  • 在存储价值之前 - 意志

  • 存储新值后 - 确定

  • 在初始化程序集中设置属性时,无法调用didset观察者。

class Samplepgm {
   var counter: Int = 0 {
      willSet(newTotal){
         print("Total Counter is: \(newTotal)")
      }
      didSet {
         if counter > oldValue {
            print("Newly Added Counter \(counter - oldValue)")
         }
      }
   }
}
let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Total Counter is: 100
Newly Added Counter 100
Total Counter is: 800
Newly Added Counter 700

本地和全局变量

声明本地和全局变量用于计算和观察属性。

局部变量 全局变量
在函数,方法或闭包上下文中定义的变量。 在函数,方法,闭包或类型上下文之外定义的变量。
用于存储和检索值。 用于存储和检索值。
存储的属性用于获取和设置值。 存储的属性用于获取和设置值。
还使用计算属性。 还使用计算属性。

输入属性

属性在类型定义部分中使用花括号{}定义,变量的范围也先前已定义。 为了定义值类型的类型属性,使用“static”关键字,对于类类型,使用“class”关键字。

语法 (Syntax)

struct Structname {
   static var storedTypeProperty = " "
   static var computedTypeProperty: Int {
      // return an Int value here
   }
}
enum Enumname {
   static var storedTypeProperty = " "
   static var computedTypeProperty: Int {
      // return an Int value here
   }
}
class Classname {
   class var computedTypeProperty: Int {
      // return an Int value here
   }
}

查询和设置属性

就像实例属性一样,查询类型属性并使用“。”进行设置。 单独使用类型语法而不是指向实例。

struct StudMarks {
   static let markCount = 97
   static var totalCount = 0
   var InternalMarks: Int = 0 {
      didSet {
         if InternalMarks > StudMarks.markCount {
            InternalMarks = StudMarks.markCount
         }
         if InternalMarks > StudMarks.totalCount {
            StudMarks.totalCount = InternalMarks
         }
      }
   }
}
var stud1Mark1 = StudMarks()
var stud1Mark2 = StudMarks()
stud1Mark1.InternalMarks = 98
print(stud1Mark1.InternalMarks)
stud1Mark2.InternalMarks = 87
print(stud1Mark2.InternalMarks)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

97
87

Swift - Methods

在Swift 4语言中,与特定类型关联的函数称为“方法”。 在Objective C中,Classes用于定义方法,而Swift 4语言为用户提供了为类,结构和枚举提供方法的灵活性。

实例方法

在Swift 4语言中,通过实例方法访问类,结构和枚举实例。

实例方法提供功能

  • 访问和修改实例属性
  • 与实例需求相关的功能

可以在{}花括号内写入实例方法。 它具有对类型实例的方法和属性的隐式访问。 当调用该类型的特定实例时,它将访问该特定实例。

语法 (Syntax)

func funcname(Parameters) -> returntype {
   Statement1
   Statement2
   ---
   Statement N
   return parameters
}

例子 (Example)

class calculations {
   let a: Int
   let b: Int
   let res: Int
   init(a: Int, b: Int) {
      self.a = a
      self.b = b
      res = a + b
   }
   func tot(c: Int) -> Int {
      return res - c
   }
   func result() {
      print("Result is: \(tot(c: 20))")
      print("Result is: \(tot(c: 50))")
   }
}
let pri = calculations(a: 600, b: 300)
pri.result()

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Result is: 880
Result is: 850

类计算定义了两个实例方法 -

  • init()被定义为添加两个数字a和b并将其存储在结果'res'中
  • tot()用于从传递'c'值中减去'res'

最后,使用a和b的值打印计算方法。 使用'。'访问实例方法 点语法

本地和外部参数名称

Swift 4函数描述了它们变量的局部声明和全局声明。 类似地,Swift 4方法命名约定也类似于Objective C的命名约定。但是函数和方法的局部和全局参数名称声明的特征是不同的。 Swift 4中的第一个参数由介词名称引用为“with”,“for”和“by”,以便于访问命名约定。

Swift 4通过将第一个参数名称声明为本地参数名称而其余参数名称为全局参数名称,提供了方法的灵活性。 这里'no1'由Swift 4方法声明为本地参数名称。 'no2'用于全局声明并通过程序访问。

class division {
   var count: Int = 0
   func incrementBy(no1: Int, no2: Int) {
      count = no1/no2
      print(count)
   }
}
let counter = division()
counter.incrementBy(no1: 1800, no2: 3)
counter.incrementBy(no1: 1600, no2: 5)
counter.incrementBy(no1: 11000, no2: 3)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

600
320
3666

带#和_符号的外部参数名称

即使Swift 4方法为本地声明提供了第一个参数名称,用户也可以修改从本地声明到全局声明的参数名称。 这可以通过在'#'符号前加上第一个参数名称来完成。 通过这样做,可以在整个模块中全局访问第一个参数。

当用户需要使用外部名称访问后续参数名称时,将使用“_”符号覆盖方法名称。

class multiplication {
   var count: Int = 0
   func incrementBy(no1: Int, no2: Int) {
      count = no1 * no2
      print(count)
   }
}
let counter = multiplication()
counter.incrementBy(no1: 800, no2: 3)
counter.incrementBy(no1: 100, no2: 5)
counter.incrementBy(no1: 15000, no2: 3)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

2400
500
45000

方法中的自我属性

方法对其所有已定义的类型实例都有一个称为“self”的隐式属性。 'Self'属性用于引用其定义方法的当前实例。

class calculations {
   let a: Int
   let b: Int
   let res: Int
   init(a: Int, b: Int) {
      self.a = a
      self.b = b
      res = a + b
      print("Inside Self Block: \(res)")
   }
   func tot(c: Int) -> Int {
      return res - c
   }
   func result() {
      print("Result is: \(tot(c: 20))")
      print("Result is: \(tot(c: 50))")
   }
}
let pri = calculations(a: 600, b: 300)
let sum = calculations(a: 1200, b: 300)
pri.result()
sum.result()

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Inside Self Block: 900
Inside Self Block: 1500
Result is: 880
Result is: 850
Result is: 1480
Result is: 1450

从实例方法修改值类型

在Swift 4中,语言结构和枚举属于值类型,不能通过其实例方法进行更改。 但是,Swift 4语言提供了通过“变异”行为修改值类型的灵活性。 Mutate将在实例方法中进行任何更改,并在执行方法后返回到原始表单。 此外,通过'self'属性,为其隐式函数创建新实例,并在执行后替换现有方法

struct area {
   var length = 1
   var breadth = 1
   func area() -> Int {
      return length * breadth
   }
   mutating func scaleBy(res: Int) {
      length *= res
      breadth *= res
      print(length)
      print(breadth)
   }
}
var val = area(length: 3, breadth: 5)
val.scaleBy(res: 3)
val.scaleBy(res: 30)
val.scaleBy(res: 300)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

9
15
270
450
81000
135000

变异方法的自我属性

变换方法与'self'属性相结合,为定义的方法分配一个新实例。

struct area {
   var length = 1
   var breadth = 1
   func area() -> Int {
      return length * breadth
   }
   mutating func scaleBy(res: Int) {
      self.length *= res
      self.breadth *= res
      print(length)
      print(breadth)
   }
}
var val = area(length: 3, breadth: 5)
val.scaleBy(res: 13)

当我们使用playground运行上述程序时,我们得到以下结果。 -

39
65

类型方法

当调用方法的特定实例时,它被称为Instance方法; 当方法调用特定类型的方法时,它被称为“类型方法”。 “类”的类型方法由“func”关键字定义,结构和枚举类型方法在“func”关键字之前使用“static”关键字定义。

类型方法由'。'调用和访问。 语法,而不是调用特定实例,调用整个方法。

class Math {
   class func abs(number: Int) -> Int {
      if number < 0 {
         return (-number)
      } else {
         return number
      }
   }
}
struct absno {
   static func abs(number: Int) -> Int {
      if number < 0 {
         return (-number)
      } else {
         return number
      }
   }
}
let no = Math.abs(number: -35)
let num = absno.abs(number: -5)
print(no)
print(num)

当我们使用playground运行上述程序时,我们得到以下结果。 -

35
5

Swift - Subscripts

在下标的帮助下访问类,结构和枚举中的集合,序列和列表的元素成员。 这些下标用于在索引的帮助下存储和检索值。 在someArray [index]的帮助下访问数组元素,并在Dictionary实例中的后续成员元素可以作为someDicitonary [key]访问。

对于单个类型,下标可以是单个声明到多个声明。 我们可以使用适当的下标来重载传递给下标的索引值的类型。 根据用户对其输入数据类型声明的要求,下标的范围也从单维到多维。

下标声明语法及其用法

让我们回顾一下计算出来的属性。 下标也遵循与计算属性相同的语法。 对于查询类型实例,下标写在方括号内,后跟实例名称。 下标语法遵循与“实例方法”和“计算属性”语法相同的语法结构。 'subscript'关键字用于定义下标,用户可以使用返回类型指定单个或多个参数。 下标可以具有读写或只读属性,并且在“getter”和“setter”属性的帮助下存储和检索实例,如计算属性的属性。

语法 (Syntax)

subscript(index: Int) −> Int {
   get {
      // used for subscript value declarations
   }
   set(newValue) {
      // definitions are written here
   }
}

例子 (Example1)

struct subexample {
   let decrementer: Int
   subscript(index: Int) -> Int {
      return decrementer/index
   }
}
let division = subexample(decrementer: 100)
print("The number is divisible by \(division[9]) times")
print("The number is divisible by \(division[2]) times")
print("The number is divisible by \(division[3]) times")
print("The number is divisible by \(division[5]) times")
print("The number is divisible by \(division[7]) times")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

The number is divisible by 11 times
The number is divisible by 50 times
The number is divisible by 33 times
The number is divisible by 20 times
The number is divisible by 14 times

例子 (Example2)

class daysofaweek {
   private var days = ["Sunday", "Monday", "Tuesday", "Wednesday",
      "Thursday", "Friday", "saturday"]
   subscript(index: Int) -> String {
      get {
         return days[index]
      }
      set(newValue) {
         self.days[index] = newValue
      }
   }
}
var p = daysofaweek()
print(p[0])
print(p[1])
print(p[2])
print(p[3])

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Sunday
Monday
Tuesday
Wednesday

下标中的选项

下标采用单个到多个输入参数,这些输入参数也属于任何数据类型。 它们还可以使用变量和可变参数。 下标不能提供默认参数值或使用任何输入输出参数。

定义多个下标称为“下标重载”,其中类或结构可根据需要提供多个下标定义。 这些多个下标是根据下标括号中声明的值的类型推断的。

struct Matrix {
   let rows: Int, columns: Int
   var print: [Double]
   init(rows: Int, columns: Int) {
      self.rows = rows
      self.columns = columns
      print = Array(count: rows * columns, repeatedValue: 0.0)
   }
   subscript(row: Int, column: Int) -> Double {
      get {
         return print[(row * columns) + column]
      }
      set {
         print[(row * columns) + column] = newValue
      }
   }
}
var mat = Matrix(rows: 3, columns: 3)
mat[0,0] = 1.0
mat[0,1] = 2.0
mat[1,0] = 3.0
mat[1,1] = 5.0
print("\(mat[0,0])")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

1.0

Swift 4下标支持单个参数到适当数据类型的多个参数声明。 该程序将'Matrix'结构声明为2 * 2维数组矩阵,以存储'Double'数据类型。 Matrix参数输入Integer数据类型,用于声明行和列。

通过将行和列计数传递给初始化来创建Matrix的新实例,如下所示。

var mat = Matrix(rows: 3, columns: 3)

可以通过将行和列值传递到下标中来定义矩阵值,用逗号分隔,如下所示。

mat[0,0] = 1.0  
mat[0,1] = 2.0
mat[1,0] = 3.0
mat[1,1] = 5.0

Swift - Inheritance

取而不是更多形式的能力被定义为继承。 通常,类可以从另一个类继承方法,属性和功能。 类可以进一步分类为子类和超类。

  • Sub Class - 当一个类从另一个类继承属性,方法和函数时,它被称为子类

  • Super Class - 包含从其自身继承其他类的属性,方法和函数的类称为超类

Swift 4类包含超类,它调用和访问方法,属性,函数和重写方法。 此外,属性观察器还用于添加属性并修改存储或计算的属性方法。

基类

不从其他类继承方法,属性或函数的类称为“基类”。

class StudDetails {
   var stname: String!
   var mark1: Int!
   var mark2: Int!
   var mark3: Int!
   init(stname: String, mark1: Int, mark2: Int, mark3: Int) {
      self.stname = stname
      self.mark1 = mark1
      self.mark2 = mark2
      self.mark3 = mark3
   }
}
let stname = "Swift 4"
let mark1 = 98
let mark2 = 89
let mark3 = 76
print(stname)
print(mark1)
print(mark2)
print(mark3)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Swift 4
98
89
76

具有classname StudDetails的类在此定义为基类,用于包含学生姓名,三个主题标记为mark1,mark2和mark3。 'let'关键字用于初始化基类的值,基类值在'print'功能的帮助下显示在操场中。

Subclass

将新类基于现有类的行为定义为“子类”。 子类继承其基类的属性,方法和函数。 在基类名称之前使用定义子类':'

class StudDetails {
   var mark1: Int;
   var mark2: Int;
   init(stm1:Int, results stm2:Int) {
      mark1 = stm1;
      mark2 = stm2;
   }
   func print() {
      print("Mark1:\(mark1), Mark2:\(mark2)")
   }
}
class display : StudDetails {
   init() {
      super.init(stm1: 93, results: 89)
   }
}
let marksobtained = display()
marksobtained.print()

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Mark1:93, Mark2:89

类'StudDetails'被定义为超类,其中声明学生标记,子类'display'用于从其超类继承标记。 子类定义学生标记并调用print()方法来显示学生标记。

Overriding

访问超类实例,键入方法,实例,类型属性和下标子类提供了覆盖的概念。 'override'关键字用于覆盖超类中声明的方法。

访问超类方法,属性和下标

'super'关键字用作访问超类中声明的方法,属性和下标的前缀

Overriding 访问方法,属性和下标
Methodssuper.somemethod()
Propertiessuper.someProperty()
Subscriptssuper[someIndex]

方法覆盖

继承的实例和类型方法可以被'override'关键字覆盖到我们子类中定义的方法。 这里在子类中重写print()以访问超类print()中提到的type属性。 另外,cricket()超类的新实例被创建为'cricinstance'。

class cricket {
   func print() {
      print("Welcome to Swift 4 Super Class")
   }
}
class tennis: cricket {
   override func print() {
      print("Welcome to Swift 4 Sub Class")
   }
}
let cricinstance = cricket()
cricinstance.print()
let tennisinstance = tennis()
tennisinstance.print()

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Welcome to Swift Super Class
Welcome to Swift Sub Class

财产覆盖

您可以覆盖继承的实例或类属性,以便为该属性提供自己的自定义getter和setter,或者添加属性观察器以使覆盖属性能够在基础属性值更改时进行观察。

覆盖属性getter和setter

Swift 4允许用户提供自定义getter和setter来覆盖继承的属性,无论它是存储属性还是计算属性。 子类不知道继承的属性名称和类型。 因此,用户需要在子类中指定超类中指定的覆盖属性的名称和类型。

这可以通过两种方式完成 -

  • 当为覆盖属性定义setter时,用户也必须定义getter。

  • 当我们不想修改继承的属性getter时,我们可以简单地将继承的值通过语法'super.someProperty'传递给超类。

class Circle {
   var radius = 12.5
   var area: String {
      return "of rectangle for \(radius) "
   }
}
class Rectangle: Circle {
   var print = 7
   override var area: String {
      return super.area + " is now overridden as \(print)"
   }
}
let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Radius of rectangle for 25.0  is now overridden as 3

覆盖财产观察员

当需要为继承的属性添加新属性时,在Swift 4中引入了“属性覆盖”概念。这会在更改继承的属性值时通知用户。 但是重写不适用于继承的常量存储属性和继承的只读计算属性。

class Circle {
   var radius = 12.5
   var area: String {
     return "of rectangle for \(radius) "
   }
}
class Rectangle: Circle {
   var print = 7
   override var area: String {
      return super.area + " is now overridden as \(print)"
   }
}
let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")
class Square: Rectangle {
   override var radius: Double {
      didSet {
         print = Int(radius/5.0)+1
      }
   }
}
let sq = Square()
sq.radius = 100.0
print("Radius \(sq.area)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Radius of rectangle for 25.0  is now overridden as 3
Radius of rectangle for 100.0  is now overridden as 21

防止覆盖的最终财产

当用户不需要其他人访问超类方法,属性或下标Swift 4引入'final'属性以防止覆盖。 一旦'final'属性被声明,下标将不允许覆盖超类方法,属性及其下标。 没有规定在“超级class”中拥有“最终”财产。 当声明'final'属性时,限制用户创建更多子类。

final class Circle {
   final var radius = 12.5
   var area: String {
      return "of rectangle for \(radius) "
   }
}
class Rectangle: Circle {
   var print = 7
   override var area: String {
      return super.area + " is now overridden as \(print)"
   }
}
let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")
class Square: Rectangle {
   override var radius: Double {
      didSet {
         print = Int(radius/5.0)+1
      }
   }
}
let sq = Square()
sq.radius = 100.0
print("Radius \(sq.area)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

<stdin>:14:18: error: var overrides a 'final' var
override var area: String {
^
<stdin>:7:9: note: overridden declaration is here
var area: String {
^
<stdin>:12:11: error: inheritance from a final class 'Circle'
class Rectangle: Circle {
^
<stdin>:25:14: error: var overrides a 'final' var
override var radius: Double {
^
<stdin>:6:14: note: overridden declaration is here
final var radius = 12.5

由于超类被声明为'final'并且其数据类型也被声明为'final',因此程序将不允许进一步创建子类,并且它将抛出错误。

Swift - Initialization

在Swift 4中声明的类,结构和枚举被初始化以准备类的实例。 为存储的属性初始化初始值,对于新实例也初始化值,初始化值以进一步继续。 创建初始化函数的关键字由'init()'方法执行。 Swift 4初始化程序与Objective-C的不同之处在于它不返回任何值。 它的功能是在处理之前检查新创建的实例的初始化。 Swift 4还提供了“取消初始化”过程,用于在取消分配实例后执行内存管理操作。

存储属性的初始化程序角色

存储属性必须在处理实例之前初始化其类和结构的实例。 存储的属性使用初始化程序来分配和初始化值,从而消除了调用属性观察者的需要。 初始化程序用于存储属性

  • 创建初始值。

  • 在属性定义中指定默认属性值。

  • 要初始化特定数据类型的实例,请使用'init()'。 init()函数内没有传递参数。

语法 (Syntax)

init() {
   //New Instance initialization goes here
}

例子 (Example)

struct rectangle {
   var length: Double
   var breadth: Double
   init() {
      length = 6
      breadth = 12
   }
}
var area = rectangle()
print("area of rectangle is \(area.length*area.breadth)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

area of rectangle is 72.0

这里结构'rectangle'被初始化为成员长度和宽度为'Double'数据类型。 Init()方法用于初始化新创建的成员长度和double的值。 通过调用矩形函数计算并返回矩形区域。

默认设置属性值

Swift 4语言提供Init()函数来初始化存储的属性值。 此外,用户可以在声明类或结构成员时默认初始化属性值。 当属性在整个程序中单独使用相同的值时,我们可以单独在声明部分声明它,而不是在init()中初始化它。 默认情况下,设置属性值会在为类或结构定义继承时启用用户。

struct rectangle {
   var length = 6
   var breadth = 12
}
var area = rectangle()
print("area of rectangle is \(area.length*area.breadth)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

area of rectangle is 72

这里不是在init()中声明长度和宽度,而是在声明本身中初始化值。

参数初始化

在Swift 4语言中,用户可以使用init()初始化参数作为初始化程序定义的一部分。

struct Rectangle {
   var length: Double
   var breadth: Double
   var area: Double
   init(fromLength length: Double, fromBreadth breadth: Double) {
      self.length = length
      self.breadth = breadth
      area = length * breadth
   }
   init(fromLeng leng: Double, fromBread bread: Double) {
      self.length = leng
      self.breadth = bread
      area = leng * bread
   }
}
let ar = Rectangle(fromLength: 6, fromBreadth: 12)
print("area is: \(ar.area)")
let are = Rectangle(fromLeng: 36, fromBread: 12)
print("area is: \(are.area)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

area is: 72.0
area is: 432.0

本地和外部参数

初始化参数具有与函数和方法参数类似的本地和全局参数名称。 本地参数声明用于在初始化体内访问,外部参数声明用于调用初始化器。 Swift 4初始化器与函数和方法初始化器不同,它们不识别哪个初始化器用于调用哪些函数。

为了解决这个问题,Swift 4为init()中的每个参数引入了一个自动外部名称。 此自动外部名称与在每个初始化参数之前写入的本地名称等效。

struct Days {
   let sunday, monday, tuesday: Int
   init(sunday: Int, monday: Int, tuesday: Int) {
      self.sunday = sunday
      self.monday = monday
      self.tuesday = tuesday
   }
   init(daysofaweek: Int) {
      sunday = daysofaweek
      monday = daysofaweek
      tuesday = daysofaweek
   }
}
let week = Days(sunday: 1, monday: 2, tuesday: 3)
print("Days of a Week is: \(week.sunday)")
print("Days of a Week is: \(week.monday)")
print("Days of a Week is: \(week.tuesday)")
let weekdays = Days(daysofaweek: 4)
print("Days of a Week is: \(weekdays.sunday)")
print("Days of a Week is: \(weekdays.monday)")
print("Days of a Week is: \(weekdays.tuesday)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Days of a Week is: 1
Days of a Week is: 2
Days of a Week is: 3
Days of a Week is: 4
Days of a Week is: 4
Days of a Week is: 4

没有外部名称的参数

如果初始化下划线不需要外部名称,则使用“_”覆盖默认行为。

struct Rectangle {
   var length: Double
   init(frombreadth breadth: Double) {
      length = breadth * 10
   }
   init(frombre bre: Double) {
      length = bre * 30
   }
   init(_ area: Double) {
      length = area
   }
}
let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")
let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")
let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

area is: 180.0
area is: 370.0
area is: 110.0

可选的属性类型

当某个实例的stored属性没有返回任何值时,该属性被声明为'optional'类型,表明该特定类型返回'no value'。 当stored属性声明为'optional'时,它会在初始化过程中自动将值初始化为'nil'。

struct Rectangle {
   var length: Double?
   init(frombreadth breadth: Double) {
      length = breadth * 10
   }
   init(frombre bre: Double) {
      length = bre * 30
   }
   init(_ area: Double) {
      length = area
   }
}
let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")
let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")
let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

area is: Optional(180.0)
area is: Optional(370.0)
area is: Optional(110.0)

初始化期间修改常量属性

初始化还允许用户修改常量属性的值。 在初始化期间,class属性允许其类实例由超类而不是子类修改。 例如,在前一个程序中考虑'length'在主类中声明为'variable'。 以下程序变量'length'被修改为'constant'变量。

struct Rectangle {
   let length: Double?
   init(frombreadth breadth: Double) {
      length = breadth * 10
   }
   init(frombre bre: Double) {
      length = bre * 30
   }
   init(_ area: Double) {
      length = area
   }
}
let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")
let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")
let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

area is: Optional(180.0)
area is: Optional(370.0)
area is: Optional(110.0)

默认初始化器

默认初始值设定项为其所有声明的基类或结构属性提供一个新实例,并使用默认值。

class defaultexample {
   var studname: String?
   var stmark = 98
   var pass = true
}
var result = defaultexample()
print("result is: \(result.studname)")
print("result is: \(result.stmark)")
print("result is: \(result.pass)")

在使用操场运行上述程序的时候,得到以下的结果。 -

result is: nil
result is: 98
result is: true

上面的程序定义为类名为'defaultexample'。 默认情况下,三个成员函数被初始化为'studname?' 存储'nil'值,'stmark'为98,'pass'为布尔值'true'。 同样,在处理类成员类型之前,可以将类中的成员值初始化为default。

结构类型的成员初始化器

当用户不提供自定义初始化程序时,Swift 4中的结构类型将自动接收“成员初始化程序”。 它的主要功能是使用默认的成员初始化初始化新结构实例,然后将新实例属性按名称传递给成员初始化。

struct Rectangle {
   var length = 100.0, breadth = 200.0
}
let area = Rectangle(length: 24.0, breadth: 32.0)
print("Area of rectangle is: \(area.length)")
print("Area of rectangle is: \(area.breadth)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Area of rectangle is: 24.0
Area of rectangle is: 32.0

在初始化期间,结构初始化为其成员函数,初始化为'length'为'100.0','breadth'为'200.0'。 但是在处理变量长度和宽度期间,值被覆盖为24.0和32.0。

值类型的初始化程序委派

初始化程序委派定义为从其他初始化程序调用初始化程序。 它的主要功能是充当可重用性,以避免跨多个初始化程序的代码重复。

struct Stmark {
   var mark1 = 0.0, mark2 = 0.0
}
struct stdb {
   var m1 = 0.0, m2 = 0.0
}
struct block {
   var average = stdb()
   var result = Stmark()
   init() {}
   init(average: stdb, result: Stmark) {
      self.average = average
      self.result = result
   }
   init(avg: stdb, result: Stmark) {
      let tot = avg.m1 - (result.mark1/2)
      let tot1 = avg.m2 - (result.mark2/2)
      self.init(average: stdb(m1: tot, m2: tot1), result: result)
   }
}
let set1 = block()
print("student result is: \(set1.average.m1, set1.average.m2)
\(set1.result.mark1, set1.result.mark2)")
let set2 = block(average: stdb(m1: 2.0, m2: 2.0),
result: Stmark(mark1: 5.0, mark2: 5.0))
print("student result is: \(set2.average.m1, set2.average.m2)
\(set2.result.mark1, set2.result.mark2)")
let set3 = block(avg: stdb(m1: 4.0, m2: 4.0),
result: Stmark(mark1: 3.0, mark2: 3.0))
print("student result is: \(set3.average.m1, set3.average.m2)
\(set3.result.mark1, set3.result.mark2)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

(0.0,0.0) (0.0,0.0)
(2.0,2.0) 5.0,5.0)
(2.5,2.5) (3.0,3.0)

初始化程序委派规则

价值类型 class类型
结构和枚举等值类型不支持继承。 引用其他初始化器是通过self.init完成的 支持继承。 检查所有存储的属性值是否已初始化

类继承和初始化

类类型有两种初始化程序,用于检查定义的存储属性是否接收初始值,即指定的初始化程序和便捷初始化程序。

指定的初始化器和便捷初始化器

指定初始化程序 便利初始化器
被视为一个类的主要初始化 被视为支持类的初始化
初始化所有类属性,并调用适当的超类初始化程序以进行进一步初始化 使用便捷初始化程序调用指定的初始化程序,以便为特定用例或输入值类型创建类实例
为每个类定义至少一个指定的初始化程序 当类不需要初始化器时,不需要强制定义便利初始化器。
Init(parameters) { statements } 便利init(参数){statements}

指定初始化程序

class mainClass {
   var no1 : Int // local storage
   init(no1 : Int) {
      self.no1 = no1 // initialization
   }
}
class subClass : mainClass {
   var no2 : Int // new subclass storage
   init(no1 : Int, no2 : Int) {
      self.no2 = no2 // initialization
      super.init(no1:no1) // redirect to superclass
   }
}
let res = mainClass(no1: 10)
let print = subClass(no1: 10, no2: 20)
print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

res is: 10
res is: 10
res is: 20

便利初始化程序

class mainClass {
   var no1 : Int // local storage
   init(no1 : Int) {
      self.no1 = no1 // initialization
   }
}
class subClass : mainClass {
   var no2 : Int
   init(no1 : Int, no2 : Int) {
      self.no2 = no2
      super.init(no1:no1)
   }
   // Requires only one parameter for convenient method
   override convenience init(no1: Int) {
      self.init(no1:no1, no2:0)
   }
}
let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)
print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

res is: 20
res is: 30
res is: 50

初始化器继承和覆盖

默认情况下,Swift 4不允许其子类为其成员类型继承其超类初始值设定项。 继承仅在某种程度上适用于超类初始值设定项,这将在自动初始化程序继承中讨论。

当用户需要在超类中定义初始化器时,具有初始化器的子类必须由用户定义为自定义实现。 当子类必须重写超类'override'时,必须声明关键字。

class sides {
   var corners = 4
   var description: String {
      return "\(corners) sides"
   }
}
let rectangle = sides()
print("Rectangle: \(rectangle.description)")
class pentagon: sides {
   override init() {
      super.init()
      corners = 5
   }
}
let bicycle = pentagon()
print("Pentagon: \(bicycle.description)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Rectangle: 4 sides
Pentagon: 5 sides

行动中的指定和便利初始化器

class Planet {
   var name: String
   init(name: String) {
      self.name = name
   }
   convenience init() {
      self.init(name: "[No Planets]")
   }
}
let plName = Planet(name: "Mercury")
print("Planet name is: \(plName.name)")
let noplName = Planet()
print("No Planets like that: \(noplName.name)")
class planets: Planet {
   var count: Int
   init(name: String, count: Int) {
      self.count = count
      super.init(name: name)
   }
   override convenience init(name: String) {
      self.init(name: name, count: 1)
   }
}

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Planet name is: Mercury
No Planets like that: [No Planets]

可用的初始化程序

在定义类,结构或枚举值时,如果有任何初始化程序失败,则必须通知用户。 由于以下情况,变量初始化有时会失败

  • 参数值无效。
  • 缺少必需的外部来源。
  • 防止初始化成功的条件。

为了捕获初始化方法抛出的异常,Swift 4生成一个名为“failable initializer”的灵活初始化,以通知用户在初始化结构,类或枚举成员时不会注意到某些内容。 捕获可用初始化程序的关键字是'init?'。 此外,不能使用相同的参数类型和名称定义可用和不可用的初始值设定项。

struct studrecord {
   let stname: String
   init?(stname: String) {
      if stname.isEmpty {return nil }
      self.stname = stname
   }
}
let stmark = studrecord(stname: "Swing")
if let name = stmark {
   print("Student name is specified")
}
let blankname = studrecord(stname: "")
if blankname == nil {
   print("Student name is left blank")
}

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Student name is specified
Student name is left blank

枚举的可用初始化程序

Swift 4语言提供了枚举的Failable初始值设定器的灵活性,以便在枚举成员离开初始化值时通知用户。

enum functions {
   case a, b, c, d
   init?(funct: String) {
      switch funct {
      case "one":
         self = .a
      case "two":
         self = .b
      case "three":
         self = .c
      case "four":
         self = .d
      default:
         return nil
      }
   }
}
let result = functions(funct: "two")
if result != nil {
   print("With In Block Two")
}
let badresult = functions(funct: "five")
if badresult == nil {
   print("Block Does Not Exist")
}

当我们使用游乐场运行上述程序时,我们得到以下结果 -

With In Block Two
Block Does Not Exist

适用于类的初始化程序

使用枚举和结构声明时,可用的初始化程序会在其实现中的任何情况下警告初始化失败。 但是,类中的可用初始化程序仅在存储的属性设置为初始值后才会警告失败。

class studrecord {
   let studname: String!
   init?(studname: String) {
      self.studname = studname
      if studname.isEmpty { return nil }
   }
}
if let stname = studrecord(studname: "Failable Initializers") {
   print("Module is \(stname.studname)")
}

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Module is Optional("Failable Initializers")

覆盖可用的初始化程序

与初始化一样,用户也可以覆盖子类中的超类可用初始化程序。 超类可用的初始化也可以在子类不可用的初始化器中被覆盖。

当使用不可用的子类初始化覆盖可用的超类初始化程序时,子类初始化程序无法委托超类初始化程序。

不可用的初始化程序永远不能委托给可用的初始化程序。

下面给出的程序描述了可用的和不可用的初始化器。

class Planet {
   var name: String
   init(name: String) {
      self.name = name
   }
   convenience init() {
      self.init(name: "[No Planets]")
   }
}
let plName = Planet(name: "Mercury")
print("Planet name is: \(plName.name)")
let noplName = Planet()
print("No Planets like that: \(noplName.name)")
class planets: Planet {
   var count: Int
   init(name: String, count: Int) {
      self.count = count
      super.init(name: name)
   }
   override convenience init(name: String) {
      self.init(name: name, count: 1)
   }
}

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Planet name is: Mercury
No Planets like that: [No Planets]

初学者! 可用的初始化程序

Swift 4提供'init?' 定义一个可选的实例failable初始化程序。 定义特定类型“init!”的隐式解包的可选实例 已指定。

struct studrecord {
let stname: String
   init!(stname: String) {
      if stname.isEmpty {return nil }
      self.stname = stname
   }
}
let stmark = studrecord(stname: "Swing")
if let name = stmark {
   print("Student name is specified")
}
let blankname = studrecord(stname: "")
if blankname == nil {
   print("Student name is left blank")
}

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Student name is specified
Student name is left blank

必需的初始化程序

要声明初始化'required'关键字的每个子类需要在init()函数之前定义。

class classA {
   required init() {
      var a = 10
      print(a)
   }
}
class classB: classA {
   required init() {
      var b = 30
      print(b)
   }
}
let res = classA()
let print = classB()

当我们使用游乐场运行上述程序时,我们得到以下结果 -

10
30
10

Swift - Deinitialization

在需要释放类实例之前,必须调用“deinitializer”来释放内存空间。 关键字'deinit'用于释放系统资源占用的内存空间。 取消初始化仅适用于class类型。

取消分配内存空间的去初始化

当不再需要实例时,Swift 4会自动释放您的实例,以释放资源。 Swift 4通过自动引用计数(ARC)处理实例的内存管理,如自动引用计数中所述。 通常,在取消分配实例时,您无需执行手动清理。 但是,当您使用自己的资源时,可能需要自己执行一些额外的清理工作。 例如,如果创建自定义类以打开文件并向其写入一些数据,则可能需要在取消分配类实例之前关闭该文件。

var counter = 0; // for reference counting
class baseclass {
   init() {
      counter++;
   }
   deinit {
      counter--;
   }
}
var print: baseclass? = baseclass()
print(counter)
print = nil
print(counter)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

1
0

当省略print = nil语句时,计数器的值保持不变,因为它未被取消初始化。

var counter = 0; // for reference counting
class baseclass {
   init() {
      counter++;
   }
   deinit {
      counter--;
   }
}
var print: baseclass? = baseclass()
print(counter)
print(counter)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

1
1

Swift - ARC Overview

内存管理功能及其用法通过自动引用计数(ARC)以Swift 4语言处理。 ARC用于初始化和取消初始化系统资源,从而在不再需要实例时释放类实例使用的内存空间。 ARC会跟踪有关代码实例之间关系的信息,以便有效地管理内存资源。

ARC的功能

  • ARC分配一块内存来存储每次init()创建新类实例时的信息。

  • 有关实例类型及其值的信息存储在内存中。

  • 当不再需要类实例时,它会通过deinit()自动释放内存空间,以进行进一步的类实例存储和检索。

  • ARC跟踪当前引用的类实例属性,常量和变量,以便deinit()仅应用于那些未使用的实例。

  • ARC保持对那些类实例属性,常量和变量的“强引用”,以在当前使用类实例时限制释放。

ARC计划

class StudDetails {
   var stname: String!
   var mark: Int!
   init(stname: String, mark: Int) {
      self.stname = stname
      self.mark = mark
   }
   deinit {
      print("Deinitialized \(self.stname)")
      print("Deinitialized \(self.mark)")
   }
}
let stname = "Swift 4"
let mark = 98
print(stname)
print(mark)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Swift 4
98

ARC强引用循环类实例

class studmarks {
   let name: String
   var stud: student?
   init (name: String) {
      print("Initializing: \(name)")
      self.name = name
   }
   deinit {
      print("Deallocating: \(self.name)")
   }
}
class student {
   let name: String
   var strname: studmarks?
   init (name: String) {
      print("Initializing: \(name)")
      self.name = name
   }
   deinit {
      print("Deallocating: \(self.name)")
   }
}
var shiba: studmarks?
var mari: student?
shiba = studmarks(name: "Swift 4")
mari = student(name: "ARC")
shiba!.stud = mari
mari!.strname = shiba

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Initializing: Swift 4
Initializing: ARC

ARC弱和无主参考

类类型属性有两种方法可以解决强引用周期 -

  • Weak References
  • Unowned References

这些引用用于使一个实例能够引用参考周期中的其他实例。 然后,实例可以参考每个实例而不是关注强参考循环。 当用户知道某个实例可能返回'nil'值时,我们可能会指出使用弱引用。 当实例返回某些内容而不是nil时,则使用无主引用声明它。

弱参考计划

class module {
   let name: String
   init(name: String) { self.name = name }
   var sub: submodule?
   deinit { print("\(name) Is The Main Module") }
}
class submodule {
   let number: Int
   init(number: Int) { self.number = number }
   weak var topic: module?
   deinit { print("Sub Module with its topic number is \(number)") }
}
var toc: module?
var list: submodule?
toc = module(name: "ARC")
list = submodule(number: 4)
toc!.sub = list
list!.topic = toc
toc = nil
list = nil

当我们使用游乐场运行上述程序时,我们得到以下结果 -

ARC Is The Main Module
Sub Module with its topic number is 4

无主参考计划

class student {
   let name: String
   var section: marks?
   init(name: String) {
      self.name = name
   }
   deinit { print("\(name)") }
}
class marks {
   let marks: Int
   unowned let stname: student
   init(marks: Int, stname: student) {
      self.marks = marks
      self.stname = stname
   }
   deinit { print("Marks Obtained by the student is \(marks)") }
}
var module: student?
module = student(name: "ARC")
module!.section = marks(marks: 98, stname: module!)
module = nil

当我们使用游乐场运行上述程序时,我们得到以下结果 -

ARC
Marks Obtained by the student is 98

闭包的强参考周期

当我们为类实例属性和闭包的主体分配闭包以捕获特定实例时,可能会发生强引用循环。 对闭包的强引用由'self.someProperty'或'self.someMethod()'定义。 强引用循环用作闭包的引用类型。

class HTMLElement {
   let samplename: String
   let text: String?
   lazy var asHTML: () -> String = {
      if let text = self.text {
         return "<\(self.samplename)>\(text)</\(self.samplename)>"
      } else {
         return "<\(self.samplename) />"
      }
   }
   init(samplename: String, text: String? = nil) {
      self.samplename = samplename
      self.text = text
   }
   deinit {
      print("\(samplename) is being deinitialized")
   }
}
var paragraph: HTMLElement? = HTMLElement(samplename: "p", text: "Welcome to Closure SRC")
print(paragraph!.asHTML())

当我们使用游乐场运行上述程序时,我们得到以下结果 -

<p>Welcome to Closure SRC</p>

弱和无主参考

当闭包和实例相互引用时,用户可以将闭包中的捕获定义为无主参考。 然后它不允许用户同时解除分配实例。 当实例有时返回'nil'值时,用弱实例定义闭包。

class HTMLElement {
   let module: String
   let text: String?
   lazy var asHTML: () -> String = {
      [unowned self] in
      if let text = self.text {
         return "<\(self.module)>\(text)</\(self.module)>"
      } else {
         return "<\(self.module) />"
      }
   }
   init(module: String, text: String? = nil) {
      self.module = module
      self.text = text
   }
   deinit {
      print("\(module) the deinit()")
   }
}
var paragraph: HTMLElement? = HTMLElement(module: "Inside", text: "ARC Weak References")
print(paragraph!.asHTML())
paragraph = nil

当我们使用游乐场运行上述程序时,我们得到以下结果 -

<Inside>ARC Weak References</Inside>
Inside the deinit()

Swift - Optional Chaining

在可选的“nil”上查询,调用属性,下标和方法的过程被定义为可选链接。 可选链接返回两个值 -

  • 如果可选项包含'value',则调用其相关属性,方法和下标返回值

  • 如果可选项包含'nil'值,则其所有相关属性,方法和下标返回nil

由于对方法,属性和下标的多个查询被组合在一起,因此对一个链的失败将影响整个链并导致'nil'值。

可选链接作为强制解包的替代方法

在带有'?'的可选值后指定可选链接 在可选值返回某些值时调用属性,方法或下标。

Optional Chaining '?' 访问方法,属性和下标可选链接'!' 强行展开
? 在可选值之后放置调用属性,方法或下标 ! 放在可选值之后调用属性,方法或下标来强制展开值
当可选项为'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

通过创建名为“circname”的实例来调用circle()子类中声明的函数circleprint()。 如果函数包含某个值,则该函数将返回一个值,否则它将通过检查语句'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]] 。 然后将下标值更改为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.")
}

当我们使用游乐场运行上述程序时,我们得到以下结果 -

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

Swift - Type Casting

要验证实例的类型'Type Casting'在Swift 4语言中发挥作用。 它用于检查实例类型是属于特定的超类还是子类,还是在自己的层次结构中定义。

Swift 4类型转换提供两个运算符'is'来检查值的类型和'as',并将类型值转换为不同的类型。 类型转换还检查实例类型是否遵循特定的协议一致性标准。

定义类层次结构

类型转换用于检查实例的类型,以确定它是否属于特定的类类型。 此外,它还检查类及其子类的层次结构,以检查并转换这些实例,使其成为同一层次结构。

class Subjects {
   var physics: String
   init(physics: String) {
      self.physics = physics
   }
}
class Chemistry: Subjects {
   var equations: String
   init(physics: String, equations: String) {
      self.equations = equations
      super.init(physics: physics)
   }
}
class Maths: Subjects {
   var formulae: String
   init(physics: String, formulae: String) {
      self.formulae = formulae
      super.init(physics: physics)
   }
}
let sa = [ Chemistry(physics: "solid physics", equations: "Hertz"),
   Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")]
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz

类型检查

使用'is'运算符完成类型检查。 'is'类型检查运算符检查实例是否属于特定的子类类型,如果它属于该实例则返回'true',否则它将返回'false'。

class Subjects {
   var physics: String
   init(physics: String) {
      self.physics = physics
   }
}
class Chemistry: Subjects {
   var equations: String
   init(physics: String, equations: String) {
      self.equations = equations
      super.init(physics: physics)
   }
}
class Maths: Subjects {
   var formulae: String
   init(physics: String, formulae: String) {
      self.formulae = formulae
      super.init(physics: physics)
   }
}
let sa = [
   Chemistry(physics: "solid physics", equations: "Hertz"),
   Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
   Chemistry(physics: "Thermo physics", equations: "Decibels"),
   Maths(physics: "Astro Physics", formulae: "MegaHertz"),
   Maths(physics: "Differential Equations", formulae: "Cosine Series")]
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")
var chemCount = 0
var mathsCount = 0
for item in sa {
   if item is Chemistry {
      ++chemCount
   } else if item is Maths {
      ++mathsCount
   }
}
print("Subjects in chemistry contains \(chemCount) topics and maths contains \(mathsCount) topics")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Subjects in chemistry contains 2 topics and maths contains 3 topics

Downcasting

向下转换子类类型可以使用两个运算符(作为?和!)。'作为?' 当值返回nil时返回可选值。 它用于检查成功的向下倾斜。

'如!' 当向下转换返回nil值时,返回force unwrapping,如可选链接中所讨论的那样。 它用于在发生转发故障时触发运行时错误

class Subjects {
   var physics: String
   init(physics: String) {
      self.physics = physics
   }
}
class Chemistry: Subjects {
   var equations: String
   init(physics: String, equations: String) {
      self.equations = equations
      super.init(physics: physics)
   }
}
class Maths: Subjects {
   var formulae: String
   init(physics: String, formulae: String) {
      self.formulae = formulae
      super.init(physics: physics)
   }
}
let sa = [
   Chemistry(physics: "solid physics", equations: "Hertz"),
   Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
   Chemistry(physics: "Thermo physics", equations: "Decibels"),
   Maths(physics: "Astro Physics", formulae: "MegaHertz"),
   Maths(physics: "Differential Equations", formulae: "Cosine Series")]
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")
var chemCount = 0
var mathsCount = 0
for item in sa {
   if let print = item as? Chemistry {
      print("Chemistry topics are: '\(print.physics)', \(print.equations)")
   } else if let example = item as? Maths {
      print("Maths topics are: '\(example.physics)', \(example.formulae)")
   }
}

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Chemistry topics are: 'solid physics', Hertz
Maths topics are: 'Fluid Dynamics', Giga Hertz
Chemistry topics are: 'Thermo physics', Decibels
Maths topics are: 'Astro Physics', MegaHertz
Maths topics are: 'Differential Equations', Cosine Series

类型转换:任何和任何对象

关键字“Any”用于表示属于包括函数类型在内的任何类型的实例。

class Subjects {
   var physics: String
   init(physics: String) {
      self.physics = physics
   }
}
class Chemistry: Subjects {
   var equations: String
   init(physics: String, equations: String) {
      self.equations = equations
      super.init(physics: physics)
   }
}
class Maths: Subjects {
   var formulae: String
   init(physics: String, formulae: String) {
      self.formulae = formulae
      super.init(physics: physics)
   }
}
let sa = [
   Chemistry(physics: "solid physics", equations: "Hertz"),
   Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
   Chemistry(physics: "Thermo physics", equations: "Decibels"),
   Maths(physics: "Astro Physics", formulae: "MegaHertz"),
   Maths(physics: "Differential Equations", formulae: "Cosine Series")]
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")
var chemCount = 0
var mathsCount = 0
for item in sa {
   if let print = item as? Chemistry {
      print("Chemistry topics are: '\(print.physics)', \(print.equations)")
   } else if let example = item as? Maths {
      print("Maths topics are: '\(example.physics)', \(example.formulae)")
   }
}
var exampleany = [Any]()
exampleany.append(12)
exampleany.append(3.14159)
exampleany.append("Example for Any")
exampleany.append(Chemistry(physics: "solid physics", equations: "Hertz"))
for print in exampleany {
   switch print {
      case let someInt as Int:
         print("Integer value is \(someInt)")
      case let someDouble as Double where someDouble > 0:
         print("Pi value is \(someDouble)")
      case let someString as String:
         print("\(someString)")
      case let phy as Chemistry:   
         print("Topics '\(phy.physics)', \(phy.equations)")
      default:
         print("None")
   }
}

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Chemistry topics are: 'solid physics', Hertz
Maths topics are: 'Fluid Dynamics', Giga Hertz
Chemistry topics are: 'Thermo physics', Decibels
Maths topics are: 'Astro Physics', MegaHertz
Maths topics are: 'Differential Equations', Cosine Series
Integer value is 12
Pi value is 3.14159
Example for Any
Topics 'solid physics', Hertz

AnyObject (AnyObject)

要表示任何类类型的实例,请使用“AnyObject”关键字。

class Subjects {
   var physics: String
   init(physics: String) {
      self.physics = physics
   }
}
class Chemistry: Subjects {
   var equations: String
   init(physics: String, equations: String) {
      self.equations = equations
      super.init(physics: physics)
   }
}
class Maths: Subjects {
   var formulae: String
   init(physics: String, formulae: String) {
      self.formulae = formulae
      super.init(physics: physics)
   }
}
let saprint: [AnyObject] = [Chemistry(physics: "solid physics", equations: "Hertz"),
   Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
   Chemistry(physics: "Thermo physics", equations: "Decibels"),
   Maths(physics: "Astro Physics", formulae: "MegaHertz"),
   Maths(physics: "Differential Equations", formulae: "Cosine Series")]
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")
var chemCount = 0
var mathsCount = 0
for item in saprint {
   if let print = item as? Chemistry {
      print("Chemistry topics are: '\(print.physics)', \(print.equations)")
   } else if let example = item as? Maths {
      print("Maths topics are: '\(example.physics)', \(example.formulae)")
   }
}
var exampleany = [Any]()
exampleany.append(12)
exampleany.append(3.14159)
exampleany.append("Example for Any")
exampleany.append(Chemistry(physics: "solid physics", equations: "Hertz"))
for print in exampleany {
   switch print {
      case let someInt as Int:
         print("Integer value is \(someInt)")
      case let someDouble as Double where someDouble > 0:
         print("Pi value is \(someDouble)")
      case let someString as String:
         print("\(someString)")
      case let phy as Chemistry:
         print("Topics '\(phy.physics)', \(phy.equations)")
      default:
         print("None")
   }
}

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Chemistry topics are: 'solid physics', Hertz
Maths topics are: 'Fluid Dynamics', Giga Hertz
Chemistry topics are: 'Thermo physics', Decibels
Maths topics are: 'Astro Physics', MegaHertz
Maths topics are: 'Differential Equations', Cosine Series
Integer value is 12
Pi value is 3.14159
Example for Any
Topics 'solid physics', Hertz

Swift - Extensions

可以在扩展的帮助下添加现有类,结构或枚举类型的功能。 可以使用扩展添加类型功能,但扩展无法覆盖功能。

Swift Extension Functionalities -

  • 添加计算属性和计算类型属性
  • 定义实例和类型方法。
  • 提供新的初始化程序。
  • 定义下标
  • 定义和使用新的嵌套类型
  • 使现有类型符合协议

使用关键字“extension”声明扩展名

语法 (Syntax)

extension SomeType {
   // new functionality can be added here
}

现有类型也可以添加扩展,使其成为协议标准,其语法类似于类或结构。

extension SomeType: SomeProtocol, AnotherProtocol {
   // protocol requirements is described here
}

计算属性

在扩展的帮助下,也可以扩展计算的“实例”和“类型”属性。

extension Int {
   var add: Int {return self + 100 }
   var sub: Int { return self - 10 }
   var mul: Int { return self * 10 }
   var div: Int { return self/5 }
}
let addition = 3.add
print("Addition is \(addition)")
let subtraction = 120.sub
print("Subtraction is \(subtraction)")
let multiplication = 39.mul
print("Multiplication is \(multiplication)")
let division = 55.div
print("Division is \(division)")
let mix = 30.add + 34.sub
print("Mixed Type is \(mix)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Addition is 103
Subtraction is 110
Multiplication is 390
Division is 11
Mixed Type is 154

初始化器(Initializers)

Swift 4提供了通过扩展向现有类型添加新初始化程序的灵活性。 用户可以添加自己的自定义类型来扩展已定义的类型,也可以使用其他初始化选项。 扩展仅支持init()。 扩展不支持deinit()。

struct sum {
   var num1 = 100, num2 = 200
}
struct diff {
   var no1 = 200, no2 = 100
}
struct mult {
   var a = sum()
   var b = diff()
}
let calc = mult()
print ("Inside mult block \(calc.a.num1, calc.a.num2)")
print("Inside mult block \(calc.b.no1, calc.b.no2)")
let memcalc = mult(a: sum(num1: 300, num2: 500),b: diff(no1: 300, no2: 100))
print("Inside mult block \(memcalc.a.num1, memcalc.a.num2)")
print("Inside mult block \(memcalc.b.no1, memcalc.b.no2)")
extension mult {
   init(x: sum, y: diff) {
      let X = x.num1 + x.num2
      let Y = y.no1 + y.no2
   }
}
let a = sum(num1: 100, num2: 200)
print("Inside Sum Block:\( a.num1, a.num2)")
let b = diff(no1: 200, no2: 100)
print("Inside Diff Block: \(b.no1, b.no2)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Inside mult block (100, 200)
Inside mult block (200, 100)
Inside mult block (300, 500)
Inside mult block (300, 100)
Inside Sum Block:(100, 200)
Inside Diff Block: (200, 100)

方法 (Methods)

借助扩展,可以在子类中进一步添加新的实例方法和类型方法。

extension Int {
   func topics(summation: () -> ()) {
      for _ in 0..<self {
         summation()
      }
   }
}
4.topics(summation: {
   print("Inside Extensions Block")
})
3.topics(summation: {
   print("Inside Type Casting Block")
})

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Inside Extensions Block
Inside Extensions Block
Inside Extensions Block
Inside Extensions Block
Inside Type Casting Block
Inside Type Casting Block
Inside Type Casting Block

topics()函数接受类型'(summation:()→())'的参数,以指示函数不接受任何参数,并且它不会返回任何值。 要多次调用该函数,初始化块,并初始化对topic()的方法的调用。

变异实例方法

声明为扩展时,实例方法也可以变异。

修改self或其属性的结构和枚举方法必须将实例方法标记为变异,就像从原始实现中改变方法一样。

extension Double {
   mutating func square() {
      let pi = 3.1415
      self = pi * self * self
   }
}
var Trial1 = 3.3
Trial1.square()
print("Area of circle is: \(Trial1)")
var Trial2 = 5.8
Trial2.square()
print("Area of circle is: \(Trial2)")
var Trial3 = 120.3
Trial3.square()
print("Area of circle is: \(Trial3)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Area of circle is: 34.210935
Area of circle is: 105.68006
Area of circle is: 45464.070735

Subscripts

通过扩展也可以向已声明的实例添加新的下标。

extension Int {
   subscript(var multtable: Int) -> Int {
      var no1 = 1
      while multtable > 0 {
         no1 *= 10
         --multtable
      }
      return (self/no1) % 10
   }
}
print(12[0])
print(7869[1])
print(786543[2])

当我们使用游乐场运行上述程序时,我们得到以下结果 -

2
6
5

嵌套类型

类,结构和枚举实例的嵌套类型也可以在扩展的帮助下进行扩展。

extension Int {
   enum calc {
      case add
      case sub
      case mult
      case div
      case anything
   }
   var print: calc {
      switch self {
         case 0:
            return .add
         case 1:
            return .sub
         case 2:
            return .mult
         case 3:
            return .div
         default:
            return .anything
      }
   }
}
func result(numb: [Int]) {
   for i in numb {
      switch i.print {
         case .add:
            print(" 10 ")
         case .sub:
            print(" 20 ")
         case .mult:
            print(" 30 ")
         case .div:
            print(" 40 ")
         default:
            print(" 50 ")
      }
   }
}
result(numb: [0, 1, 2, 3, 4, 7])

当我们使用游乐场运行上述程序时,我们得到以下结果 -

10
20
30
40
50
50

Swift - Protocols

协议为方法,属性和其他需求功能提供了蓝图。 它被描述为方法或属性骨架而不是实现。 通过定义类,函数和枚举,可以进一步完成方法和属性的实现。 协议的一致性被定义为满足协议要求的方法或属性。

语法 (Syntax)

协议也遵循与类,结构和枚举类似的语法 -

protocol SomeProtocol {
   // protocol definition 
}

协议在类,结构或枚举类型名称之后声明。 单个和多个协议声明也是可能的。 如果定义了多个协议,则必须用逗号分隔。

struct SomeStructure: Protocol1, Protocol2 {
   // structure definition 
}

当必须为超类定义协议时,协议名称应使用逗号跟随超类名称。

class SomeClass: SomeSuperclass, Protocol1, Protocol2 {
   // class definition 
}

属性和方法要求

协议用于指定特定的类类型属性或实例属性。 它只是单独指定类型或实例属性,而不是指定它是存储属性还是计算属性。 此外,它还用于指定属性是“gettable”还是“settable”。

属性需求由'var'关键字声明为属性变量。 {get set}用于在类型声明后声明gettable和settable属性。 {get}属性在类型声明后提到了Gettable。

protocol classa {
   var marks: Int { get set }
   var result: Bool { get }
   func attendance() -> String
   func markssecured() -> String
}
protocol classb: classa {
   var present: Bool { get set }
   var subject: String { get set }
   var stname: String { get set }
}
class classc: classb {
   var marks = 96
   let result = true
   var present = false
   var subject = "Swift 4 Protocols"
   var stname = "Protocols"
   func attendance() -> String {
      return "The \(stname) has secured 99% attendance"
   }
   func markssecured() -> String {
      return "\(stname) has scored \(marks)"
   }
}
let studdet = classc()
studdet.stname = "Swift 4"
studdet.marks = 98
studdet.markssecured()
print(studdet.marks)
print(studdet.result)
print(studdet.present)
print(studdet.subject)
print(studdet.stname)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

98
true
false
Swift 4 Protocols
Swift 4

变异方法要求

protocol daysofaweek {
   mutating func print()
}
enum days: daysofaweek {
   case sun, mon, tue, wed, thurs, fri, sat 
   mutating func print() {
      switch self {
         case sun:
            self = sun
            print("Sunday")
         case mon:
            self = mon
            print("Monday")
         case tue:
            self = tue
            print("Tuesday")
         case wed:
            self = wed
            print("Wednesday")
         case mon:
            self = thurs
            print("Thursday")
         case tue:
            self = fri
            print("Friday")
         case sat:
            self = sat
            print("Saturday")
         default:
            print("NO Such Day")
      }
   }
}
var res = days.wed
res.print()

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Wednesday

初始化程序要求

Swing允许用户初始化协议以遵循类似于普通初始化器的类型一致性。

语法 (Syntax)

protocol SomeProtocol {
   init(someParameter: Int)
}

例如 (For example)

protocol tcpprotocol {
   init(aprot: Int)
}

协议初始化程序要求的类实现

指定或便利初始化程序允许用户初始化协议以使其标准符合保留的“required”关键字。

class SomeClass: SomeProtocol {
   required init(someParameter: Int) {
      // initializer implementation statements
   }
}
protocol tcpprotocol {
   init(aprot: Int)
}
class tcpClass: tcpprotocol {
   required init(aprot: Int) {
   }
}

通过'required'修饰符确保所有子类的协议一致性,用于显式或继承实现。

当子类重写其超类初始化要求时,它由'override'修饰符关键字指定。

protocol tcpprotocol {
   init(no1: Int)
}
class mainClass {
   var no1: Int        // local storage
   init(no1: Int) {
      self.no1 = no1  // initialization
   }
}
class subClass: mainClass, tcpprotocol {
   var no2: Int
   init(no1: Int, no2 : Int) {
      self.no2 = no2
      super.init(no1:no1)
   }
   // Requires only one parameter for convenient method
   required override convenience init(no1: Int) {
      self.init(no1:no1, no2:0)
   }
}
let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)
print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

res is: 20
res is: 30
res is: 50

作为类型的协议

它们不是在协议中实现功能,而是用作函数,类,方法等的类型。

协议可以作为类型访问 -

  • 函数,方法或初始化为参数或返回类型

  • 常数,变量或属性

  • 数组,字典或其他容器作为项目

protocol Generator {
   typealias members
   func next() -> members?
}
var items = [10,20,30].generate()
while let x = items.next() {
   print(x)
}
for lists in map([1,2,3], {i in i*5}) {
   print(lists)
}
print([100,200,300])
print(map([1,2,3], {i in i*10}))

当我们使用游乐场运行上述程序时,我们得到以下结果 -

10
20
30
5
10
15
[100, 200, 300]
[10, 20, 30]

添加协议与扩展的一致性

通过使用扩展,可以采用现有类型并使其符合新协议。 借助扩展,可以将新属性,方法和下标添加到现有类型中。

protocol AgeClasificationProtocol {
   var age: Int { get }
   func agetype() -> String
}
class Person {
   let firstname: String
   let lastname: String
   var age: Int
   init(firstname: String, lastname: String) {
      self.firstname = firstname
      self.lastname = lastname
      self.age = 10
   }
}
extension Person : AgeClasificationProtocol {
   func fullname() -> String {
      var c: String
      c = firstname + " " + lastname
      return c
   }
   func agetype() -> String {
      switch age {
         case 0...2:
            return "Baby"
         case 2...12:
            return "Child"
         case 13...19:
            return "Teenager"
         case let x where x > 65:
            return "Elderly"
         default:
            return "Normal"
      }
   }
}

协议继承

Swift 4允许协议从其定义的属性继承属性。 它类似于类继承,但可以选择列出用逗号分隔的多个继承协议。

protocol classa {
   var no1: Int { get set }
   func calc(sum: Int)
}
protocol result {
   func print(target: classa)
}
class student2: result {
   func print(target: classa) {
      target.calc(sum: 1)
   }
}
class classb: result {
   func print(target: classa) {
      target.calc(sum: 5)
   }
}
class student: classa {
   var no1: Int = 10
   func calc(sum: Int) {
      no1 -= sum
      print("Student attempted \(sum) times to pass")
      if no1 <= 0 {
         print("Student is absent for exam")
      }
   }
}
class Player {
   var stmark: result!
   init(stmark: result) {
      self.stmark = stmark
   }
   func print(target: classa) {
      stmark.print(target: target)
   }
}
var marks = Player(stmark: student2())
var marksec = student()
marks.print(target: marksec)
marks.print(target: marksec)
marks.print(target: marksec)
marks.stmark = classb()
marks.print(target: marksec)
marks.print(target: marksec)
marks.print(target: marksec)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Student attempted 1 times to pass
Student attempted 1 times to pass
Student attempted 1 times to pass
Student attempted 5 times to pass
Student attempted 5 times to pass
Student is absent for exam
Student attempted 5 times to pass
Student is absent for exam

仅类协议

当定义协议并且用户想要用类定义协议时,应该通过首先定义类,然后是协议的继承列表来添加协议。

protocol tcpprotocol {
   init(no1: Int)
}
class mainClass {
   var no1: Int        // local storage
   init(no1: Int) {
      self.no1 = no1  // initialization
   }
}
class subClass: mainClass, tcpprotocol {
   var no2: Int
   init(no1: Int, no2 : Int) {
      self.no2 = no2
      super.init(no1:no1)
   }
   // Requires only one parameter for convenient method
   required override convenience init(no1: Int) {
      self.init(no1:no1, no2:0)
   }
}
let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)
print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

res is: 20
res is: 30
res is: 50

协议组成

Swift 4允许在协议组合的帮助下一次调用多个协议。

语法 (Syntax)

protocol<SomeProtocol, AnotherProtocol>

例子 (Example)

protocol stname {
   var name: String { get }
}
protocol stage {
   var age: Int { get }
}
struct Person: stname, stage {
   var name: String
   var age: Int
}
func print(celebrator: stname & stage) {
   print("\(celebrator.name) is \(celebrator.age) years old")
}
let studname = Person(name: "Priya", age: 21)
print(studname)
let stud = Person(name: "Rehan", age: 29)
print(stud)
let student = Person(name: "Roshan", age: 19)
print(student)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Person(name: "Priya", age: 21)
Person(name: "Rehan", age: 29)
Person(name: "Roshan", age: 19)

检查协议一致性

协议一致性由'is'和'as'运算符测试,类似于类型转换。

  • 如果实例符合协议标准,则is运算符返回true,如果失败则返回false。

  • as? downcast运算符的版本返回协议类型的可选值,如果实例不符合该协议,则此值为nil。

  • 如果向下转换操作符的as版本强制转发为协议类型,并且如果向下转换不成功则触发运行时错误。

import Foundation
@objc protocol rectangle {
   var area: Double { get }
}
@objc class Circle: rectangle {
   let pi = 3.1415927
   var radius: Double
   var area: Double { return pi * radius * radius }
   init(radius: Double) { self.radius = radius }
}
@objc class result: rectangle {
   var area: Double
   init(area: Double) { self.area = area }
}
class sides {
   var rectsides: Int
   init(rectsides: Int) { self.rectsides = rectsides }
}
let objects: [AnyObject] = [Circle(radius: 2.0),result(area:198),sides(rectsides: 4)]
for object in objects {
   if let objectWithArea = object as? rectangle {
      print("Area is \(objectWithArea.area)")
   } else {
      print("Rectangle area is not defined")
   }
}

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Area is 12.5663708
Area is 198.0
Rectangle area is not defined

Swift - Generics

Swift 4语言提供了“通用”功能来编写灵活且可重用的函数和类型。 泛型用于避免重复并提供抽象。 Swift 4标准库使用泛型代码构建。 Swift 4s'Arrays'和'Dictionary'类型属于泛型集合。 在数组和字典的帮助下,数组被定义为保存“Int”值和“String”值或任何其他类型。

func exchange(a: inout Int, b: inout Int) {
   let temp = a
   a = b
   b = temp
}
var numb1 = 100
var numb2 = 200
print("Before Swapping values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping values are: \(numb1) and \(numb2)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Before Swapping values are: 100 and 200
After Swapping values are: 200 and 100

通用函数:类型参数

通用函数可用于访问任何数据类型,如“Int”或“String”。

func exchange<T>(a: inout T, b: inout T) {
   let temp = a
   a = b
   b = temp
}
var numb1 = 100
var numb2 = 200
print("Before Swapping Int values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping Int values are: \(numb1) and \(numb2)")
var str1 = "Generics"
var str2 = "Functions"
print("Before Swapping String values are: \(str1) and \(str2)")
exchange(a: &str1, b: &str2)
print("After Swapping String values are: \(str1) and \(str2)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Before Swapping Int values are: 100 and 200
After Swapping Int values are: 200 and 100
Before Swapping String values are: Generics and Functions
After Swapping String values are: Functions and Generics

函数exchange()用于交换上述程序中描述的值,用作类型参数。 第一次调用函数exchange()返回'Int'值,第二次调用函数exchange()将返回'String'值。 多个参数类型可以包含在由逗号分隔的尖括号内。

类型参数被命名为用户定义,以了解它所包含的类型参数的用途。 Swift 4提供作为泛型类型参数名称。 但是,类型参数(如数组和字典)也可以命名为key,value以标识它们属于“Dictionary”类型。

struct TOS<T> {
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
}
var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Type Parameters")
print(tos.items)
tos.push(item: "Naming Type Parameters")
print(tos.items)
let deletetos = tos.pop()

当我们使用游乐场运行上述程序时,我们得到以下结果 -

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]

扩展通用类型

“extension”关键字包含扩展堆栈属性以了解项目顶部的内容。

struct TOS<T> {
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
}
var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Type Parameters")
print(tos.items)
tos.push(item: "Naming Type Parameters")
print(tos.items)
extension TOS {
   var first: T? {
      return items.isEmpty ? nil : items[items.count - 1]
   }
}
if let first = tos.first {
   print("The top item on the stack is \(first).")
}

当我们使用游乐场运行上述程序时,我们得到以下结果 -

["Swift 4"]
["Swift 4", "Generics"]
["Swift 4", "Generics", "Type Parameters"]
["Swift 4", "Generics", "Type Parameters", "Naming Type Parameters"]
The top item on the stack is Naming Type Parameters.

键入约束

Swift 4语言允许“类型约束”指定类型参数是继承自特定类,还是确保协议一致性标准。

func exchange<T>(a: inout T, b: inout T) {
   let temp = a
   a = b
   b = temp
}
var numb1 = 100
var numb2 = 200
print("Before Swapping Int values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping Int values are: \(numb1) and \(numb2)")
var str1 = "Generics"
var str2 = "Functions"
print("Before Swapping String values are: \(str1) and \(str2)")
exchange(a: &str1, b: &str2)
print("After Swapping String values are: \(str1) and \(str2)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Before Swapping Int values are: 100 and 200
After Swapping Int values are: 200 and 100
Before Swapping String values are: Generics and Functions
After Swapping String values are: Functions and Generics

相关类型

Swift 4允许通过关键字“associatedtype”在协议定义内声明关联类型。

protocol Container {
   associatedtype ItemType
   mutating func append(item: ItemType)
   var count: Int { get }
   subscript(i: Int) -> ItemType { get }
}
struct TOS<T>: Container {
   // original Stack<T> implementation
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
   // conformance to the Container protocol
   mutating func append(item: T) {
      self.push(item: item)
   }
   var count: Int {
      return items.count
   }
   subscript(i: Int) -> T {
      return items[i]
   }
}
var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Type Parameters")
print(tos.items)
tos.push(item: "Naming Type Parameters")
print(tos.items)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]

条款

类型约束使用户能够定义与通用函数或类型关联的类型参数的要求。 用于定义关联类型的要求'where'子句被声明为类型参数列表的一部分。 'where'关键字紧跟在类型参数列表之后,后跟关联类型的约束,类型和关联类型之间的相等关系。

protocol Container {
   associatedtype ItemType
   mutating func append(item: ItemType)
   var count: Int { get }
   subscript(i: Int) -> ItemType { get }
}
struct Stack<T>: Container {
   // original Stack<T> implementation
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
   // conformance to the Container protocol
   mutating func append(item: T) {
      self.push(item: item)
   }
   var count: Int {
      return items.count
   }
   subscript(i: Int) -> T {
      return items[i]
   }
}
func allItemsMatch<
C1: Container, C2: Container
where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
(someContainer: C1, anotherContainer: C2) -> Bool {
   // check that both containers contain the same number of items
   if someContainer.count != anotherContainer.count {
      return false
   }
   // check each pair of items to see if they are equivalent
   for i in 0..<someContainer.count {
      if someContainer[i] != anotherContainer[i] {
         return false
      }
   }
   // all items match, so return true
   return true
}  
var tos = Stack<String>()
tos.push(item: "Swift 4")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Where Clause")
print(tos.items)
var eos = ["Swift 4", "Generics", "Where Clause"]
print(eos)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Where Clause]
[Swift 4, Generics, Where Clause]

Swift - Access Control

为了限制对代码块的访问,模块和抽象是通过访问控制完成的。 可以根据访问控制机制的属性,方法,初始化程序和下标来访问类,结构和枚举。 协议中的常量,变量和函数受到限制,并允许通过访问控制作为全局和本地访问。 应用于属性,类型和功能的访问控制可称为“实体”。

访问控制模型基于模块和源文件。

模块被定义为单个代码分发单元,可以使用关键字“import”导入。 源文件被定义为单个源代码文件,在模块中用于访问多种类型和功能。

Swift 4语言提供了三种不同的访问级别。 它们是公共,内部和私人访问。

S.No 访问级别和定义
1

Public

允许在其定义模块的任何源文件中处理实体,从另一个导入定义模块的模块的源文件。

2

Internal

允许实体在其定义模块的任何源文件中使用,但不能在该模块之外的任何源文件中使用。

3

Private

将实体的使用限制在其自己的定义源文件中。 专用访问可以隐藏特定代码功能的实现细节。

语法 (Syntax)

public class SomePublicClass {}
internal class SomeInternalClass {}
private class SomePrivateClass {}
public var somePublicVariable = 0
internal let someInternalConstant = 0
private func somePrivateFunction() {}

功能类型的访问控制

某些函数可能在函数内声明了参数而没有任何返回值。 以下程序将a和b声明为sum()函数的参数。 在函数本身内部,参数a和b的值通过调用函数调用sum()来传递,并且它的值被打印,从而消除了返回值。 要使函数的返回类型为private,请使用private修饰符声明函数的整体访问级别。

private func sum(a: Int, b: Int) {
   let a = a + b
   let b = a - b
   print(a, b)
}
sum(a: 20, b: 10)
sum(a: 40, b: 10)
sum(a: 24, b: 6)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

30 20
50 40
30 24

枚举类型的访问控制

public enum Student {
   case Name(String)
   case Mark(Int,Int,Int)
}
var studDetails = Student.Name("Swift 4")
var studMarks = Student.Mark(98,97,95)
switch studMarks {
   case .Name(let studName):
      print("Student name is: \(studName).")
   case .Mark(let Mark1, let Mark2, let Mark3):
      print("Student Marks are: \(Mark1),\(Mark2),\(Mark3).")
}

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Student Marks are: 98,97,95

对于枚举的个别情况,Swift 4语言中的枚举自动获得相同的访问级别。 例如,考虑访问三个主题中的学生姓名和标记,枚举名称被声明为学生,枚举类中的成员是属于字符串数据类型的名称,标记表示为数据类型Integer的mark1,mark2和mark3。 访问学生姓名或他们得分的分数。 现在,如果执行该案例块,则开关案例将打印学生姓名,否则将打印学生保护的标记。 如果两个条件都失败,则将执行默认块。

子类的访问控制

Swift 4允许用户子类化当前访问上下文中可以访问的任何类。 子类不能具有比其超类更高的访问级别。 限制用户编写内部超类的公共子类。

public class cricket {
   internal func printIt() {
      print("Welcome to Swift 4 Super Class")
   }
}
internal class tennis: cricket {
   override internal func printIt() {
      print("Welcome to Swift 4 Sub Class")
   }
}
let cricinstance = cricket()
cricinstance.printIt()
let tennisinstance = tennis()
tennisinstance.printIt()

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Welcome to Swift Super Class
Welcome to Swift Sub Class

常量,变量,属性和下标的访问控制

Swift 4常量,变量或属性不能定义为公共类型。 使用私有类型编写公共属性是无效的。 同样,下标不能比索引或返回类型更公开。

当常量,变量,属性或下标使用私有类型时,常量,变量,属性或下标也必须标记为私有 -

private var privateInstance = SomePrivateClass()

吸气剂和二传手

常量,变量,属性和下标的getter和setter自动获得与它们所属的常量,变量,属性或下标相同的访问级别。

class Samplepgm {
   var counter: Int = 0{
      willSet(newTotal) {
         print("Total Counter is: \(newTotal)")
      }
      didSet {
         if counter > oldValue {
            print("Newly Added Counter \(counter - oldValue)")
         }
      }
   }
}
let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800

当我们使用游乐场运行上述程序时,我们得到以下结果 -

Total Counter is: 100
Newly Added Counter 100
Total Counter is: 800
Newly Added Counter 700

初始化器和默认初始化器的访问控制

可以为自定义初始值设定项分配小于或等于它们初始化类型的访问级别。 必需的初始值设定项必须具有与其所属类相同的访问级别。 初始化程序的参数类型不能比初始化程序自己的访问级别更私密。

要声明初始化'required'关键字的每个子类需要在init()函数之前定义。

class classA {
   required init() {
      let a = 10
      print(a)
   }
}
class classB: classA {
   required init() {
      let b = 30
      print(b)
   }
}
let res = classA()
let print = classB()

当我们使用游乐场运行上述程序时,我们得到以下结果 -

10
30
10

默认初始值设定项具有与其初始化类型相同的访问级别,除非该类型被定义为public。 当默认初始化定义为公共时,它被视为内部。 当用户需要使用另一个模块中的无参数初始化程序初始化公共类型时,请明确提供公共无参数初始化程序作为类型定义的一部分。

协议的访问控制

当我们定义一个新协议来从现有协议继承功能时,必须将它们声明为相同的访问级别以继承彼此的属性。 Swift 4访问控制将不允许用户定义继承自“内部”协议的“公共”协议。

public protocol tcpprotocol {
   init(no1: Int)
}
public class mainClass {
   var no1: Int      // local storage
   init(no1: Int) {
      self.no1 = no1 // initialization
   }
}
class subClass: mainClass, tcpprotocol {
   var no2: Int
   init(no1: Int, no2 : Int) {
      self.no2 = no2
      super.init(no1:no1)
   }
   // Requires only one parameter for convenient method
   required override convenience init(no1: Int) {
      self.init(no1:no1, no2:0)
   }
}
let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)
print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

当我们使用游乐场运行上述程序时,我们得到以下结果 -

res is: 20
res is: 30
res is: 50

扩展的访问控制

当用户使用该扩展来添加协议一致性时,Swift 4不允许用户为扩展提供显式访问级别修饰符。 扩展中每个协议要求实现的默认访问级别具有自己的协议访问级别。

泛型的访问控制

泛型允许用户指定最小访问级别以访问其类型参数的类型约束。

public struct TOS<T> {
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
}
var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Type Parameters")
print(tos.items)
tos.push(item: "Naming Type Parameters")
print(tos.items)
let deletetos = tos.pop()

当我们使用游乐场运行上述程序时,我们得到以下结果 -

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]

类型别名的访问控制

用户可以定义类型别名以处理不同的访问控制类型。 用户可以定义相同的访问级别或不同的访问级别。 当类型别名为“私有”时,其关联成员可以声明为“私有,内部公共类型”。 当类型别名为public时,成员不能将别名作为“内部”或“私有”名称

为了访问控制的目的,您定义的任何类型别名都被视为不同类型。 类型别名的访问级别可以小于或等于其别名类型的访问级别。 例如,私有类型别名可以为私有,内部或公共类型设置别名,但公共类型别名不能为内部或私有类别设置别名。

public protocol Container {
   associatedtype ItemType
   mutating func append(item: ItemType)
   var count: Int { get }
   subscript(i: Int) -> ItemType { get }
}
struct Stack<T>: Container {
   // original Stack<T> implementation
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
   // conformance to the Container protocol
   mutating func append(item: T) {
      self.push(item: item)
   }
   var count: Int {
      return items.count
   }
   subscript(i: Int) -> T {
      return items[i]
   }
}
func allItemsMatch<
   C1: Container, C2: Container
   where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
   (someContainer: C1, anotherContainer: C2) -> Bool {
   // check that both containers contain the same number of items
   if someContainer.count != anotherContainer.count {
      return false
   }
   // check each pair of items to see if they are equivalent
   for i in 0..<someContainer.count {
      if someContainer[i] != anotherContainer[i] {
         return false
      }
   }
   // all items match, so return true
   return true
}
var tos = Stack<String>()
tos.push(item: "Swift 4")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Where Clause")
print(tos.items)
var eos = ["Swift 4", "Generics", "Where Clause"]
print(eos)

当我们使用游乐场运行上述程序时,我们得到以下结果 -

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Where Clause]
[Swift 4, Generics, Where Clause]

Swift编码和解码

Swift 4引入了一个新的Codable协议,它允许您在不编写任何特殊代码的情况下序列化和反序列化自定义数据类型 - 而不必担心丢失您的值类型。

struct Language: Codable {
   var name: String
   var version: Int
}
let swift = Language(name: "Swift", version: 4)
let java = Language(name: "java", version: 8)
let R = Language(name: "R", version: 3

请注意,Langauage符合Codable协议。 现在我们将使用一条简单的线将其转换为Json数据表示。

let encoder = JSONEncoder()
if let encoded = try? encoder.encode(java) {
   //Perform some operations on this value.
}

Swift将自动编码数据类型中的所有值。

您可以使用解码器功能解码数据

let decoder = JSONDecoder()
if let decoded = try? decoder.decode(Language.self, from: encoded) {
   //Perform some operations on this value.
}

JSONEncoder及其属性列表对应的PropertyListEncoder都有很多选项可用于自定义它们的工作方式。

↑回到顶部↑
WIKI教程 @2018