美文网首页
Swift数据类型至少要知道这些

Swift数据类型至少要知道这些

作者: _我和你一样 | 来源:发表于2019-03-01 18:12 被阅读0次

可选型optional

  1. 可选型本质上是一个枚举类型enum
enum Optional<T> {// The <T> is a generic like as in Array<T>
    case none
    case some(T)
}

以下两种写法是等价的

let x:String? = nil
... is ...
let y = Optional<String>.none

let x:String? = "Hello"
... is ...
let x = Optional<String>.some("Hello")

// unwrap
let y = x!
...is...
switch x {
    case .some(let value):y = value
    case .none:// raise an excepiton
}

let x:String? = ...
if let y = {
    // do someting with y 
}
... is ...
switch x {
    case .some(let y):// do something with y
    case .none:break
}
  1. 可选型是可以链式传递的
var display:UILabel?
if let temp1 = display {
    if let temp2 = temp1.text {
        let  x = temp2.hashValue
        //...
    }
}
// 等价于 链式解包如果中间有一个为nil,返回的值为nil
if let x = display?.text.hashValue // x is an Int
let x = display?.text.hashValu // x is an Int?
//因此在链式解包时使用?而不是!
  1. 可选默认值操作符??

    如果可选型解包值为nil,则赋予默认值

let s: String? = ...
if s != nil {
    display.text = s
}else {
    display.text = ""
}
// 等价于
display.text = s??""

元组 tuple

tuple is a grouping of values

You can use it anywhere you can use a type.

let x: (String,Int,Double) = ("Hello",5,0.85)// the tyoe of x is a tuple
let (word,number,value) = x// this names the tuple emlements when accessing the tuple 当元组被访问时,命名元组内的元素
print(word)// hello
print(number)// 5
print(value)// 0.85
// 当元组被声明的时候也可以为元组元素命名 建议使用这种,tuple 可以通过点语法访问元组内的元素
let y:(x:String,i:Int,v:Double) = ("Hello",5,0.85)
print(y.x)
print(y.i)
print(y.v)
// 可以使用下划线忽略元组中元素
let (word,_,value) = x

Range

A range in swift is just tow end Points.

A range can represent things like a selection in some text or a portion of an Array

Range is generic(e.g. Range<T>), but T is restricted(e.g. comparable).

类似于这种

struct Range<T> {
    var startIndex:T
    var endIndex:T
}

CountableRange 包含的值可以迭代或者用下标访问

创建Range有一种特殊的语法

..< 不包含上限。

...包含上限

CountableRange 可以用for in 遍历

// C-like : for (i = 0;i<20;i++)
for i in 0..<20 {
    
}
// 浮点数不是countable的 对于 for(i=0.5;i<=15.25;i+=3) 是无法直接使用forin的,但是有一个通用的方法可以从浮点数创建一个CountableRange
for i in stride(from:0.5,through:12.25,by:0.3){
    
}

数据结构 struct,enum,class

相似点:

语法声明相似

class ViewController: ... {
    
}

struct Calculation {
    
}

enum Opration {
    
}

都可以拥有属性和方法

func doit(agrx agri:Type)->ReturnValue{
    
}
var storedProperty =<initial value>(not enum)

var computedProperty:Type {
    get{}
    set{}
}

初始化(not enum)

init(arg1x arg1i:Type,arg2x arg2i:Type ...){
    
}

不同点:

  1. 只有class可以继承

  2. struct 和 enum是值(value)类型,而class是引用类型(inference)

值类型(如struct,enum)特点如下:

Copied when passed as an argument to a founction

Copied when assigned to a different variable

Immutable if assigned to a variable with let (function parameters are let)

You must note any func that can mutate a struct/enum with the keyword mutating

引用类型(如class)特点如下:

Stored in the heap and reference counted(automatically)

Constant Pointers to a class (let) still can mutate by calling methods and changing properties

When passed as an argument, does note make a copy (just passing a pointer to same instance)

参数名称

对于所有的方法而言所有的参数都有一个内部名称和外部名称,

内部名称是在方法内使用的局部变量

外部名称是调用者调用方法时使用的名称

如果不想让调用者使用外部名称,可以使用下划线忽略外部名称,

如果只提供了一个参数名,这个参数名即是外部名称又是外部名称

类型和方法都可以拥有方法和属性

类型的方法和属性都需要使用static关键词修饰

比如Double这个struct类型有一系列变量和方法在这个类型上

比如访问 Double.pi 访问的不是实例的属性而是类型的属性

属性观察

可以通过willSet和didSet来观察属性值的更改。

如果修改了一个结构体,也会包含这种变化

var someStoredProperty:Int = 42 {
    willSet{newValue is the new value}
    didSet{oleValue is the old value}
}
// 继承的属性也可以观察 重新父类的属性和方法都需要使用关键词override
override var inheritedProperty:String{
    willSet{newValue is the new value}
    didSet{oleValue is the old value}
}
// 架构体的变化也可以捕获
var opertaions:Dictionary<String,Operation>=[...]{
    willSet{will be executed if an opreation is added/removed}
    didSet {will be executed if an opreation is added/removed}
}

懒加载

使用lazy关键词修饰,这种变量只有在访问的时候才会初始化,可以通过执行闭包或者调用方法来创建一个对象

lazy var brain = CalulatorBrain()
lazy var someProperty:Type = {
    // construct the value of someProperty 
    return <the constructed value>
}()
lazy var myProperty = self.initialiedMyProperty()

初始化

  1. 什么时候需要init方法

init方法不是非常常见,因为

  • 属性可以使用=赋予默认值
  • 属性也可以使用可选型,这种情况下初始值为nil
  • 属性也可以使用懒加载

因此,当上述方面不能满足时,需要初始化方法。

  1. 有些初始化方法不用自己写就可以使用
  • 基类的init()方法
  • 如果结构体没有初始化方法,会有默认的初始化方法包含所有的参数
  1. 在init方法中需要做什么

    当初始化完成之后,所有属性都应当有值(可选型可以为nil)

    在class中有两种初始化方法 convenience and designated

    1. a designated init must (and can only) call a designated init that is in its immediate supercalss
    2. you must initialize all properties introduced by your calss before calling a supercalss' init
    3. You must call a supercalss' init before you assign a value to an inherited property
    4. a convenience init must ( and can only) call an init in its own class
    5. a convenience init must call that init before it can set any property values
  2. 可以失败的初始化

如果init声明为init?,它将返回一个可选型,初始化失败时为nil

比如

let image = UIImage(named:"foo")// image is an Optional

类型转换

可以使用as?来进行类型转换,尤其在有使用到Any类型,以及父类像子类转换时很常见

断言

可以使用assert在调试时帮助调试,

assert(()->Bool,"message") 这个函数的参数时自动闭包,所以不需要{}

条件为假时,给出后面的信息。

当编辑为release版本时,断言会完全被忽略。

相关文章

网友评论

      本文标题:Swift数据类型至少要知道这些

      本文链接:https://www.haomeiwen.com/subject/hzljuqtx.html