目录[-]

  • Hello world - Swift
  • 简单赋值
  • 控制流
  • 函数与闭包
  • 对象和类
  • 枚举与结构
  • 协议和扩展
  • 泛型

2014.6.3日,苹果公布最新编程语言Swift,Swift是一种新的编程语言,用于iOS和OS X应用的开发,没有C的兼容性限制,Swift采用安全的编程模式,增加了现代功能,使编程变得容易,更灵活,更有趣,Swift的重新设计,依靠成熟和 备受喜爱的Cocoa, Cocoa Touch 框架,是重新构想软件如何开发的机会。

  • Swift官网
  • 关于Swift

以下为语法介绍

原文:A Swift Tour

翻译:http://blog.qunee.com/2014/06/swift语法介绍/

Hello world - Swift

传统建议新语言的第一个程序是打印“Hello world”,对于Swift是下面的一行代码

println("Hello, world")

如果你用C或者Objective-C编写过代码,这段句法会感觉熟悉,在Swift中,这是一行完整的代码,不需要引入单独的库比如输入输出或者字符串 操作,在全局作用域下编写的代码会作为程序的入口,所以你也不需要main函数,你同样不需要在每段代码后面写分号 这次tour将教你使用Swift编程的足够信息,完成各种编程任务,如果你有不理解也不用担心,本次演示的任何内容在后面的章节中都有详细的介绍

简单赋值

使用 let定义常量,使用var定义变量,常量的值不需要在编译的时候知道,但你必须只设置一次,这意味着你可以使用常量来定义这样的数值:一次决定,多处使用

var myVariable = 42
myVariable = 50
let myConstant = 42

常量和变量必须为你指定的类型,但是你并不需要总是显示的指定类型,创建变量或者常量时,直接提供一个数值让编译器知道他的类型,下面的例子中,编译器指 定myVariable为整型,因为他的初始值是一个整型 如果初始值没有足够的信息(比如没有初始值),可以在变量后面指定一个类型,通过冒号分割

let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70

数值不会隐式的转换成另一种类型,你必须转换成另一种类型,显式的指定类型

let label = "The width is "
let width = 94
let widthLabel = label + String(width)

有更简单的方式让字符串中包含数值:在小括号中编写数值,并在括号之前写上(\),如下例:

let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit."

使用中括号[]创建数组和字典,通过序号或者key来访问集合中的元素

var shoppingList = ["catfish", "water", "tulips", "blue paint"]
shoppingList[1] = "bottle of water"var occupations = ["Malcolm": "Captain","Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"

创建一个空的数组或者字典,使用下面的初始化语法

let emptyArray = String[]()
let emptyDictionary = Dictionary<String, Float>()

如果类型信息可以被断定,你可以写一个空数组[],或者一个空的字典[:],比如当你为一个变量设置新的值,或者给函数传递一个参数

shoppingList = []   // Went shopping and bought everything.

控制流

使用if和switch判断条件,使用for-in, for, while和do-while 循环,条件或者循环参数的小括号是可选的,但是主体的花括号是必须的

let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0
for score in individualScores {if score > 50 {teamScore += 3} else {teamScore += 1}
}
teamScore

if声明中,条件必须是Boolean表达式,这意味着类似 if score{…}de的写法是错误的,不会隐式的与0比较 你可以将if和let结合使用,这意味着数值为可选,可选值可能是一个数值也可能是nil表示值缺失,在类型后面标记问号(?)表示这个值为可选

var optionalString: String? = "Hello"
optionalString == nilvar optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {greeting = "Hello, \(name)"
}

如果可选值为nil,条件为flase,代码会被跳过,否则会进入并设置常量,使得变量在代码体中可用 Switch支持任何类型和多种操作符,不限于整型和相等操作

let vegetable = "red pepper"
switch vegetable {
case "celery":let vegetableComment = "Add some raisins and make ants on a log."
case "cucumber", "watercress":let vegetableComment = "That would make a good tea sandwich."
case let x where x.hasSuffix("pepper"):let vegetableComment = "Is it a spicy \(x)?"
default:let vegetableComment = "Everything tastes good in soup."
}

在执行完匹配的条件后,程序将跳出选择条件,不会继续到下一个条件,所以不需要在每个条件中指定break

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}}
}
largest

使用while重复一段代码块知道条件改变,循环条件也可以放在后面,这样可以确保循环被至少调用一次

var n = 2
while n < 100 {n = n * 2
}
nvar m = 2
do {m = m * 2
} while m < 100
m

可以使用序号遍历,既可以使用.. 指定序号范围,也可以写完整的表达式

var firstForLoop = 0
for i in 0..3 {firstForLoop += i
}
firstForLoopvar secondForLoop = 0
for var i = 0; i < 3; ++i {secondForLoop += 1
}
secondForLoop

函数与闭包

