class Student{
    var name: String
    init(name:String){
        self.name = name
    }
}
var dylan = Student(name:"dylan")

延迟属性

import Cocoa

class sample {
    lazy var no = doLatter() // `var` 关键字是必须的
}
class doLatter{
    var name = "dylan"
}
print(sample().no.name)

以上输出dylan

类属性的get,set,willSet,didSet

import UIKit

class Student{
    var x:Int
    var y:Int{
        willSet{
            print("y willSet")
        }
        didSet{
            print("y didSet")
        }
    }
  
    var Pos:(Int,Int){
        get{
            return (self.x,self.y)
        }
        set(pos){
            self.x = pos.0
            self.y = pos.1
        }
        //willSet(pos){
        //    print("马上要设置pos为:\(pos)"+"\n该方法只观察")
        //}
        //didSet{
        //    print("成功设置pos")
        //}
    }
}

let stu = Student(x: 10,y:20)
print("stu的name:\(stu.Pos)")
stu.y = 111
print(stu.x)
print(stu.y)

以上输出

stu的name:(10, 20)
y willSet
y didSet
10
111

注意

  • set方法写明时,不能同时实现willSet,didSet
  • 在init函数中的赋值不会触发willSet,didSet
  • 可以只写一个get方法,实现只读变量

方法的局部参数与外部参数

Swift 默认仅给方法的第一个参数名称一个局部参数名称;默认同时给第二个和后续的参数名称为全局参数名称。

第一个参数可以强制再加一个外部参数,其余的参数可以通过添加"_"来声明为局部参数

class Counter {
  var count: Int = 0
  func incrementBy(amount: Int, numberOfTimes: Int) {
    count += amount * numberOfTimes
  }
}

let counter = Counter()
couter.incrementBy(5,numberOfTimes:3)

可以通过以下操作,实现第一个参数外部化,第二个参数默认内部

class Counter {
  var count: Int = 0
  func incrementBy(numberOfAmount amount: Int, _ numberOfTimes: Int) {
    count += amount * numberOfTimes
  }
}

let counter = Counter()
couter.incrementBy(numberOfAmount:5,3)

可变方法修改结构体或枚举的属性

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

结构体使用static声明静态方法

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

类使用class声明静态方法

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

使用下标脚本实现自定义中括号"[]"调用

struct subexample {
    let decrementer: Int
    subscript(index: Int) -> Int {
        return decrementer / index
    }
}
let division = subexample(decrementer: 100)

print("100 除以 9 等于 \(division[9])")

通常下标脚本是用来访问集合(collection),列表(list)或序列(sequence)中元素的快捷方式。

你可以在你自己特定的类或结构体中自由的实现下标脚本来提供合适的功能。

继承与重写

class SuperClass {
    var name
    init(str:String){
        self.name = str;
    }
    func show() {
        print("这是超类 SuperClass")
    }
}

class SubClass: SuperClass  {
    init(){
        super.init(str:"dylan")
    }
    override func show() {
        print("这是子类 SubClass")
    }
    override var name:String{
        return super.name +"重写了"
    }
}

使用final关键字防止被重写,编译时会报错提示

init构造函数

如果你在定义构造器时没有提供参数的外部名字,Swift 会为每个构造器的参数自动生成一个跟内部名字相同的外部名。

struct Color {
    let red, green, blue: Double
    init(red: Double, green: Double, blue: Double) {
        self.red   = red
        self.green = green
        self.blue  = blue
    }
    init(white: Double) {
        red   = white
        green = white
        blue  = white
    }
}

let magenta = Color(red: 1.0, green: 0.0, blue: 1.0)

如果你不希望为构造器的某个参数提供外部名字,你可以使用下划线_来显示描述它的外部名。

struct Rectangle {
    var length: Double
    
    init(frombreadth breadth: Double) {
        length = breadth * 10
    }
    
    init(frombre bre: Double) {
        length = bre * 30
    }
    //不提供外部名字
    init(_ area: Double) {
        length = area
    }
}

构造过程中可以修改常量属性的值,因为实例还没生成。

class ShoppingListItem {
    var name: String?
    var quantity = 1
    var purchased = false
}

以上类的属性都有默认值,且它是没有父类的基类,它将自动获得一个可以为所有属性设置默认值的默认构造器

Swift 中的子类不会默认继承父类的构造器

当你重写一个父类指定构造器时,你需要写override修饰符。

convenience修饰init使成为辅助的便利构造器

class mainClass {
    var no1 : Int // 局部存储变量
    init(no1 : Int) {
        self.no1 = no1 // 初始化
    }
}

class subClass : mainClass {
    var no2 : Int
    init(no1 : Int, no2 : Int) {
        self.no2 = no2
        super.init(no1:no1)
    }
    // 便利方法只需要一个参数
    override convenience init(no1: Int)  {
        self.init(no1:no1, no2:0)
    }
}

可失败构造器

在init关键字后面加添问号(init?)或者添加感叹号(init!),当参数无效或者其他原因不满足构造条件时,返回nil

