Swift语言简介
2010 年 7 月,苹果开发者工具部门总监
Chris Lattner(克里斯·拉特纳)
开始着手Swift
编程语言的设计工作,用时一年时间,完成开发语言基本架构,经历了4年的开发周期,终于在2014 年 6 月Apple WWDC
发表,用来撰写 OS X 和 iOS 应用程序等。
Swift较Objective-C优点 ?
- 快速、现代、安全、互动,而且明显优于
Objective-C
语言;
- 取消了
Objective-C
的指针及其他不安全访问的使用; - 舍弃
Objective C
早期应用Smalltalk
的语法,全面改为 句点表示法; - 提供了类似 Java 的命名空间(namespace)、泛型(generic)、运算对象重载(operator overloading)等新概念。
基本知识点详解
常量与变量
-
let
声明常量,var
声明变量,打印print()
- 枚举类型:枚举名称点枚举值(点语法表示)
- 常量、变量可用任何字符表示,常量必须在定义时初始化, 否则会报错
- 每行语句后不需添加分号(添加也正确),若是多条语句则需添加分号区别
- 若在定义的同时并初始化 - 没有必要指定数据类型,若定义时没初始化 - 必须指定数据类型
- 常量、变量名不能包含数学符号、箭头、保留的/非法的Unicode 码位、连线与制表符、也不能以数字开头,但可在常量、变量名其他地方包含数字
-
Swift
对数据类型要求非常严格,若要转换,则必须显示转换;- 小数默认是
Double
类型 - 整数默认是
Int
类型
- 小数默认是
var 2x = 50 //错误
var 🐶 = 100
var 欢迎 = 500
let num:Int = 10 //显示指定类型
let sum = num + Int(num2) //显示转换(不存在隐式转换)
逻辑分支
-
if
语句不存在“非零即真”概念 条件只能放BOOL值/(true、false)
- 三目运算符:可以
if ... else
语句转换而来,保持了和OC
的一致 -
if
语句条件的()
可以省略,{ }
不能省略 -
for
循环for ... in ... { ... }
,0..<10 -> 0~9,0...10 ->0~10
for _ in 0..<10 {
print("hello") //_代表忽略
}
var a = 10
while a < 10 {
print(a)
a++ // ++ 前面的空格不能省略
}
//do~while在Swift2.0之后变为 repeat { ... } while(...), do用于捕捉异常
var b = 10
repeat{
print(b)
b++
}while b < 10
/**
* switch 后面()可以省略 ,每条语句后面不需添加break,在case语句内添加变量不需{}
* default语句必须放在最后,且大部分情况下不能省略
*/
switch num{
case 1:
print("1")
case 10:
print("10")
case 15:
print("15")
let value = 15
default:
print("0")
}
//条件绑定
var point = (100, 10)
switch point{
//只有where后面的条件表达式为真才赋值并执行case后的语句
case var(x, y) where x > y:
print("x= \(x) , y= \(y)")
default:
print("Other")
}
//值绑定
var point = (1, 10)
switch point{
case (var x, 10): //会将point中X的值赋值给X
print("x= \(x)")
case (var x, var y): //会将point中X、Y的值赋值给X、Y
print("x= \(x) y= \(y)")
case var( x, y):
print("x= \(x) y= \(y)")
default:
print("Other")
}
var point = (10, 15)
switch point{
case (0, 0):
print("坐标在原点")
case (1...10, 10...20): // 可在元祖中再加上区间
print("坐标的X和Y在1~10之间")
case (_, 0): // X可以是任意数
print("坐标的X在X轴上")
default:
print("Other")
}
- C语言和OC并没有真正的Bool类型(类似非0即真),Swift引入了真正的Bool类型(Bool true false)
- 元祖:将多个相同或者不同类型的值用一个小括号括起来,是复合类型, 小括号中可以写任意类型
//有了元祖之后就可以实现让一个函数返回多个值
let (name1 , age1 , _) = ("chongzone", 50, 25) //利用_通配符来忽略提取
print(name1);print(age1)
//元祖的其它定义方式:
let (name , age , score) = ("chongzone", 50, 25)
print(name);print(age);print(score)
//指明应用元祖元素的名称
let student2 = (name:"chongzone",age:50,score:99)
print(student2.name);print(student2.age);print(student2.score)
let student = ("chongzone", 50, 55)
let student1: (String, Int, Double) = ("chongzone", 50, 55)
print(student);print(student.0);print(student.1);print(student.2)
- 可选项(
optional
) - 直接打印可选类型,则会被optional
包囊 - 对于可选项,可使用
!
来强制解析,若是可选项没有值再做类型转换,会导致程序崩溃 - 解决办法 - 可选绑定 -
let + 常量 = 可选项
-
??
是一个非常有用的操作符,能够快速对nil
进行判断,若对象是 nil,则使用??
后面的值代替前面的 nil 值参与计算,在使用??
时,前面的整个部分需要使用()
包装
let url = NSURL(string: "www.baidu.com")
let request = NSURLRequest(URL: url!)
//解决办法 - 可选绑定
if let urlNormal = url {
print(urlNormal)
let request = NSURLRequest(URL: urlNormal)
}
- 数组、字典、字符串
//定义数组时若指定保存对象的类型,则不能向数组添加其他类型内容
let arr = ["1","2"]
var arr2 : [String] //或是 var arr2 = [String]() //只能保存字符串对象
arr2 = ["1"]
arr2.append("2")
var dict = ["name":"chong","age":25]
//利用元祖类型遍历字典,则会将字典内的key赋值给元祖中第一个变量,字典的value赋值给元祖中第二个变量
for (key, value) in dict {
print(k)
print(v)
}
//合并字典
var dict2 = ["sex":"man"]
for (k, v) in dict2 {
dict[k] = v
}
//格式化字符串
let name = "chong"
let age = 10
var str4 = "name = \(name),age = \(age)"
var str5 = String(format: "%@, %04d", arguments: [name, age])
////遍历字符串 可直接遍历
var str6 = "chongzone is 25 la"
for st in str6.characters {
print(st)
}
//截取 建议转化OC操作
var str7 : NSString = "chong is 30 lo"
var str8 = "chong is 30 la" as NSString
var subStr = str7.substringWithRange(NSMakeRange(3, 10))
- 函数(四种类型)
//没参数没返回值
func sum4() {
print("hello")
}
//存在参数没返回值
func sum2(a: Int, b: Int) {
print(a + b)
}
//没有参数与存在返回值
func sum3() -> Int {
return 20
}
//存在参数与返回值
func sum(a: Int, b: Int) ->Int {
return a + b
}
//对于存在的参数,可以添加标签
func sum5 (one a: Int, two b: Int) ->Int {
return a + b
}
print(sum5(one: 10, two: 10))
- 闭包、函数
//Swift方法/函数 参数在前 类型在后
/**
* 闭包 类似于 block,闭包是定义函数的, Swift中函数就是一种特殊的闭包
* 闭包的使用和block一样, 用于保存一段代码, 用作回调, 用作执行耗时操作
* 定义闭包格式 - 闭包名:形参 -> 返回值类型
* 调用闭包时格式:
* {
* (参数) -> 返回值类型
* in
* 执行语句
* }
*/
//闭包的返回值
//Swift 不建议使用self,不同数据类型不能参与计算
override func viewDidLoad() {
super.viewDidLoad()
//调用重构后的函数
let sc = createScrollView({ () -> Int in
return 10
}) { (index) -> UILabel in
let width = 45
let label = UILabel()
label.backgroundColor = UIColor.greenColor()
label.textColor = UIColor.darkGrayColor()
label.font = UIFont.systemFontOfSize(17)
label.text = "text\(index)"
label.frame = CGRect(x: index * width, y: 0, width: width, height: 44)
/**
* 闭包内部, 为了能够准确定位到view, 所以在闭包内部代码需要写self
* Swift开发中不建议写self, 一般是在闭包内才使用
* "weakSelf!" 强制其存在 (weakSelf是可选类型 需要‘!’保证其一定不是nil)并且防止了其循环引用
*/
weakSelf!.view.backgroundColor = UIColor.redColor()
return label
}
view.addSubview(sc)
}
//2个参数都是闭包,定义闭包后一般都会在本函数内部都会调用该闭包实现
func createScrollView(labelCount: ()->Int, labelWithIndex: (index:Int)->UILabel) -> UIScrollView{
// 1.创建UIScrollView
let sc = UIScrollView(frame: CGRect(x: 0, y: 100, width: 375, height: 44))
sc.backgroundColor = UIColor.orangeColor()
//labelCount():调用外部实现的闭包代码并返回int
let count = labelCount()
// 2.遍历创建UILabel
for i in 0..<count{
//labelWithIndex(index: i):先调用外部实现的闭包代码并返回UILabel
let label = labelWithIndex(index: i)
sc.addSubview(label)
sc.contentSize = CGSize(width: CGFloat(count) * label.bounds.width, height: 44)
}
return sc
}
- 自定义构造方法
//新建一个对象类
class Chongzone: NSObject {
var name: String?
var age: Int = 0
/**
* Swift要求属性必须初始化,若定义属性(“对象类型”)没初始化,则需在后面加上 ?,若是“基本数据类型”,初始化最好直接赋值为0,因为super.init()不会分配其存储空间
* 若在构造方法中对属性初始化,则不再需要 ?
* 若要初始化必须重写init方法, 重写init方法后就不用加?号了
* Swift中支持方法名重载, 同样的方法名称只要参数/返回值不同就可以
* 若是自定义了init方法, 但没重写init方法, 默认init方法就会失效
*/
//默认init方法
override init() {
name = "chongzone"
age = 26
}
//自定义的构造方法
init(name:String, age:Int) {
self.name = name
self.age = age
}
init(dict: [String: NSObject]) {
// 使用kvc给self赋值之前, 必须调用super.init(分配其内存空间)
super.init()
self.setValuesForKeysWithDictionary(dict)
}
}
//对应控制器调用
override func viewDidLoad() {
super.viewDidLoad()
// 不需import来导入某个类/控制器可直接使用, 因为Swift中有一个命名空间(namespace(默认情况下项目名称))的概念,同一个项目所有的资源共享
// 使用Swift最好使用cocoapods管理三方框架, 避免命名空间相同导致的冲突
//则对应的三种初始化方法
let cz = Chongzone()
print("\(cz.name), \(cz.age)")
let cz2 = Chongzone(name: "chongzone", age: 26)
print("\(cz2.name), \(cz2.age)")
let cz3 = Chongzone(dict: ["name": "chongzone", "age": 26])
print("\(cz3.name), \(cz3.age)")
}
- 懒加载(lazy)本质上是定义并执行一个闭包
// lazy var 变量:类型 = { ... }()
lazy var dataList: [String] = {
print("...")
return ["chongzone", "kongjian", "jianshu"]
}()
- getter、setter方法
class Chongzone: NSObject {
var title:String? {
didSet{
title = title! + " happy" //给属性设置完值之后调用, 用于更新UI
}
}
/**
* 如果只重写了get,没有set. 那么属性是一个"计算型"属性
* 计算型属性不占用存储空间, 相当于OC中的readOnly 最后的 ?不需写
*/
var name2:String{
return "chongzone"
}
//给某个变量赋值之后,去做些额外操作,赋值length - tomeStr改变
var length: Int? {
didSet {
timeStr = String(format: "%02d:%02d:%02d", arguments: [length! / 3600, (length! % 3600) / 60, length! % 60])
}
}
var timeStr: String?
// 以下开发中几乎不用
var _name:String?
var name:String?{
get{
return _name
}
set{
_name = newValue //只要外界给name赋值,则会保存在newValue
}
}
}
//对应的控制器
override func viewDidLoad() {
super.viewDidLoad()
let cz = Chongzone()
print(cz.name2) //chongzone
cz.title = " hello" //赋值后调用 didSet
print(cz.title!) //hello happy
}
- 部分代码
//设置跟控制器,和OC同
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window?.backgroundColor = UIColor.whiteColor()
window?.rootViewController = ViewController()
window?.makeKeyAndVisible()
//按钮触发方法 action - 字符串""
btn.addTarget(self, action: "btnClick:", forControlEvents: UIControlEvents.TouchUpInside)
//对应的方法
func btnClick(btn: UIButton) {
print(__FUNCTION__)
}
- 析构函数
deinit { //类似dealloc
print("...")
}
- 最后附上一段Swift环境下UITableView的简单实现
//核心代码
class ViewController: UIViewController {
override func loadView() {
let tableView = UITableView(frame: UIScreen.mainScreen().bounds)
tableView.dataSource = self
tableView.delegate = self
view = tableView
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
lazy var dataList : [String] = {
return ["1","2","3"]
}()
}
//MARK: - UITableViewDataSource
//Swift遵守协议 直接在后面添加 ,
//官方建议 数据源、代理单独写在一个扩展(extension)
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataList.count;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("cellIdentifier")
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cellIdentifier")
}
cell?.textLabel?.text = dataList[indexPath.row]
return cell!
}
}
终于完了... 有什么不对的地方还望指正咯,这个点...该吃饭啦。。。