使用 func声明一个函数,通过函数名和参数调用一个函数,使用 -> 声明函数返回类型

func greet(name: String, day: String) -> String {return "Hello \(name), today is \(day)."
}
greet("Bob", "Tuesday")

使用值组表示多个数值返回

func getGasPrices() -> (Double, Double, Double) {return (3.59, 3.69, 3.79)
}
getGasPrices()

函数还可以设置可变参数,会将他们整合到一个数组中

func sumOf(numbers: Int...) -> Int {var sum = 0for number in numbers {sum += number}return sum
}
sumOf()
sumOf(42, 597, 12)

函数可以嵌套,嵌套函数可以访问外部函数的声明的变量,对于很长或者复杂的函数,你可以使用嵌套函数来组织代码

func returnFifteen() -> Int {var y = 10func add() {y += 5}add()return y
}
returnFifteen()

函数也是一种类型(第一等类型),这意味着你可以返回一个函数作为函数返回值

func makeIncrementer() -> (Int -> Int) {func addOne(number: Int) -> Int {return 1 + number}return addOne
}
var increment = makeIncrementer()
increment(7)

函数还可以作为另一个函数的参数

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, lessThanTen)

闭包实际上是函数的一种特殊形式,你可以写一个闭包,使用花括号({})包裹代码,没有函数名,使用 in 来分隔传入参数和返回类型

numbers.map({(number: Int) -> Int inlet result = 3 * numberreturn result})

你可以选择更简洁的闭包方式,当一个闭包类型已知,比如某个委托的回调函数,你可以省略它的参数和返回类型,单声明的闭包默认会返回这个唯一的声明变量

numbers.map({ number in 3 * number })

你可以通过序号替代名称来访问参数,这种方式尤其适合非常短的闭包

sort([1, 5, 3, 12, 2]) { $0 > $1 }

对象和类

使用class创建类,类中的属性声明与常量和变量声明一样,只是他位于这个类的上下文中,同样的函数和方法声明也一样

class Shape {var numberOfSides = 0func simpleDescription() -> String {return "A shape with \(numberOfSides) sides."}
}

创建一个类实例,使用类名加括号,使用点操作符访问实例的属性和方法

var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()

这个版本的Shape类缺少一些重要的东西:用于初始化这个类的构造器,可以使用init来创建

class NamedShape {var numberOfSides: Int = 0var name: Stringinit(name: String) {self.name = name}func simpleDescription() -> String {return "A shape with \(numberOfSides) sides."}
}

注意,使用self来就区别传入参数的name和自身的name属性,构造器中的构造参数与函数参数的传递方式一样,所有的属性都需要指定值,可以在声明 时指定(如numberOfSides)也可以在构造函数中指定(如name) 如果你希望在对象被回收时执行清除动作,可以使用deinit创建一个析构器 子类名包含在父类名称之后,使用冒号分隔,类不需要从任何标准的根类继承,所以你可以包含或者忽略父类 子类中的重写方法需要标记上override,如果没有 override,会被编译器检查出错,同样编译器还会检测带override标志的函数是否真的存在于父类中

