swift2.docx
- 文档编号:27665815
- 上传时间:2023-07-03
- 格式:DOCX
- 页数:22
- 大小:24.04KB
swift2.docx
《swift2.docx》由会员分享,可在线阅读,更多相关《swift2.docx(22页珍藏版)》请在冰豆网上搜索。
swift2
在if语句中,条件必须是一个布尔表达式——这意味着像ifscore{...}这样的代码将报错,而不会隐形地与0做对比。
你可以一起使用if和let来处理值缺失的情况。
这些值可由可选值来代表。
一个可选的值是一个具体的值或者是nil以表示值缺失。
在类型后面加一个问号来标记这个变量的值是可选的。
varoptionalString:
String?
="Hello"
print(optionalString==nil)
varoptionalName:
String?
="JohnAppleseed"
vargreeting="Hello!
"
ifletname=optionalName{
greeting="Hello,\(name)"
}
如果变量的可选值是nil,条件会判断为false,大括号中的代码会被跳过。
如果不是nil,会将值赋给let后面的常量,这样代码块中就可以使用这个值了。
另一种处理可选值的方法是通过使用?
?
操作符来提供一个默认值。
如果可选值缺失的话,可以使用默认值来代替。
letnickName:
String?
=nil
letfullName:
String="JohnAppleseed"
letinformalGreeting="Hi\(nickName?
?
fullName)"
TheSwiftProgrammingLanguage中文版
时间简史
本页内容包括:
简单值(SimpleValues)
控制流(ControlFlow)
函数和闭包(FunctionsandClosures)
对象和类(ObjectsandClasses)
枚举和结构体(EnumerationsandStructures)
协议和扩展(ProtocolsandExtensions)
泛型(Generics)
通常来说,编程语言教程中的第一个程序应该在屏幕上打印“Hello,world”。
在Swift中,可以用一行代码实现:
print("Hello,world!
")
如果你写过C或者Objective-C代码,那你应该很熟悉这种形式——在Swift中,这行代码就是一个完整的程序。
你不需要为了输入输出或者字符串处理导入一个单独的库。
全局作用域中的代码会被自动当做程序的入口点,所以你也不需要main()函数。
你同样不需要在每个语句结尾写上分号。
这个教程会通过一系列编程例子来让你对Swift有初步了解,如果你有什么不理解的地方也不用担心——任何本章介绍的内容都会在后面的章节中详细讲解。
注意:
为了获得最好的体验,在Xcode当中使用代码预览功能。
代码预览功能可以让你编辑代码并实时看到运行结果。
下载Playground
简单值
使用let来声明常量,使用var来声明变量。
一个常量的值,在编译的时候,并不需要有明确的值,但是你只能为它赋值一次。
也就是说你可以用常量来表示这样一个值:
你只需要决定一次,但是需要使用很多次。
varmyVariable=42
myVariable=50
letmyConstant=42
常量或者变量的类型必须和你赋给它们的值一样。
然而,你不用明确地声明类型,声明的同时赋值的话,编译器会自动推断类型。
在上面的例子中,编译器推断出myVariable是一个整数(integer)因为它的初始值是整数。
如果初始值没有提供足够的信息(或者没有初始值),那你需要在变量后面声明类型,用冒号分割。
letimplicitInteger=70
letimplicitDouble=70.0
letexplicitDouble:
Double=70
练习:
创建一个常量,显式指定类型为Float并指定初始值为4。
值永远不会被隐式转换为其他类型。
如果你需要把一个值转换成其他类型,请显式转换。
letlabel="Thewidthis"
letwidth=94
letwidthLabel=label+String(width)
练习:
删除最后一行中的String,错误提示是什么?
有一种更简单的把值转换成字符串的方法:
把值写到括号中,并且在括号之前写一个反斜杠。
例如:
letapples=3
letoranges=5
letappleSummary="Ihave\(apples)apples."
letfruitSummary="Ihave\(apples+oranges)piecesoffruit."
练习:
使用\()来把一个浮点计算转换成字符串,并加上某人的名字,和他打个招呼。
使用方括号[]来创建数组和字典,并使用下标或者键(key)来访问元素。
最后一个元素后面允许有个逗号。
varshoppingList=["catfish","water","tulips","bluepaint"]
shoppingList[1]="bottleofwater"
varoccupations=[
"Malcolm":
"Captain",
"Kaylee":
"Mechanic",
]
occupations["Jayne"]="PublicRelations"
要创建一个空数组或者字典,使用初始化语法。
letemptyArray=[String]()
letemptyDictionary=[String:
Float]()
如果类型信息可以被推断出来,你可以用[]和[:
]来创建空数组和空字典——就像你声明变量或者给函数传参数的时候一样。
shoppingList=[]
occupations=[:
]
控制流
使用if和switch来进行条件操作,使用for-in、for、while和repeat-while来进行循环。
包裹条件和循环变量括号可以省略,但是语句体的大括号是必须的。
letindividualScores=[75,43,103,87,12]
varteamScore=0
forscoreinindividualScores{
ifscore>50{
teamScore+=3
}else{
teamScore+=1
}
}
print(teamScore)
在if语句中,条件必须是一个布尔表达式——这意味着像ifscore{...}这样的代码将报错,而不会隐形地与0做对比。
你可以一起使用if和let来处理值缺失的情况。
这些值可由可选值来代表。
一个可选的值是一个具体的值或者是nil以表示值缺失。
在类型后面加一个问号来标记这个变量的值是可选的。
varoptionalString:
String?
="Hello"
print(optionalString==nil)
varoptionalName:
String?
="JohnAppleseed"
vargreeting="Hello!
"
ifletname=optionalName{
greeting="Hello,\(name)"
}
练习:
把optionalName改成nil,greeting会是什么?
添加一个else语句,当optionalName是nil时给greeting赋一个不同的值。
如果变量的可选值是nil,条件会判断为false,大括号中的代码会被跳过。
如果不是nil,会将值赋给let后面的常量,这样代码块中就可以使用这个值了。
另一种处理可选值的方法是通过使用?
?
操作符来提供一个默认值。
如果可选值缺失的话,可以使用默认值来代替。
letnickName:
String?
=nil
letfullName:
String="JohnAppleseed"
letinformalGreeting="Hi\(nickName?
?
fullName)"
switch支持任意类型的数据以及各种比较操作——不仅仅是整数以及测试相等。
letvegetable="redpepper"
switchvegetable{
case"celery":
print("Addsomeraisinsandmakeantsonalog.")
case"cucumber","watercress":
print("Thatwouldmakeagoodteasandwich.")
caseletxwherex.hasSuffix("pepper"):
print("Isitaspicy\(x)?
")
default:
print("Everythingtastesgoodinsoup.")
}
练习:
删除default语句,看看会有什么错误?
注意let在上述例子的等式中是如何使用的,它将匹配等式的值赋给常量x。
运行switch中匹配到的子句之后,程序会退出switch语句,并不会继续向下运行,所以不需要在每个子句结尾写break。
你可以使用for-in来遍历字典,需要两个变量来表示每个键值对。
字典是一个无序的集合,所以他们的键和值以任意顺序迭代结束。
letinterestingNumbers=[
"Prime":
[2,3,5,7,11,13],
"Fibonacci":
[1,1,2,3,5,8],
"Square":
[1,4,9,16,25],
]
varlargest=0
for(kind,numbers)ininterestingNumbers{
fornumberinnumbers{
ifnumber>largest{
largest=number
}
}
}
print(largest)
练习:
添加另一个变量来记录现在和之前最大数字的类型。
使用while来重复运行一段代码直到不满足条件。
循环条件也可以在结尾,保证能至少循环一次。
varn=2
whilen<100{
n=n*2
}
print(n)
varm=2
repeat{
m=m*2
}whilem<100
print(m)
你可以在循环中使用..<来表示范围,也可以使用传统的写法,两者是等价的:
varfirstForLoop=0
foriin0..<4{
firstForLoop+=i
}
print(firstForLoop)
varsecondForLoop=0
forvari=0;i<4;++i{
secondForLoop+=i
}
print(secondForLoop)
使用..<创建的范围不包含上界,如果想包含的话需要使用...。
函数和闭包
使用func来声明一个函数,使用名字和参数来调用函数。
使用->来指定函数返回值的类型。
funcgreet(name:
String,day:
String)->String{
return"Hello\(name),todayis\(day)."
}
greet("Bob",day:
"Tuesday")
练习:
删除day参数,添加一个参数来表示今天吃了什么午饭。
使用元组来让一个函数返回多个值。
该元组的元素可以用名称或数字来表示。
funccalculateStatistics(scores:
[Int])->(min:
Int,max:
Int,sum:
Int){
varmin=scores[0]
varmax=scores[0]
varsum=0
forscoreinscores{
ifscore>max{
max=score
}elseifscore min=score } sum+=score } return(min,max,sum) } letstatistics=calculateStatistics([5,3,100,3,9]) print(statistics.sum) print(statistics.2) 函数可以带有可变个数的参数,这些参数在函数内表现为数组的形式: funcsumOf(numbers: Int...)->Int{ varsum=0 fornumberinnumbers{ sum+=number } returnsum } sumOf() sumOf(42,597,12) 练习: 写一个计算参数平均值的函数。 函数可以嵌套。 被嵌套的函数可以访问外侧函数的变量,你可以使用嵌套函数来重构一个太长或者太复杂的函数。 funcreturnFifteen()->Int{ vary=10 funcadd(){ y+=5 } add() returny } returnFifteen() 函数是第一等类型,这意味着函数可以作为另一个函数的返回值。 funcmakeIncrementer()->(Int->Int){ funcaddOne(number: Int)->Int{ return1+number } returnaddOne } varincrement=makeIncrementer() increment(7) 函数也可以当做参数传入另一个函数。 funchasAnyMatches(list: [Int],condition: Int->Bool)->Bool{ foriteminlist{ ifcondition(item){ returntrue } } returnfalse } funclessThanTen(number: Int)->Bool{ returnnumber<10 } varnumbers=[20,19,7,12] hasAnyMatches(numbers,condition: lessThanTen) 函数实际上是一种特殊的闭包: 它是一段能之后被调取的代码。 闭包中的代码能访问闭包所建作用域中能得到的变量和函数,即使闭包是在一个不同的作用域被执行的-你已经在嵌套函数例子中所看到。 你可以使用{}来创建一个匿名闭包。 使用in将参数和返回值类型声明与闭包函数体进行分离。 numbers.map({ (number: Int)->Intin letresult=3*number returnresult }) 练习: 重写闭包,对所有奇数返回0。 有很多种创建更简洁的闭包的方法。 如果一个闭包的类型已知,比如作为一个回调函数,你可以忽略参数的类型和返回值。 单个语句闭包会把它语句的值当做结果返回。 letmappedNumbers=numbers.map({numberin3*number}) print(mappedNumbers) 你可以通过参数位置而不是参数名字来引用参数——这个方法在非常短的闭包中非常有用。 当一个闭包作为最后一个参数传给一个函数的时候,它可以直接跟在括号后面。 当一个闭包是传给函数的唯一参数,你可以完全忽略括号。 letsortedNumbers=numbers.sort{$0>$1} print(sortedNumbers) 对象和类 使用class和类名来创建一个类。 类中属性的声明和常量、变量声明一样,唯一的区别就是它们的上下文是类。 同样,方法和函数声明也一样。 classShape{ varnumberOfSides=0 funcsimpleDescription()->String{ return"Ashapewith\(numberOfSides)sides." } } 练习: 使用let添加一个常量属性,再添加一个接收一个参数的方法。 要创建一个类的实例,在类名后面加上括号。 使用点语法来访问实例的属性和方法。 varshape=Shape() shape.numberOfSides=7 varshapeDescription=shape.simpleDescription() 这个版本的Shape类缺少了一些重要的东西: 一个构造函数来初始化类实例。 使用init来创建一个构造器。 classNamedShape{ varnumberOfSides: Int=0 varname: String init(name: String){ self.name=name } funcsimpleDescription()->String{ return"Ashapewith\(numberOfSides)sides." } } 注意self被用来区别实例变量。 当你创建实例的时候,像传入函数参数一样给类传入构造器的参数。 每个属性都需要赋值——无论是通过声明(就像numberOfSides)还是通过构造器(就像name)。 如果你需要在删除对象之前进行一些清理工作,使用deinit创建一个析构函数。 子类的定义方法是在它们的类名后面加上父类的名字,用冒号分割。 创建类的时候并不需要一个标准的根类,所以你可以忽略父类。 子类如果要重写父类的方法的话,需要用override标记——如果没有添加override就重写父类方法的话编译器会报错。 编译器同样会检测override标记的方法是否确实在父类中。 classSquare: NamedShape{ varsideLength: Double init(sideLength: Double,name: String){ self.sideLength=sideLength super.init(name: name) numberOfSides=4 } funcarea()->Double{ returnsideLength*sideLength } overridefuncsimpleDescription()->String{ return"Asquarewithsidesoflength\(sideLength)." } } lettest=Square(sideLength: 5.2,name: "mytestsquare") test.area() test.simpleDescription() 练习: 创建NamedShape的另一个子类Circle,构造器接收两个参数,一个是半径一个是名称,在子类Circle中实现area()和simpleDescription()方法。 除了储存简单的属性之外,属性可以有getter和setter。 classEquilateralTriangle: NamedShape{ varsideLength: Double=0.0 init(sideLength: Double,name: String){ self.sideLength=sideLength super.init(name: name) numberOfSides=3 } varperimeter: Double{ get{ return3.0*sideLength } set{ sideLength=newValue/3.0 } } overridefuncsimpleDescription()->String{ return"Anequilateraltriaglewithsidesoflength\(sideLength)." } } vartriangle=EquilateralTriangle(sideLength: 3.1,name: "atriangle") print(triangle.perimeter) triangle.perimeter=9.9 print(triangle.sideLength) 在perimeter的setter中,新值的名字是newValue。 你可以在set之后显式的设置一个名字。 注意EquilateralTriangle类的构造器执行了三步: 设置子类声明的属性值 调用父类的构造器 改变父类定义的属性值。 其他的工作比如调用方法、getters和setters也可以在这个阶段完成。 如果你不需要计算属性,但是仍然需要在设置一个新值之前或者之后运行代码,使用willSet和didSet。 比如,下面的类确保三角形的边长总是和正方形的边长相同。 classTriangleAndSquare{ vartriangle: EquilateralTriangle{ willSet{ square.sideLength=newValue.sideLength } } varsquare: Square{ willSet{ triangle.sideLength=newValue.sideLength } } init(size: Double,name: String){ square=Square(sideLength: size,name: name) triangle=EquilateralTriangle(sideLength: size,name: name) } } vartriangleAndSquare=TriangleAndSquare(size: 10,name: "anothertestshape") print(triangleAndSquare.square.sideLength) print(triangleAndSquare.triangle.sideLength) triangleAndSquare.square=Square(sideLength: 50,name: "largersquare") print(triangleAndSquare.triangle.sideLength) 处理变量的可选值时,你可以在操作(比如方法、属性和子脚本)之前加? 。 如果? 之前的值是nil,? 后面的东西都会被忽略,并且整个表达式返回nil。 否则,? 之后的东西都会被运行。 在这两种情况下,整个表达式的值也是一个可选值。 letoptionalSquare: Square? =Squar
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- swift2