标签:
原文参考
https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/GuidedTour.html#//apple_ref/doc/uid/TP40014097-CH2-ID1
1、let关键字声明一个常量,var关键字声明一个变量,每条语句后面可以不接分号。
var myVariable = 42 myVariable = 50 let myConstant = 42
2、常量或变量的数据类型不必显示声明,初始化赋值时编译器会推断数据类型。当然,也可以显示声明数据类型。
let implicitInteger = 70 let implicitDouble = 70.0 let explicitDouble: Double = 70
3、不同类型数据之间不存在隐式转换,如果需要转换,则需要进行显示声明。
let label = "The width is " let width = 94 let widthLabel = label + String(width)
4、使用\()可以将数值插入string变量中
let apples = 3 let oranges = 5 let appleSummary = "I have \(apples) apples." let fruitSummary = "I have \(apples + oranges) pieces of fruit."
5、用[]创建array类型和dictionary类型的数据,可以用index或key作为索引,最后一个元素后面允许接一个逗号。
var shoppingList = ["catfish", "water", "tulips", "blue paint"] shoppingList[1] = "bottle of water" var occupations = [ "Malcolm": "Captain", "Kaylee": "Mechanic", ] occupations["Jayne"] = "Public Relations"
6、声明一个空的array或dictionary
let emptyArray = [String]()
let emptyDictionary = [String: Float]()
如果元素类型已知,也可以如下赋空值:
shoppingList = []
occupations = [:]
1、if和switch进行条件控制,for
-in
, for
, while
, and 和repeat
-while进行循环控制
条件语句可以不加括号,但控制段的{}是必须的
条件语句的值必须是Boolean类型,不存在其他类型与Boolean类型的隐式转换。
let individualScores = [75, 43, 103, 87, 12] var teamScore = 0 for score in individualScores { if score > 50 { teamScore += 3 } else { teamScore += 1 } } print(teamScore)
2、可以用if和let来处理值可能为空的情况,这些值是optional类型,在声明数据类型后面加一个问号,就声明了一个optional类型的值,其可能有值,也可能为nil。
var optionalString: String? = "Hello" print(optionalString == nil) var optionalName: String? = "John Appleseed" var greeting = "Hello!" if let name = optionalName { greeting = "Hello, \(name)" }
如果optionalName的值为nil,则判断语句的值为false,否则,判断语句为真,optionalName的unwrapped值将赋值给name变量。
3、switch支持多种数据类型和多种比较操作,并不局限于整数类型
let vegetable = "red pepper" switch vegetable { case "celery": print("Add some raisins and make ants on a log.") case "cucumber", "watercress": print("That would make a good tea sandwich.") case let x where x.hasSuffix("pepper"): print("Is it a spicy \(x)?") default: print("Everything tastes good in soup.") }
注意这里的let以一定格式来为x赋值。
switch中,执行完某一个case中的语句后不再继续执行下面case,所以不必显示的添加break语句。
4、for-in中可以使用键值对来对dictionary进行迭代,由于dictionary是乱序的,所以迭代顺序是任意的。
let interestingNumbers = [ "Prime": [2, 3, 5, 7, 11, 13], "Fibonacci": [1, 1, 2, 3, 5, 8], "Square": [1, 4, 9, 16, 25], ] var largest = 0 for (kind, numbers) in interestingNumbers { for number in numbers { if number > largest { largest = number } } } print(largest)
5、while 和repeat-while
var n = 2 while n < 100 { n = n * 2 } print(n) var m = 2 repeat { m = m * 2 } while m < 100 print(m)
6、可以用..<来表示循环条件的范围,也可以显示写出
var firstForLoop = 0 for i in 0..<4 { firstForLoop += i } print(firstForLoop) var secondForLoop = 0 for var i = 0; i < 4; ++i { secondForLoop += i } print(secondForLoop)
用..<表示一个半闭区间,用...表示一个闭合区间
1、用func关键字声明一个函数,括号中声明参数列表,用->声明函数返回类型
func greet(name: String, day: String) -> String { return "Hello \(name), today is \(day)." } greet("Bob", day: "Tuesday")
2、用一个数组来使函数返回多个值,这些值用名字或索引值区分。
func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) { var min = scores[0] var max = scores[0] var sum = 0 for score in scores { if score > max { max = score } else if score < min { min = score } sum += score } return (min, max, sum) } let statistics = calculateStatistics([5, 3, 100, 3, 9]) print(statistics.sum) print(statistics.2)
3、函数的参数可以是不定数目的,把他们放入一个array即可。
func sumOf(numbers: Int...) -> Int { var sum = 0 for number in numbers { sum += number } return sum } sumOf() sumOf(42, 597, 12)
4、函数之间可以嵌套,可以使用内部函数来减小函数的复杂度和长度。
func returnFifteen() -> Int { var y = 10 func add() { y += 5 } add() return y } returnFifteen()
5、函数的返回值可以是一个函数。
func makeIncrementer() -> (Int -> Int) { func addOne(number: Int) -> Int { return 1 + number } return addOne } var increment = makeIncrementer() increment(7)
6、函数的参数可以是一个函数。
func hasAnyMatches(list: [Int], condition: Int -> Bool) -> Bool { for item in list { if condition(item) { return true } } return false } func lessThanTen(number: Int) -> Bool { return number < 10 } var numbers = [20, 19, 7, 12] hasAnyMatches(numbers, condition: lessThanTen)
7、函数实际上时闭包的一种特殊情况——代码块可以之后调用。闭包中的代码可以访问其范围内的变量和函数,甚至是其他范围内。可以用{}直接声明一个没有名字的Closure,用in关键字来分开参数列表返回类型和函数主体。
numbers.map({ (number: Int) -> Int in let result = 3 * number return result })
8、有一些技巧可以使闭包更为精简。
当闭包的类型已知,例如委托调用,你可以省略参数类型或返回类型,单一态声明的闭包默认返回该声明变量的值。
let mappedNumbers = numbers.map({ number in 3 * number }) print(mappedNumbers)
可以用数字代替名字来声明参数,闭包作为函数的最后一个参数时可以立即显示在()中,如果闭包作为函数的唯一参数,则()可以省略。
let sortedNumbers = numbers.sort { $0 > $1 } print(sortedNumbers)
1、创建一个类
class Shape { var numberOfSides = 0 func simpleDescription() -> String { return "A shape with \(numberOfSides) sides." } }
2、创建类的一个实例
var shape = Shape() shape.numberOfSides = 7 var shapeDescription = shape.simpleDescription()
3、上面的类缺少初始化器,用init来声明一个初始化器。
class NamedShape { var numberOfSides: Int = 0 var name: String init(name: String) { self.name = name } func simpleDescription() -> String { return "A shape with \(numberOfSides) sides." } }
每一个属性都要在声明时或初始化器中进行赋一个初值。
4、使用deinit来清理一些当对象被清理时需要清理的变量。
5、创建一个子类
override声明子类中复写父类的方法。
class Square: NamedShape { var sideLength: Double init(sideLength: Double, name: String) { self.sideLength = sideLength super.init(name: name) numberOfSides = 4 } func area() -> Double { return sideLength * sideLength } override func simpleDescription() -> String { return "A square with sides of length \(sideLength)." } } let test = Square(sideLength: 5.2, name: "my test square") test.area() test.simpleDescription()
6、属性可以有setter和getter
class EquilateralTriangle: NamedShape { var sideLength: Double = 0.0 init(sideLength: Double, name: String) { self.sideLength = sideLength super.init(name: name) numberOfSides = 3 } var perimeter: Double { get { return 3.0 * sideLength } set { sideLength = newValue / 3.0 } } override func simpleDescription() -> String { return "An equilateral triangle with sides of length \(sideLength)." } } var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle") print(triangle.perimeter) triangle.perimeter = 9.9 print(triangle.sideLength)
setter中默认传入的值的名字是newValue,可以在set后面用()声明一个自定义的名字。
7、用willSet和didSet,可以使你不必计算属性,只需要提供赋值之后的代码。这些代码会在初始化器外部的变量的值发生变化时执行。例如,下面的这个类就保证了三角形的边长和四边形的边长相同。
class TriangleAndSquare { var triangle: EquilateralTriangle { willSet { square.sideLength = newValue.sideLength } } var square: Square { willSet { triangle.sideLength = newValue.sideLength } } init(size: Double, name: String) { square = Square(sideLength: size, name: name) triangle = EquilateralTriangle(sideLength: size, name: name) } } var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape") print(triangleAndSquare.square.sideLength) print(triangleAndSquare.triangle.sideLength) triangleAndSquare.square = Square(sideLength: 50, name: "larger square") print(triangleAndSquare.triangle.sideLength)
9、处理可选值类型
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square") let sideLength = optionalSquare?.sideLength
如果可选值为nil,则?后面的代码被忽略,整个表达式的值为nil。
1、enum声明枚举类型
enum Rank: Int { case Ace = 1 case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten case Jack, Queen, King func simpleDescription() -> String { switch self { case .Ace: return "ace" case .Jack: return "jack" case .Queen: return "queen" case .King: return "king" default: return String(self.rawValue) } } } let ace = Rank.Ace let aceRawValue = ace.rawValue
2、用init?(rawValue:)来初始化一个枚举类型的实例变量
if let convertedRank = Rank(rawValue: 3) { let threeDescription = convertedRank.simpleDescription() }
3、枚举的原始数值类型是实际的值类型,如果找不到有意义的类型,可以不进行类型声明。
enum Suit { case Spades, Hearts, Diamonds, Clubs func simpleDescription() -> String { switch self { case .Spades: return "spades" case .Hearts: return "hearts" case .Diamonds: return "diamonds" case .Clubs: return "clubs" } } } let hearts = Suit.Hearts let heartsDescription = hearts.simpleDescription()
如果没有声明enum的数据类型,则Suit.Hearts将通过全称被引用给hearts变量。
4、struct声明一个结构类型
struct Card { var rank: Rank var suit: Suit func simpleDescription() -> String { return "The \(rank.simpleDescription()) of \(suit.simpleDescription())" } } let threeOfSpades = Card(rank: .Three, suit: .Spades) let threeOfSpadesDescription = threeOfSpades.simpleDescription()
5、Associated values和Raw Values
每个枚举的成员变量的值可以绑定不同类型的值。例如:
enum ServerResponse { case Result(String, String) case Error(String) } let success = ServerResponse.Result("6:00 am", "8:09 pm") let failure = ServerResponse.Error("Out of cheese.") switch success { case let .Result(sunrise, sunset): let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)." case let .Error(error): let serverResponse = "Failure... \(error)" }
1、protocol关键字声明一个协议
protocol ExampleProtocol { var simpleDescription: String { get } mutating func adjust() }
2、类、枚举和结构都可以实现协议
class SimpleClass: ExampleProtocol { var simpleDescription: String = "A very simple class." var anotherProperty: Int = 69105 func adjust() { simpleDescription += " Now 100% adjusted." } } var a = SimpleClass() a.adjust() let aDescription = a.simpleDescription struct SimpleStructure: ExampleProtocol { var simpleDescription: String = "A simple structure" mutating func adjust() { simpleDescription += " (adjusted)" } } var b = SimpleStructure() b.adjust() let bDescription = b.simpleDescription
注意,mutating关键字标记一个修改结构的方法。而类中的方法都可以修改类,所以不必声明mutating。
3、使用extension来扩展一个已知类的功能,可以扩展一个协议或者你引用的类。
extension Int: ExampleProtocol { var simpleDescription: String { return "The number \(self)" } mutating func adjust() { self += 42 } } print(7.simpleDescription)
4、可以用协议的名字来创建一个集合,集合中的对象类型不同但是都遵守同一个协议。当你处理一个协议类型的变量时,协议外部定义的变量不可用。
let protocolValue: ExampleProtocol = a print(protocolValue.simpleDescription) // print(protocolValue.anotherProperty) // Uncomment to see the error
尽管protocolValue运行时的类型为SimpleClass,编译器把它当做ExampleProtocol变量,这意味着你无法使用这个类中实现协议的代码之外的变量和属性。
1、创建一个泛型函数或类型
func repeatItem<Item>(item: Item, numberOfTimes: Int) -> [Item] { var result = [Item]() for _ in 0..<numberOfTimes { result.append(item) } return result } repeatItem("knock", numberOfTimes:4)
2、也可以构造泛型的枚举、类、结构和方法。
// Reimplement the Swift standard library‘s optional type enum OptionalValue<Wrapped> { case None case Some(Wrapped) } var possibleInteger: OptionalValue<Int> = .None possibleInteger = .Some(100)
3、在类型名字后面用where来指定一些必要元素,来获得实现一定协议的类型、相同的两个类型或者有某个特定子类的类型。
func anyCommonElements <T: SequenceType, U: SequenceType where T.Generator.Element: Equatable, T.Generator.Element == U.Generator.Element> (lhs: T, _ rhs: U) -> Bool { for lhsItem in lhs { for rhsItem in rhs { if lhsItem == rhsItem { return true } } } return false } anyCommonElements([1, 2, 3], [3])
<T: Equatable>和<T where T: Equatable>是等效的。
标签:
原文地址:http://www.cnblogs.com/tt2015-sz/p/4797959.html