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

 

posted @ 2015-01-09 16:55  随心~  阅读(2585)  评论(0编辑  收藏  举报