class Square: NamedShape {var sideLength: Doubleinit(sideLength: Double, name: String) {self.sideLength = sideLengthsuper.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()

除了简单属性外,属性还可以具备getter和setter方法

class EquilateralTriangle: NamedShape {var sideLength: Double = 0.0init(sideLength: Double, name: String) {self.sideLength = sideLengthsuper.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 triagle with sides of length \(sideLength)."}
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
triangle.perimeter
triangle.perimeter = 9.9
triangle.sideLength

在perimeter的setter函数中,新值隐式的命名为newValue,你也可以在set后面的括号中提供一个显式的名称 注意EquilateralTriangle类的构造函数有三步: 1、为子类声明的属性设置值 2、调用父类构造器 3、改变父类定义的属性值,如何用到方法或者getter, setter的工作可以在这之后执行 如果你不需要控制属性,但需要在属性设置前后做些处理,可以使用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")
triangleAndSquare.square.sideLength
triangleAndSquare.triangle.sideLength
triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
triangleAndSquare.triangle.sideLength

类中的方法与函数有一个重要区别,函数参数名只在函数体中使用,但方法的参数名在调用方法时也需要(除了第一个参数),默认不论是调用方法时还是在方法内,方法的参数名都是相同的,你可以指定另一个名称用于方法内

class Counter {var count: Int = 0func incrementBy(amount: Int, numberOfTimes times: Int) {count += amount * times}
}
var counter = Counter()
counter.incrementBy(2, numberOfTimes: 7)

当使用可选参数时,可以在方法或者属性操作符前加上(?),如果?前是nil,所有?后面的内容都会忽略,整个表达式的值为nil

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength

枚举与结构

使用enum创建枚举,与类或者其他可命名的类型一样,枚举可以定义方法

enum Rank: Int {case Ace = 1case Two, Three, Four, Five, Six, Seven, Eight, Nine, Tencase Jack, Queen, Kingfunc simpleDescription() -> String {switch self {case .Ace:return "ace"case .Jack:return "jack"case .Queen:return "queen"case .King:return "king"default:return String(self.toRaw())}}
}
let ace = Rank.Ace
let aceRawValue = ace.toRaw()

上面的例子中,枚举中的原始值类型是int,所以你必须指定第一个原始值,余下的会按顺序指定,你也可以使用浮点数或者字符串作为枚举的原始类型 使用toRaw和fromRaw函数转换枚举值和原始值

if let convertedRank = Rank.fromRaw(3) {let threeDescription = convertedRank.simpleDescription()
}

枚举中的成员数值必须是实际的值,不能通过其他方式设置,实际上对于没有原始值的情况,你也不能为他设置一个

enum Suit {case Spades, Hearts, Diamonds, Clubsfunc 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()

注意枚举中的Hearts成员引用的两种方式:当指派给常量hearts时,使用了Suit.Hearts全名称,而在switch中,使用 了.Hearts,因为self 已经知道是suit,在知道类型时,你可以使用这种缩写 使用struct创建结构,结构支持许多类似类的功能,比如方法和构造函数,两者最大的区别是,结构是值传递,类为引用传递

struct Card {var rank: Rankvar suit: Suitfunc simpleDescription() -> String {return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"}
}
let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()

枚举成员实例可以拥有关联值,相同枚举成员可以有不同的关联值,你可以在创建实例时设置关联值,关联值与原始值不同,同一个枚举成员的所有实例有相同的原始值,但可以有不同的关联值 举个例子,考虑从服务中获取日升日落的时间,服务可以响应这些信息或者一些异常信息

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

注意从VerverResponse中获取的日升日落的具体数值可以在switch条件中获取

协议和扩展

使用protocol声明一个协议

protocol ExampleProtocol {var simpleDescription: String { get }mutating func adjust()
}

类,枚举,结构都可以使用协议

class SimpleClass: ExampleProtocol {var simpleDescription: String = "A very simple class."var anotherProperty: Int = 69105func adjust() {simpleDescription += "  Now 100% adjusted."}
}
var a = SimpleClass()
a.adjust()
let aDescription = a.simpleDescriptionstruct SimpleStructure: ExampleProtocol {var simpleDescription: String = "A simple structure"mutating func adjust() {simpleDescription += " (adjusted)"}
}
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescription

注意,在SimpleStructure声明中使用mutating关键词用于标示这个方法会修改结构,而SimpleClass中不需要设置 mutating标志,是因为类中的方法总是会修改这个类 使用extension为一个已存在的类型增加函数,比如新的方法或者计算属性,你可以使用扩展,保证任意类型具有相同的协议,不管这个类型是从框架还是 类库中来的

extension Int: ExampleProtocol {var simpleDescription: String {return "The number \(self)"}mutating func adjust() {self += 42}
}
7.simpleDescription

你可以像其他命名类型一样使用协议名称,比如,创建一个由类型不同但使用相同协议的对象组成的集合,当你使用这些类型时,可以当做一个协议类型来使用,协议以外的方法将不可用

let protocolValue: ExampleProtocol = a
protocolValue.simpleDescription
// protocolValue.anotherProperty  // Uncomment to see the error

虽然protocolValue在运行时是SimpleClass类型,但编译器会以ExampleProtocol对待,这意味你可以避免访问协议以外的方法

泛型

尖括号中的名称用于创建一个泛型的函数和类型

func repeat(item: ItemType, times: Int) -> ItemType[] {var result = ItemType[]()for i in 0..times {result += item}return result
}
repeat("knock", 4)

也可以用同样的方式在类,枚举,结构中使用泛型

// Reimplement the Swift standard library's optional type
enum OptionalValue {case Nonecase Some(T)
}
var possibleInteger: OptionalValue = .None
possibleInteger = .Some(100)

在类型名后使用where指定需求列表,比如指定类型必须实现某个协议,或者要求两种类型相同,或者要求具有某个特定的超类

func anyCommonElements <T, U where T: Sequence, U: Sequence, T.GeneratorType.Element: Equatable, T.GeneratorType.Element == U.GeneratorType.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])

一般情况下,你可以忽略where,在括号后面简单的写一个协议名或者类型,比如,<T: Equatable><T where T: Equatable>是相同的效果

参考:http://my.oschina.net/nosand/blog/272018#OSC_h3_2

转载于:https://www.cnblogs.com/langtianya/p/3766483.html

Swift翻译之-Swift语法入门 Swift语法介绍相关推荐

  1. 【Linux】shell语法入门手册 语法大全

