Swift 可以导入 C C++ object C (c的超级) cocoa ( object C 框架)Swift 是一个区分大小写的语言,所以字母大写与小写是不一样的。
类型安全 :运行时会检测到不同类型的赋值会标记报错; Let 常量 Var 变量
import Cocoa
var varA = 42
varA = "This is hello"
print(varA)类型推断: 根据后面的赋值推断当前变量的类型 let meaningOfLife = 42
// meaningOfLife 会被推测为 Int 类型
变量输出:反斜杠加括号来插入变量print("(name)的官网地址为:(site)")Swift 可选(Optionals)类型: Optional 是一个含有两种情况的枚举,None 和 Some(T),,用来表示可能有或可能没有值var optionalInteger: Int?
var optionalInteger: Optional<Int>
var num:String?
var num:Optional<Double>强制解析:swift “!” (解包) ,当可选类型为有值时不会报错,不然会报错, 可以用可选绑定,或者可选链来解包,这样不会出错;var myString:String?
myString = "Hello, Swift!"
if myString != nil {
// 强制解析
print( myString! )
}else{
print("myString 值为 nil")
}
自动解析
你可以在声明可选变量时使用感叹号(!)替换问号(?)。这样可选变量在使用时就不需要再加一个感叹号(!)来获取值,它会自动解析。
var myString:String!
myString = "Hello, Swift!"
if myString != nil {
print(myString)
}else{
print("myString 值为 nil")
}
可选绑定 :如果有值就把optional 赋值给 这个变量/常量; 没有值也不会运行报错
if let constantName = someOptional {
statements
}
可选链 : 注意这里有个“问号”,这就是可选链:在“问号”后的所有代码,只会在“问号”前的代码有值时,才会运行。这不会影响 album 的基本数据类型,因为无论这行返回 nil 还是大写的 album 名称,它都是一个可选 string 。
let album = albumReleased(year: 2006)?.uppercased()
print("The album is (album)")
nil 合并运算符 “?? “:它起的作用就好像你会说“如果可以的话,使用 A 的值,如果 A 是 nil 的话就使用 B 的值。
let num = A ?? B
Swift 字面量 :就是指像特定的数字,字符串或者是布尔值这样,能够直接了当地指出自己的类型并为变量进行赋值的值
定义枚举
enum name {
case Sunday
case Monday
case TUESDAY
case WEDNESDAY
case THURSDAY
case FRIDAY
case Saturday
}
var user = name.Sunday
user = .TUESDAY
switch user {
case .Sunday:
print("星期天")
case .Monday:
print("星期一")
case .TUESDAY:
print("星期二")
case .WEDNESDAY:
print("星期三")
case .THURSDAY:
print("星期四")
case .FRIDAY:
print("星期五")
case .Saturday:
print("星期六")
}
枚举相关值
enum Student{
case Name(String)
case Mark(Int,Int,Int)
}
var studDetails = Student.Name("Runoob")
var studMarks = Student.Mark(98,97,95)
switch studMarks {
case .Name(let studName):
print("学生的名字是: (studName)。")
case .Mark(let Mark1, let Mark2, let Mark3):
print("学生的成绩是: (Mark1),(Mark2),(Mark3)。")
}
枚举原始值
原始值可以是字符串,字符,或者任何整型值或浮点型值。每个原始值在它的枚举声明中必须是唯一的。
在原始值为整数的枚举时,不需要显式的为每一个成员赋值,Swift会自动为你赋值。
enum Month: Int {
case January = 1, February, March, April, May, June, July, August, September, October, November, December
}
let yearMonth = Month.May.rawValue
print("数字月份为: (yearMonth)。")数字月份为:5
结构体应用 :结构体实例总是通过值传递来定义你的自定义数据类型。
结构体的主要目的是用来封装少量相关简单数据值。
有理由预计一个结构体实例在赋值或传递时,封装的数据将会被拷贝而不是被引用。
任何在结构体中储存的值类型属性,也将会被拷贝,而不是被引用。
结构体不需要去继承另一个已存在类型的属性或者行为。
值传递: 赋值的时候,传递的是复制的值 ,修改前一个或者后一个对另外一个的值不受影响. 结构体 枚举 值面变量
func test() {
var age = 18
var age2 = age
age = 20
age2 = 30
print("age:\(age)--age2:\(age2)")
}
test()
引用传递 : 传递的时候赋值给的是前一个实例的地址,前后拥有是同一个地址,修改任何一个都会影响前一个.
Class 省略1,结构体的函数中需要修改自身的属性,需要使用mutating修饰函数,而类不需要
2,mutating的本质就是给隐式参数self用inout修饰
3,inout修饰的参数是使用地址的,不是值传递,是引用
4,mutating修饰的是函数,inout修饰的是参数
因为类是引用类型,有可能有多个常量和变量在后台同时引用某一个类实例。
为了能够判定两个常量或者变量是否引用同一个类实例,Swift 内建了两个恒等运算符:
恒等运算符 ===
如果两个变量 引用同一个实例,返回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")
if spClass1 === spClass2 {// false
print("引用相同的类实例 (spClass1)")
}
if spClass1 !== spClass2 {// true
print("引用不相同的类实例 (spClass2)")
}
引用不相同的类实例 SampleClass
Lazy: 延迟存储属性 ,第一次调用时,才会计算存储值的属性延迟存储属性一般用于:
延迟对象的创建。
当属性的值依赖于其他未知类
class sample {
lazy var no = number() // var
关键字是必须的
}
class number {
var name = "Runoob Swift 教程"
}
var firstsample = sample()
print(firstsample.no.name)
属性观察器 swift 的伟大之处
willSet 属性被设置之前
didSet属性被设置之后调用
willSet和didSet观察器在属性初始化过程中不会被调用
class Samplepgm {
var counter: Int = 0{
willSet(newTotal){
print("计数器: (newTotal)")
}
didSet{
if counter > oldValue {
print("新增数 (counter - oldValue)")
}
}
}
}
let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800
类型属性
static 关键字 static 来定义值类型的类型属性,类似于实例的属性,类型属性的访问也是通过点运算符(.)来进行。但是,类型属性是通过类型本身来获取和设置,而不是通过实例。实例如下:
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)
关键字 final 防止类型被重写 Overriding 枚举类型的可失败构造器
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时,将闭包内的捕获定义为弱引用。
如果捕获的引用绝对不会置为nil,应该用无主引用,而不是弱引用。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) 被析构")
}
}
//创建并打印HTMLElement实例
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
print(paragraph!.asHTML())
// HTMLElement实例将会被销毁,并能看到它的析构函数打印出的消息
paragraph = nil
Swift 类型转换
wift 语言类型转换可以判断实例的类型。也可以用于检测实例类型是否属于其父类或者子类的实例。
Swift 中类型转换使用 is 和 as 操作符实现,is 用于检测值的类型,as 用于转换类型。
类型转换也可以用来检查一个类是否实现了某个协议。
Swift 访问控制
public 可以访问模块中任何实体,别人也可以通过引用该模块来访问
internal 可以访问自己模块中的任何实体,但是别人不能访问模块中源文件的实体 (默认)
fileprivate 文件内私有,只能在当前源文件中使用。
private 只能在类中访问,离开了这个类或者结构体的作用域外面就无法访问。
public 为最高级访问级别,private 为最低级访问级别。
枚举类型访问权限
枚举中成员的访问级别继承自该枚举,你不能为枚举中的成员单独申明不同的访问级别。
子类访问权限
子类的访问级别不得高于父类的访问级别。比如说,父类的访问级别是internal,子类的访问级别就不能申明为public。
网友评论