swift 学习(一)基础知识 (基本数据类型,操作符,流控制,集合)
xcode 中调用API帮助
1、查看简单信息,选中后 按键 control +左键单击 或者按 右侧属性栏 里的帮助按钮
2、完整API,选中后 按键 control +左键双击
3、查看类、函数等的注释,参数列表等,alt +左键单击
4、代码块注释与取消注释的快捷键 都是 command + /
5、---不能用try...catch,但可用assertion 调试,有多个重载版本,assert(useDate<=0,"不符合则报错")
swift2.0中已引入do-catch语句
正文
初步印象
1. 字符统一用unicode编码,区分大小写,有很多类似js,java的用法
2. 类型安全:有可选类型,可选类型的值缺失时为 nil ,不再需要对一个值判别是否为Null,变量声明时已经确定
3. 在swift中,数字字面量之间的运算,支持隐式类型转换,但数字类型的变量和常量之间的运算,则不再支持隐式类型转换。
4. 标示符命名规则与C相同,但是 关键字可以做标示符
let π = 3.14 等价于 let `π` = 3.14
var `class`="sdd"
5. 字符串比对时加入了更多判断。不再只是简单地比对组成字符串的标量,而是会比对最终表现形式
6. 字符和字符串都用双引号
7. 句末不用写分号,但多条语句写在同一行时要加
8. 变量声明用var, 常量用let,因此变量声明格式 变化较大 ,数据类型编译器会自动识别,一般不用显式声明
let a = 2
var b: Double = 4
var aInt = 4, bInt = 7
var p1 = 10,p2:Double
9. swift 语法内容很少,使用也很方便。而且函数是第一性的,也有全局变量,面向对象,面向过程,函数式都可以尝试。就是太多与objective-c相关的东西。
10. 声明字典,数组用 方括号,而不是花括号, 元组 用圆括号
11. 接口关键字改做protocal,更形象了
12. 枚举和结构的功能增强了,可以加入属性,方法,也可以实现接口
一段Swift代码(可选类型的源码)
enum Optional<T> : Reflectable, NilLiteralConvertible { case None case Some(T) /// Construct a `nil` instance. init() /// Construct a non-\ `nil` instance that stores `some`. init(_ some: T) /// If `self == nil`, returns `nil`. Otherwise, returns `f(self!)`. func map<U>(f: @noescape (T) -> U) -> U? /// Returns `f(self)!` iff `self` and `f(self)` are not nil. func flatMap<U>(f: @noescape (T) -> U?) -> U? /// Returns a mirror that reflects `self`. func getMirror() -> MirrorType /// Create an instance initialized with `nil`. init(nilLiteral: ()) } extension Optional : DebugPrintable { /// A textual representation of `self`, suitable for debugging. var debugDescription: String { get } }
注意点
1、 xcode 中 swift 运算符 两边要加空格,否则多数时候会报错(赋值 和 比较)
关键字 共60个
与声明有关的14个:class, deinit, enum, extension, func, import, init, let, protocol, static, struct, subscript, typealias, var
与语句有关的14个:break, case, continue, default, do, else, fallthrough, if, in, for, return, switch, where, while
表达式和类型关键字12个:as, dynamicType, is, new, super, self, Self, Type, _COLUMU_ , _FILE_ , _FUNCTION_ , _LINE_
特定上下文中使用的20个:associativity, didset, get, infix, inout, left, mutating, none, nonmutating, operator, override, postfix, precedence, prefix, rightset, unowned, unowned(safe), unowned(unsafe), weak, willset
补充:finaly private public internal dynamic
@IBoutlet @IBAction @UIApplicationMain @objc
@autoclosure @autoclosure(escaping)
@autoclosure:用在函数的里标记一个参数,然后这个参数会先被隐式的包装为一个closure,再把closure作为参数给这个函数。 从而实现对传递给这个参数的表达式延迟求值。
func myassert(@auto_closure predicate : () -> Bool) { #if !NDEBUG if predicate() { abort() } #endif } //调用 myassert(someExpensiveComputation() != 42)
func &&(lhs: LogicValue, @auto_closure rhs: () -> LogicValue) -> Bool { return lhs.getLogicValue() ? rhs().getLogicValue() : false }
1.2 新增:@noescape:可以用在函数的闭包参数上,这意味着这个参数是唯一可被调用的(或者用在函数调用时以参数的方式出现),其意思是它的生命周期比函数调用的周期短,这有助于一些小小的性能优化,但最重要的是它屏蔽了闭包中对self.的需求。这使得函数的控制流比其他更加透明。在未来的beta版本中,标准库函数将普遍采用这种特性,比如autoreleasepool():
func autoreleasepool(@noescape code: () -> ()) { pushAutoreleasePool() code() popAutoreleasePool() }
使用在函数参数上的 @autoclosure属性现在含有@noescape新属性的功能,这个改进限制了@autoclosure作为控制流程以及惰性计算的能力。
第二种形式。@autoclosure(escaping), 和@autoclosure有着同样的调用形式,但是它允许产生结果的闭包在实现中缓存
运算符
优先级排序:
最高: ++, --, !, ~, - , +
160: << , >>
150: * , / , % , & , &* , &/ , &%
140: + , - , &+ , &- , | , ^
135: ..< , ...
132: is , as
130: < , <= , > , >= , == , != , === , !==
120: &&
110: ||,??
100: ?:
90: =, *=, /=, %=, +=, -=, <<=, >>=, &=, |=, ^=, &&=, ||=
swift特点
swift 赋值运算符并不能将自身作为一个值进行返回
if x = y {} // 报错
println(a = 3) // ()
swift 默认情况下算数运算符不容许值溢出,需使用溢出运算符
&+,&*: 溢出加法 用于整数 上溢出
var max = UInt16.max // 65535
println(max + 1) // 报错
println(max &+ 1) // 0
var max = Int16.max // 32767
println(max &+ 1) // -32768
&-,&*: 整数下溢出
&/, &% 解决除数为0 的情况,xcode不识别了,已经被移除
swift中可以浮点数求余
let a = 3.667 % 1.3 // 1.067
swift 中提供了 恒等运算符===,!==,用来测试两个对象的引用是否来自同一个对象实例
可选类型与拆封运算
// nil不同于c中的NULL,它表示值缺失,而不是空指针 // 只有可选类型的变量或常量才可接受nil,非可选类型的变量或常量不能接受nil func divide(a:Double,b:Double) ->Double? { if(b == 0){ return nil } return a / b } let result1 : Double? = divide(100,1) println(result1) // Optional(100.0) //强制拆封 (确定可选类型一定有值,可在读取它时通过拆封获取这个值) if result1 != nil{ println(result1!) //100 result1?.hashValue } //隐式拆封(更方便访问,会自动解封,若此时数据为nil,则后续操作可能出错) let result2 : Double! = divide (100,0) println(result2) //nil // result2.hashValue // 报错 result2?.hashValue // nil,添加问号则如果result2为nil就不会执行后续 let result3 : Double! = divide (100,2) println(result3) //50.0 result3.hashValue
?? 空值合并运算符
// 对 a 进行判断,如果不为 nil 则解包,否则就返回 b // a 必须是 optional 的 // b 必须和 a 类型一致 // 相当于三目运算符的简化版 var a: String? = "a" var b: String? = "b" var c = a ?? b // "a" a = nil c = a ?? b // "b" b = nil c = a ?? b ?? "c" // "c" //简化代码 if allowEmpty || items?.count ?? 0 > 0 { }
区间运算符分为闭区间 (...) 和左闭右开区间 (..<)
//1...100 等同于 1..<101,区间 // 区间运算符其实返回的是一个 Range<T> 对象,是一个连续无关联序列索引的集合。 // ..... let aNumber:Int = 3 switch aNumber { case 0...5: println("This number is between 0 and 5") case 6...10: println("This number is between 6 and 10") default: println("This number is not between 0 and 10") } // ..... (1...10).map{ "$\($0)" + ".00" } // .generate() 遍历 Range<T> 中的值。 var range = 1...4 var generator = range.generate() // {startIndex 1, endIndex 5} var item:Int? do{ item = generator.next() println(item) }while(item != nil) //区间运算符返回的是一个 ClosedInterval 或者 HalfOpenInterval 的东西, //类型只要是 Comparable 就可以了。所以我们也可以把 String 放到 ... 里。 let interval3 = 4.6...7.8 interval3.contains(4.88) // true //通过 String 的 ClosedInterval 来输出字符串中的小写字母: let test = "Hello" let interval = "a"..."z" // 交集 let interval2 = interval.clamp("d"..."h") for c in test.characters { if interval.contains(String(c)) { println("\(c)") } } //e l l o
+Inf, -Inf, NAN
//let a = 23 / 0 // 报错,0不能做除数 let b = 23.0 / 0 // inf 正无穷大 let bb = 23.0 / -0 // inf 正无穷大 let c = -23.0 / 0 // -inf 负无穷大 let cc = -23.0 / -0 // -inf 负无穷大 let d = 0.0 / 0 // nan 非数 let dd = 0.0 / -0 // nan 非数 b == bb // true c == cc // true d == dd // false
运算符重载
1. 非常实用,但也相当有风险,可读性问题,可使用字符为:/ = – + * % < > ! & | ^ . ~
2. 运算符函数即便写在类内部,定义后也会自动进入全局Global作用域,而不是作为类的一个成员函数
struct Vector2D { var x = 1.0, y = 1.0 } // 实现结构类型Vector2D的加法 func + (left: Vector2D, right: Vector2D) -> Vector2D { return Vector2D(x: left.x + right.x, y: left.y + right.y) } func *(vector2D: Vector2D,scalar:Double)->Vector2D{ return Vector2D(x: vector2D.x * scalar, y: vector2D.y * scalar) } // 1.实现 组合赋值运算符 左参数要设置为inout,赋值运算没有返回值 func += (inout left: Vector2D, right: Vector2D){ left = left + right } // 3. 会把1,2都覆盖了,不会报错 func += (left: Vector2D, right: Vector2D)->Vector2D{ let left2 = left + right return left2 } // 2.也可以有返回值,与1 不能并存 func += (inout left: Vector2D, right: Vector2D)->Vector2D{ left = left + right return left } // 实现一个单目运算符,需要加前缀prefix或 postfix // prefix func -(vector2D:Vector2D)->Vector2D{ return Vector2D(x: -vector2D.x, y: -vector2D.y) } // 1.运算结果要保存,则要用inout prefix func ++(inout vector2D:Vector2D)->Vector2D{ vector2D = vector2D + Vector2D(x: 1,y: 1) return vector2D } // 3.会覆盖1,2 。不保存运算结果,有返回值 prefix func ++(vector2D:Vector2D)->Vector2D{ let vector2D2 = vector2D + Vector2D(x: 1,y: 1) return vector2D2 } // 2. 没有返回值 prefix func ++(inout vector2D:Vector2D){ vector2D = vector2D + Vector2D(x: 1,y: 1) } postfix func ++(inout vector2D:Vector2D)->Vector2D{ let _vector2D = vector2D vector2D = vector2D + Vector2D(x: 1,y: 1) return _vector2D } // 非是对原有操作符的新应用,则要先声明其为操作符 prefix operator +++ {} prefix func +++(var c: Vector2D) -> Vector2D{ c += c c += Vector2D(x: 1.0, y: 1.0) return c } /// 自定义运算符需要遵循两段式,即需要先声明运算符 /// infix / prefix / postfix /// associativity 表示结合性:left,rigth,none,默认为none /// 指的事和其他运算符优先级相同的情况下,是从左边开始计算还是右边 /// precedence 表示优先级的数值,0...255,默认100 /// assignment 定义组合运算符时需要用到这个, infix operator +-{ associativity left precedence 140} func +-(left:Vector2D,right:Vector2D)->Vector2D{ return Vector2D(x:left.x + right.x,y:left.y - right.y) } infix operator +-={associativity right precedence 140 assignment} func +-=(inout left:Vector2D,right:Vector2D)->Vector2D{ left = Vector2D(x:left.x + right.x,y:left.y - right.y) return left } var point = Vector2D(x: 3.0, y: 1.0) var v1 = Vector2D(x: 1,y: 1) ++v1 //{x 2, y 2} v1 //{x 2, y 2} v1++ //{x 2, y 2} v1 //{x 3, y 3} -v1 //{x -3, y -3} +++point //{x 7.0, y 3.0} point //{x 3, y 1} v1+-point //{x 6, y 2} v1+-=point //{x 6, y 2} v1 //{x 6, y 2} let v3 = v1 += point v3 v1
数据类型
swift中,不同于c,java等的基本数据类型那样单纯表示数值,
swift中 基本数据类型和集合全部由结构或枚举实现,虽然牺牲了性能,但是功能却强大了很多。
基本数据类型
- 整型(Int8,Int16,Int32,Int64,Int(32位平台与Int32等宽,64位平台与Int64等宽),UInt8,UInt16,UInt32,UInt64,UInt)
- 浮点型(Float, Double)float 32位,double64位,默认浮点数为double
- 字符 let a:Character = "&" let b = "\u{1fb03}" 字符也用双引号
- 字符串 字符串拼接 let number = 9 ; let total = "\(number)加10等于\(Double(number) + 10)"
- 布尔型 Bool 只有两个值true,false,不能用0,1代替
元组(tuple)类型(记录)
var student1 = ("1001","张飞",20,96) 或 var student2 = (id:"1001",name:"张飞",age:20,score:96)
或 var student3 : (String,String,Int,Int) ; student3 = ("1001","张飞",20,96)
访问元组字段: student1.0, student2.0,student2.id
枚举
结构
类
typealias MyInt = Int var x :MyInt = 10
swift 中除类以外,所有基本数据类型,集合都是由结构实现,所有都可以调用构造器来初始化
let x = Float() //0.0 let y = Double() //0.0 let z = Int() //0 let aa = Bool()//false let bb = Character("S") //Character没有无参初始化 let dd = String() //"" let ee = [Int]()//0 elements let ff = [Int:String]()//0 key/value pairs let gg = Set<String>() //0 members let xxx: () = ()
swift里除了类以外的基本类型都是由结构体实现的,也既是除了类以外都是值引用类型
不再支持数字类型的隐式转换
let pi = 3 + 0.1415926 // pi的类型推导为double(最大精度匹配原则) let anInt = 10 let aDouble = 3.14 //var result = anInt + aDouble //报错 var result = Double(anInt) + aDouble let aChar:Character = "a" //var a:Character = anInt + aChar //报错 //var b:Int = a //报错
- Int8.min,Int8.max
- 二进制:0b,八进制:0o,十六进制:0x,指数:1.56e-2; 十六进制指数 0x5.a2p2(0x5.a2 * 22)
- swift 为方便阅读,整形,浮点均可添加多个零或下划线以提高可读性 var a = 000.0145 ; var b = 3_360_000
// 整形 let a = 100 a.byteSwapped a.bigEndian a.littleEndian a.toIntMax() a.value a.advancedBy(100) a.description
字符Character,字符串String 都使用""
String 本质上是一个Struct,因此可以用构造器来创建字符串
var str1 = "2sfer" var str2 = String() var str3 = String(count:5,repeatedValue:Character("f")) let character:Character = "a" let str4 = String(character) let characters:[Character] = ["c","b","a"] let str5 = String(characters)
字符串日常操作:是否包含某字符,rangOfString,前后缀,大小写切换,分割等
let someone = "Joris Kluivers" let end2 = someone.rangeOfString(" ")//5..<6 if (end2 != nil) { let firstName = someone[someone.startIndex..<end2!.startIndex] //"Joris" } else { // no space found } // 前后缀 let doc = "Java.docx" if doc.hasSuffix(".docx"){} if doc.lowercaseString.hasPrefix("java"){} // 大小写 "Hello, playground".uppercaseString //HELLO, PLAYGROUND "Hello, playground".lowercaseString //hello, playground // 分割 "Hello, playground".componentsSeparatedByCharactersInSet( NSCharacterSet(charactersInString: "eo") ) //["H", "ll", ", playgr", "und"] "Hello, playground".componentsSeparatedByString("play")//["Hello, ", "ground"]
var cafe = "cafe" // 插入字符 cafe.insert("!", atIndex: cafe.endIndex) // "cafe!" // 插入字符串 cafe.insertContentsOf(" is delicious".characters , at: cafe.endIndex.predecessor())//"cafe is delicious!" //移除字符 cafe.removeAtIndex(cafe.endIndex.predecessor()) // "!" //移除字符 cafe.removeRange(cafe.startIndex.advancedBy(1)...cafe.startIndex.advancedBy(3))// "c is delicious" //替换 ,移除字符单位置还在 cafe.replaceRange(cafe.startIndex.advancedBy(1)...cafe.startIndex.advancedBy(3), with: "afe") //"cafe delicious"
swift中每一个字符都代表了一个可扩展字母集(Extended Grapheme Clusters)
每一个可扩展的字母集,又由一个或几个有序的Unicode标量的值(Unicode scalar value)所组成,以上这些构成了人类可读的字符。
//形同c中用ascii编码,swift用unicode编码, 一个unicode标量占21个bit, 取值范围,U+0000到U+D7FF和从 U+E000 到U+10FFFF,不包括 U+D800 到 U+DFFF let dollarSign = "\u{24}" let blackHeart = "\u{2665}"
String 用结构实现,是值类型,而NSString 用类实现,是引用类型
String.Characters.count,和 NSString.length 并不总是完全一样的值,因为前者统计的是有意义的Extended Grapheme Clusters 个数,后者是UTF-16编码 计数
var word = "cafe" word.characters.count // 4 (word as NSString).length // 4 word += "\u{301}" // "café", 组合了一个重音符号 word.characters.count // 4 (word as NSString).length // 5 word += "\u{301}" // "café́", 再组合了一个重音符号 word.characters.count // 4 (word as NSString).length // 6 word += "\u{301}" // "café́́", 再组合了一个重音符号 word.characters.count // 4 (word as NSString).length // 7 word += "\u{301}" // "café́́́", 再组合了一个重音符号 word.characters.count // 4 (word as NSString).length // 8 word += "\u{301}" // "café́́́́", 再组合了一个重音符号 word.characters.count // 4 (word as NSString).length // 9 word += "\u{20dd}" // "café́́́́⃝", 再组合了一个圆 word.characters.count // 4 (word as NSString).length // 10 var decomposed:Character = "\u{1112}\u{1161}\u{11ab}" // "한" 由三个Unicode标量组成,但是一个字符 var decomposedString:String = "\u{1112}\u{1161}\u{11ab}" // 用 for in 遍历字符串 for c in decomposedString.characters{ print(c) // "한", 只有一个字符 } //用下标遍历 let end = decomposedString.endIndex // 3 最后一个Unicode标量的位置+1 var i = decomposedString.startIndex // 0 i.advancedBy(1) // 3 for(var j = decomposedString.startIndex;j<end;j=j.successor()){ print(decomposedString[j]) } let NSdecomposedString = decomposedString as NSString for var i = 0; i < NSdecomposedString.length; i++ { //3 times (4370, 4449, 4523) print(NSdecomposedString.characterAtIndex(i)) } let u1 = UnicodeScalar(4370) // 4370 let u2 = UnicodeScalar(4449) // 4449 let u3 = UnicodeScalar(4523) // 4523 let c1 = Character(u1) // ᄒ let c2 = Character(u2) // ᅡ let c3 = Character(u3) // ᆫ let c = Character("\(c1)\(c2)\(c3)") // 한
swift中字符串的比较会 比对每个字符的语义和最终表现形式。而不是比对构成字符的标量
let word1 = "caf\u{e9}" // "café" \u{e9} 带音调的拉丁字母e let word2 = "caf\u{65}\u{301}" // "café" \u{65}\u{301} 拉丁字母e + 一个重音符号 word1 == word2 // true // 转化为 NSString 后比对 (word1 as NSString) == (word2 as NSString) // false let a1 = "\u{41}" // 拉丁字母 A let a2 = "\u{0410}" // 斯拉夫字母 A a1 == a2 // false
子字符串:无法用Int下标来访问String中的字符或字串,而使用String.Index
var imageStr = "🐶🐱🐭🐰" let start = imageStr.startIndex.advancedBy(2) //4 let end = imageStr.startIndex.advancedBy(3) //6 let range = start..<end //4..<6 print(range.debugDescription) // Range(4..<6) print(imageStr[range]) //🐭 print(imageStr.substringFromIndex(start))//🐭🐰 print(imageStr.rangeOfString("🐭"))// Optional(Range(4..<6)) print(imageStr.substringToIndex(start))//"🐶🐱" (imageStr as NSString).substringFromIndex(1)//�🐱🐭🐰"
var imageStr = "s🐶🐱🐭🐰" //下标:swift中数组,字符串都支持 区间做下标 extension String { subscript (r: Range<Int>) -> String { get { let startIndex = self.startIndex.advancedBy(r.startIndex) let endIndex = startIndex.advancedBy(r.endIndex - r.startIndex) return self[Range(start: startIndex, end: endIndex)] } } } var s = "Hello, playground" print(s[0...5]) // ==> "Hello," print(s[0..<5]) // ==> "Hello" imageStr[1..<2] //🐶
编码
let S1:String = "one 🐱🐭🇨🇳" //swift 1.2时 ᄒ ᅡ ᆫ三个标量还是三个字符,2.1自动替换为한 let a = "ᄒ" let b = "ᅡ" let c = "ᆫ" let S2:String = "\(a)\(b)\(c)"//"한" let view1:String.UnicodeScalarView = S1.unicodeScalars //one 🐱🐭🇨🇳 let view2:String.UTF16View = S1.utf16 //one 🐱🐭🇨🇳 let view3:String.UTF8View = S1.utf8 //one 🐱🐭🇨🇳 view3.debugDescription //UTF8View("one 🐱🐭🇨🇳") // utf-8编码 for i in S1.utf8 {//遍历utf-8编码的字符串 // 前4个ascii字符各占一个字节 111 110 101 32 // 中间两个emoji表情240 159 144 177, 240 159 144 173 // 最后一个emoji表情240 159 135 168, 240 159 135 179 print(i) // 20 times } for i in S2.utf8 {//遍历utf-8编码的字符串 // ᄒ 225 132 146 // ᅡ 225 133 161 // ᆫ 225 134 171 print(i) } // utf-16编码 for i in S1.utf16 {//遍历utf-16编码的字符串 // 前4个ascii字符各占一个字节 111 110 101 32 // 中间两个emoji表情 55357 56369, 55357 56365 // 最后一个emoji表情 55356 56808, 55356 56819 print(i) // 12个数字 12 times } let NSS1 = S1 as NSString for(var i=0;i<NSS1.length;i++){ print(NSS1.characterAtIndex(i)) // 12个数字 12 times } for i in S2.utf16 {//遍历utf-16编码的字符串 //4370 4449 4523 print(i) } let NSS2 = S2 as NSString //한 for(var i=0;i<NSS2.length;i++){ print(NSS2.characterAtIndex(i)) // 54620 } // unicode标量 for i in S1.unicodeScalars {//遍历unicode标量 // 最后一个emoji表情由两个unicode标量组成 print(i) // one 🐱🐭🐰🇨 🇳 8times } for i in S2.unicodeScalars {//遍历unicode标量 //ᄒ ᅡ ᆫ 3 times print(i) } //遍历字符 for i in S1.characters {//遍历字符 print(i) // one 🐱🐭🇨🇳 7 times } for i in S2.characters {//遍历字符 print(i) // 한 1 times }
与c语言字符串的转换
// 以某种编码取到 c String //[72, 101, 108, 108, 111, 44, 32, 112, 108, 97, 121, 103, 114, 111, 117, 110, 100, 0] let xxxx = "Hello, playground".cStringUsingEncoding(NSASCIIStringEncoding) // 从cString转回String //"Hello, playground" String.fromCString(xxxx!) let anInt = 10 let aChar:Character = "a" if var xx = "\(aChar)".cStringUsingEncoding(NSASCIIStringEncoding){ xx[0] = anInt + xx[0] // 107 let s:String = String.fromCString(xx)! // "k" } let yy = String.cStringUsingEncoding("🐱") //UInt -> Optional<Array<Int8>> let code1 = yy(NSUTF8StringEncoding)//[-16, -97, -112, -79, 0] let code2 = yy(NSUTF16StringEncoding)//[61, -40, 49, -36, 0] let code3 = yy(NSASCIIStringEncoding)//nil String.fromCString(code1!) // "🐱" ,c语言字符是ascii编码 String.fromCString(code2!) // nil String.fromCString(code3!) //fatal error: unexpectedly found nil while unwrapping an Optional value
流程控制
流程控制语句中条件表达式的小括号 可以省略, 但 代码块的 大括号不能再省略
if let ,if var 语句(可选绑定,如果可选类型的变量或常量有值,则会赋值给另一个临时变量或常量)
// 自动拆封,简化了判别代码 func foo()->Int?{ return 1 } func bar()->Int?{ return 2 } func baz(a:Int,b:Int)->String?{ return "ss" } if let a = foo(), b = bar() where a < b, let c = baz(a,b) { println(c) }
也可用if var 声明为变量
var aaa:Int? = 12 if var bb = aaa{ bb++ println(bb) }
分支语句 switch有较大变化
3.1 swift中switch语句可以使用几乎所有数据类型,而C中只有整数,c#也仅支持基本数据类型。
3.2 c中的取值是离散的(case后为常量表达式),而Swift中可以离散 也可以是连续的范围区间 还可用 let where 进行过滤( if let 形式)
3.3 swift 中case 分支 无需添加 break 语句,分支执行完会跳出跳出switch,要连通多个case 需要用到 fallthrough 语句
但细分下来,swift中switch与c#是类似的,不同之处在于可以使用元组,区间,以及类似 if let where 的结构,以及break的默认添加
//类似c中的离散整型 let testscore = 86 var grade:Character switch testscore / 10 { case 9: grade = "优" case 8: grade = "良" case 7,6: grade = "中" default : grade = "差" } //浮点 let value = 1.000 var desc:String switch value { case 0.0: desc = "最小值" case 0.5: desc = "中值" case 1.0: desc = "最大值" default : desc = "其他值" } //字符 let level= "优" var desc:String switch level { case "优": desc = "90分以上" case "良": desc = "80分~90分" case "中": desc = "60~80分" case "差": desc = "低于60分" default : desc = "无法判断" } //区间 let testscore = 86 var grade:Character switch testscore { case 90...100 : grade = "优" case 80..<90: grade = "良" case 60..<80: grade = "中" default : grade = "差" } //元组 var student = (id:"1002",name:"李四",age:32,ChineseScore:80,EnglishScore:79) var grade:String switch student { case (_,_,_,90...100,90...100) : grade = "优" case (_,_,_,80..<90,80..<90) : grade = "良" case (_,_,_,60..<80,60..<80): grade = "中" case (_,_,_,60..<80,90...100),(_,_,_,90...100,60..<80): grade = "偏科" case (_,_,_,0..<80,90...100),(_,_,_,90...100,0..<80): grade = "严重偏科" default : grade = "无" } //元组 值绑定 var student = (id:"1002",name:"李四",age:32,ChineseScore:80,EnglishScore:79) var grade:String switch student { case (_,_, let age,90...100,90...100) : if (age > 30) { grade = "老优" } //大括号省略了会报错 else { grade = "小优" } case (_,_,_,80..<90,80..<90) : grade = "良" case (_,_,_,60..<80,60..<80): grade = "中" case (_,_,_,60..<80,90...100),(_,_,_,90...100,60..<80): grade = "偏科" case (_,_,_,0..<80,90...100),(_,_,_,90...100,0..<80): grade = "严重偏科" default : grade = "无" } //元组 值绑定 情况下, 使用 where 语句进行条件过滤 var student = (id:"1002",name:"李四",age:32,ChineseScore:80,EnglishScore:79) var grade:String switch student { case (_,_, let age,90...100,90...100) where age < 30 : grade = "小优" case (_,_,_,90...100,90...100) : grade = "老优" case (_,_,_,80..<90,80..<90) : grade = "良" case (_,_,_,60..<80,60..<80): grade = "中" case (_,_,_,60..<80,90...100),(_,_,_,90...100,60..<80): grade = "偏科" case (_,_,_,0..<80,90...100),(_,_,_,90...100,0..<80): grade = "严重偏科" default : grade = "无" } let yetAnotherPoint = (1, -1) switch yetAnotherPoint { case let (x, y) where x == y: println("(\(x), \(y)) is on the line x == y") case let (x, y) where x == -y: println("(\(x), \(y)) is on the line x == -y") case let (x, y): println("(\(x), \(y)) is just some arbitrary point") } // "(1, -1) is on the line x == -y"
其他循环 while, for , for in ,与其他语言用法上几本没有变动,do while 2.0后改为repeat{}while(), 关键字do用于错误处理
跳转 return ,break , continue, fallthrough,没有goto了
fallthrough是新增关键字,用于switch中
break , continue 也有变化
outFor: for a in 1...5{ for i in 1...10{ if i == 2{ //continue //45 times continue outFor // 5 times } println("\(a):\(i)") } } outFor: for a in 1...5{ for i in 1...10{ if i == 2{ // break // 5 times break outFor // 1:1 } println("\(a):\(i)") } }
break 在switch 中,每个case一旦匹配,都会有默认的break,想如同c 般跨越多个case,需要使用fallthrough,但如果case匹配后没有任何操作,则需要主动加一个 break
//类似c中的离散整型 let testscore = 86 var grade:Character switch testscore / 10 { case 9: break//grade = "优" case 8: fallthrough//grade = "良" case 7,6: grade = "中" default : grade = "差" }
集合
swift 中集合都是由结构实现的,所以都属于值引用,这和objective-c 是不一样的
数组 Array 关联 NSArray
- var a: Array<Int> 等价于 var a: [Int]
- var a: Array<Int> = [1,2]
- var a = [Int]()
- var threeDoubles = [Double](count:3,repeatedValue:0.0) //重复值的初始化
- 数组创建完成后,清空元素,a = []
//未指明数组中的数据类型,下列会自动推导为[AnyObject],等同于NSArray var array = [0,"","ssf",4] // 访问数组元素 print(array[0]) //"0" print(array[1...2]) //["", "ssf"] print(array.first) // 0 print(array.last) // 4 // 移除元素 let temp = array.removeAtIndex(0) print(array) // [, ssf, 4] print(temp) // "0" // 清空元素 array = [] //0 elements // 新元素 array.append(4) //[4] array.appendContentsOf([22,44]) //[4, 22, 44] array += ["df",4.5] //[4, 22, 44, "df", 4.5] array.insert("3",atIndex:array.count) //[4, 22, 44, "df", 4.5, "3"] array[1...1] = [4,5,6] //[4, 4, 5, 6, 44, df, 4.5, 3] array[0...2] = [1] //[1, 6, 44, df, 4.5, 3] array.insert(2, atIndex: 1) //[1, 2, 6, 44, "df", 4.5, "3"] array.removeLast() //[1, 2, 6, 44, "df", 4.5] array.removeFirst(3) //[44, "df", 4.5] array.removeFirst() //["df", 4.5] // 数组的值引用 测试 var array2 = array //[4, 4, 5, 6, 44, "df", 4.5, "3"] array[0] = 1 print(array) //[1, 4, 5, 6, 44, df, 4.5, 3]" print(array2) //[4, 4, 5, 6, 44, df, 4.5, 3] //其他属性 array.capacity // 8 array.count // 8 array.description array.debugDescription array.endIndex // 8 array.isEmpty // 迭代器 var gene = array.generate() gene.next() // 遍历 for x in array { print(x) } for (index,value) in array.enumerate() { print("item\(index + 1):\(value)") } for var i = 0; i < array.count; i++ { print("item\(i + 1):\(array[i])") } // ======================= var array3 = [1,5,3] // 拼接字符串 print(array3.map{"$\($0)" + ".00"}.joinWithSeparator(" - ")) //$1.00 - $5.00 - $3.00 //// 拼接数组 2.0不能用了 //array3.join([[],[],[]]) //[1, 5, 3, 1, 5, 3] //array3.join([[4,6,7],[1,2],[3,4,6]]) //[4, 6, 7, 1, 5, 3, 1, 2, 1, 5, 3, 3, 4, 6] // 排序 // 得到一个新数组 array3.sort( {$0 > $1} ) // 默认升序 array3.sort() // 对原数组修改 array3.sortInPlace(){ return $0 > $1 } // 默认升序 array3.sortInPlace() // 得到一个倒序数组 array3.reverse() //[5, 3, 1] //map 数组按一定规则转为另一数组 //map函数会对每一条输入进行指定的操作,然后为每一条输入返回一个对象 //而flatMap函数则是两个操作的集合——正是“先映射后扁平化”: //操作1:同map函数一样:对每一条输入进行指定的操作,然后为每一条输入返回一个对象 //操作2:最后将所有对象合并为一个对象 array3.flatMap{ [$0 + 4, $0 * 2] }//[5, 2, 7, 6, 9, 10] //filter 筛选 array3.filter{ $0 <= 3 }//[1,3] //reduce将数组中的值整合到某个独立对象里,有两个参数一个原始值,一个闭包,闭包返回的结果也就是下一轮循环的原始值 // 闭包的两个参数,左侧为原始值,右侧为当前数组元素 array3.reduce(2, combine: {$0 + $1} ) //11 array3.reduce(2, combine: +)//操作符本身就是一个函数 //11
集合 Set 关联 NSSet
// 集合set,无序,元素不能重复 // 集合中的元素要求都有hashvalue,swift 中所有基本数据类型都是可哈希的 var vowel:Set<Character> = ["a","e","i","o","u"] var evenSet:Set = [2,4,5,6] var set = Set<Int>() set.insert(1) set.insert(1) set.insert(2) //{2, 1} set.contains(2) set.count set.debugDescription set.description set.first set.insert(3) set.removeFirst() for i in set{ print(i) } for i in set.sort(){ print(i) } // 集合运算 var setA:Set = [1,2,3,4,5,6] var setB:Set = [4,5,6,7,8,9] // 交集 let interSetAB = setA.intersect(setB) //{5, 6, 4} let exclusiveSetAB = setA.exclusiveOr(setB) //{9, 7, 2, 3, 1, 8} let unionSetAb = setA.union(setB) //{2, 4, 9, 5, 6, 7, 3, 1, 8} let aSubstractB = setA.subtract(setB) //{2, 3, 1} var setC:Set = [1,2,3] if setA == setB{ } setA.isSubsetOf(setC) //false setA.isSupersetOf(setC) //true setC.isDisjointWith(setB) //true setA.isStrictSupersetOf(setC) //true setC.isStrictSubsetOf(setA) //true
字典 Dictionary 关联 NSDictionary
var a: Dictionary<Int,String> = [101: "张飞", 102:"关羽"]
var b = Dictionary<Int,String>()
var c = [String : (NSCache, UIView)]()
var formats : [String : (NSCache, UIView)] = [:]
字典中所有能作为键的类型,必须是可以哈希化(:Hashable)的类型,即必须提供一个可以计算出自身哈希值的方法。
var a = [101: "张飞", 102:"关羽"] a[103] = "刘备" print(a) let dismissOne = a.removeValueForKey(101) if dismissOne != nil { print("\(dismissOne!)") } print(a) a[102] = nil print(a) a[103] = "张飞" print(a) let replaceOne = a.updateValue("赵云",forKey: 103) print("\(replaceOne )") print(a) a[111] = "sdfsf" a.removeValueForKey(103) //遍历 for vkey in a.keys.sort() { print("\(vkey )") } for vvalue in a.values { print("\(vvalue )") } for (id,name) in a { print("\(id) : \(name)") }