    shell学习笔记 yxc的linux shell语法目录 概论 运行方式 直接用解释器执行 作为可执行文件运行 注释 单行注释 多行注释 变量 定义变量 引用变量 只读变量 删除变量 变量类型 字符 ...

  2. swift android界面,使用 Swift 语言编写 Android 应用入门

    原标题:使用 Swift 语言编写 Android 应用入门 Swift标准库可以编译安卓armv7的内核,这使得可以在安卓移动设备上执行Swift语句代码.本文解释了如何在你的安卓手机上运行一个简单 ...

  3. Swift基础:创建第一个Swift工程:Swift的基本语法

    苹果公司在今年的WWDC大会上,除了发布了iOS8和Max OS X 10.10之外,还发布了一个新的编程语言Swift.不得不说,Swift有较大的转变,也使编程变得更加容易了,下面介绍了Swift ...

  4. Swift Web 开发之 Vapor - 入门(一)

    简介 Vapor 是一个基于纯 Swift 构建出的 Web 开发框架,目前可以运行在 macOS 和 Ubuntu ,用于构建出漂亮易用的网站或者 API 服务. 官方称是用的最多的 Swift w ...

  5. Swift 1.1语言快速入门7.2使用无参函数

    Swift 1.1语言快速入门7.2使用无参函数 无参数函数是指没有参数列表的函数.以下对它的声明定义.调用以及最简单的函数--空函数进行详细的讲解 7.2.1  无参函数的声明定义 函数在使用之前必 ...

  6. Swift vs. Objective-C:未来看好Swift的十个理由

    是时候使用易入手又全面的 Swif 语言为 iOS 和 mac OS X 做应用开发了. 虽然编程语言不会那么容易消逝,但坚持衰落范例的开发小组正在这么做.如果你正为移动设备开发应用程序,并且你还没有 ...

  7. 【绝对干货】Swift是花拳绣腿吗?从Swift谈开发语言与程序员的职业发展

    Swift是一种新的编程语言,用于编写 iOS 和 OS X 应用.Swift 结合了 C 和 Objective-C 的优点并且不受C兼容性的限制.Swift 采用安全的编程模式并添加了很多新特性, ...

  8. swift python混合开发_引用swift项目

    iOS - OC 与 Swift 互相操作 前言 在 Swift 语言中,我们可以使用 Objective-C.C 语言编写代码,我们可以导入任意用 Objective-C 写的 Cocoa 平台框架 ...

  9. 拥抱Swift!优酷Mac迁移Swift实践

    作者丨阿里文娱高级无线开发工程师 大斗 不管从"明里"还是"暗里"来看,苹果都在大力推荐使用 Swift 这一门语言.作为苹果的"亲儿子", ...

最新文章

  1. oracle判断值是否为0的高数,SQLServer和Oracle的常用函数对比
  2. 在项目中使用Google Closure Compiler
  3. Exchange 2003允许部分用户发送邮件到部分外网服务器
  4. 机器学习笔记:牛顿方法
  5. BMP位图之8位位图(三)
  6. P1726-上白泽慧音【tarjan,图论】
  7. xtext_使用Xtext为Eclipse和IntelliJ开发DSL
  8. node实现简单的群体聊天工具
  9. hystrix基于request cache请求缓存技术优化批量数据查询接口
  10. 干货分享丨玩转物联网IoTDA服务系列五-智能家居煤气检测联动
  11. 最耗性能的SQL语句
  12. 运行文件服务器,服务器的运行目录文件
  13. Spring Roo 之 Mysql 连接
  14. 如何找出php木马,linux下查找php木马
  15. java 企业级安全_《企业级Java安全性—构建安全的J2EE应用》 尹亚 【正版电子纸书阅读_PDF下载】- 书问...
  16. 卡西欧手表城市编码,调时区用
  17. java基于springboot酒店客房预定管理系统ssm
  18. 各种Java游戏引擎简介
  19. C语言变量类型及其表示范围
  20. python查看电脑配置_怎么看电脑配置_怎么查看电脑配置好坏|信息【图文】-太平洋IT百科...

热门文章

  1. linux有关网络服务的接口,linux系统有关网络服务接口定义是哪个?
  2. java页面登陆密码_java实现页面登陆2 密码加密
  3. oracle 日志切换太频繁,关于oracle日志切换的问题
  4. linux服务器上装R语言,R语言 在linux上的安装
  5. reg类型变量综合电路_2014年PLD习题集(含参考答案)数字系统设计
  6. Java面试面向对象三大特征,Java面试经典基础问答三
  7. java简述会话对象的生命周期_简述Java Web三大作用域对象
  8. 3dvary灯光材质为什么不亮_装修小白设计家里的灯光,知道这些参数就行了!
  9. 你真的会读datasheet吗?
  10. json在android的应用,JSON解析在android应用程序