struct Animal {
    let species: String
    init?(species: String) {
        if species.isEmpty { return nil }
        self.species = species
    }
}
enum TemperatureUnit {
    // 开尔文,摄氏,华氏
    case Kelvin, Celsius, Fahrenheit
    init?(symbol: Character) {
        switch symbol {
        case "K":
            self = .Kelvin
        case "C":
            self = .Celsius
        case "F":
            self = .Fahrenheit
        default:
            return nil
        }
    }
}


let fahrenheitUnit = TemperatureUnit(symbol: "F")
if fahrenheitUnit != nil {
    print("这是一个已定义的温度单位,所以初始化成功。")
}

let unknownUnit = TemperatureUnit(symbol: "X")
if unknownUnit == nil {
    print("这不是一个已定义的温度单位,所以初始化失败。")
}

使用deinit方法进行析构

属性中的?与!(可选链)

通过在属性、方法、或下标脚本的可选值后面放一个问号(?)定义一个可选链。

多次请求或调用可以被链接成一个链,如果任意一个节点为nil将导致整条链失效

class Person {
    var residence: Residence?
}

class Residence {
    var numberOfRooms = 1
}

let john = Person()

//将导致运行时错误
let roomCount = john.residence!.numberOfRooms

// 链接可选residence?属性,如果residence存在则取回numberOfRooms的值
if let roomCount = john.residence?.numberOfRooms {
    print("John 的房间号为 \(roomCount)。")
} else {
    print("不能查看房间号")
}

swift中避免循环引用

如果是互相持有,多使用weak

class Module {
    let name: String
    init(name: String) { self.name = name }
    var sub: SubModule?
    deinit { print("\(name) 主模块") }
}

class SubModule {
    let number: Int
    
    init(number: Int) { self.number = number }
    
    weak var topic: Module?
    
    deinit { print("子模块 topic 数为 \(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

如果是闭包(类似block),多使用[unowned self] in(称为无主引用)

class HTMLElement {
    
    let name: String
    let text: String?
    
    lazy var asHTML: () -> String = {
        [unowned self] in
        if let text = self.text {
            return "<\(self.name)>\(text)</\(self.name)>"
        } else {
            return "<\(self.name) />"
        }
    }
    
    init(name: String, text: String? = nil) {
        self.name = name
        self.text = text
    }
    
    deinit {
        print("\(name) 被析构")
    }
    
}

swift中的类型判断与转换

使用is判断实例是否属性某类

class Subjects {
    var physics: String
    init(physics: String) {
        self.physics = physics
    }
}
var tmp = Subjects("高分子")
if tmp is Subjects {
    print("tmp为Subjects的实例")
}

类型转换

as? 如果转换成功返回实例,失败为nil

as! 如果转换成功返回实例,失败报错

class Subjects {
    var physics: String
    init(physics: String) {
        self.physics = physics
    }
}
class Math{
    var title: String
    init(title:String){
        self.title = title
    }
}
var tmp1 = Subjects("高分子")
var tmp2 = Math("微积分")
let sa = [tmp1,tmp2]

for item in sa{
    if let show = item as? Subjects{
        
    }else if let example = item as? Math{
        
    }
}
  • AnyObject可以代表任何class类型的实例。
  • Any可以表示任何类型,包括方法类型(function types)。

#### 使用extension进行扩展

使用扩展管理协议或添加新属性方法等

extension SomeType: SomeProtocol, AnotherProctocol {
    // 协议实现写到这里
}
extension Int {
   var double: Int {return self * 2 }
}
print("扩展后的功能2的double:\(2.double)")

一些有意思的扩展

extension Int {
   func topics(summation: () -> ()) {
      for _ in 0..<self {
         summation() 
      }
   }
}  

4.topics({
   print("扩展模块内")       
})    
    
3.topics({
   print("内型转换模块内")       
})  

输出

扩展模块内
扩展模块内
扩展模块内
扩展模块内
内型转换模块内
内型转换模块内
内型转换模块内

下面扩展通过下标返回int的位数值

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

swift中的协议

协议的语法格式如下:

protocol SomeProtocol {
    // 协议内容
}

要使类遵循某个协议,需要在类型名称后加上协议名称,中间以冒号:分隔,作为类型定义的一部分。遵循多个协议时,各协议之间用逗号,分隔。

struct SomeStructure: FirstProtocol, AnotherProtocol {
    // 结构体内容
}

如果类在遵循协议的同时拥有父类,应该将父类名放在协议名之前,以逗号分隔。

class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
    // 类的内容
}

协议中的通常用var来声明变量属性,在类型声明后加上{ set get }来表示属性是可读可写的,只读属性则用{ get }来表示

协议可继承

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

protocol中的方法同样可以使用mutating修饰,实现协议的struct或者enum可以修改值实例中的值

protocol daysofaweek {
    mutating func show()
}

enum days: daysofaweek {
    case sun, mon, tue, wed, thurs, fri, sat
    mutating func show() {
        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.show()

尽量使用forin循环

for _ in 0..5 {
  println("Hello five times")
}

标签: Swift, Objective-C, 从Objective-C到Swift

添加新评论