您的位置:首页 > 移动开发 > Swift

IOS开发-Swift-基础知识学习笔记

2017-04-25 11:36 627 查看
实例代码下载:

IOS开发-Swift-基础知识学习笔记

1.定义常量变量,显示指定类型

var myVariable = 42;
let myConstant = 42;
//指定类型
var myChange: Float = 4;
myVariable = 50;
myChange = 666;
print("\(myVariable) \(myConstant) \(myChange)");


2.转换成字符串的方法

let label = "the width is ";
let width = 94;

let widthLabel = label+String(width);
print(widthLabel);

let apple = 3;
let orange = 5;
let appleSummary = "i have \(apple) apples.";
let orangeSummary = "i have \(orange+apple) pieces of fruit";

print(appleSummary);
print(orangeSummary);

let name = "zhao";
let times = 3.0;
let ask = "say \(times) times hello to \(name)";
print(ask);


3.创建数组和字典,创建空数组和空字典

var shoppingList = ["catfish","water","tulips","blue paint"];
shoppingList[1] = "bottle of water";

var occupations = ["Malcolm":"Captain","Kaylee":"Mechanic"];
occupations["Jayne"] = "Public Relations";

print(shoppingList);
print(occupations);

let emptyDictionary = Dictionary<String,Float>();
let emptyArray = [String]();
shoppingList = [];
occupations = [:];

print(shoppingList);
print(emptyDictionary);
print(emptyArray);


4.控制流 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;
}
}
print("team score : \(teamScore)");


swift的switch与很多语言不同,他是可以处理很多种类型的,比如String类型

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


比较神奇的就是,其他语言一般都要在case的末写上break,但是swift不同,运行switch中匹配到的子句之后,程序会退出switch语句,并不会继续向下运行,所以不需要在每个子句结尾写break。

let interestiongNumbers = [
"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 interestiongNumbers {
for number in numbers {
if(number > largest){
largest = number;
}
}
}
print("largest \(largest)");


在for (kind,numbers) in interestiongNumbers 这一句代码会提示一个警告:



提示可以用 “_” 代替,因为这个kind在下面的代码中是没有用到的。

这个小下划线是有很多作用的,具体作用贴个链接:

swift下划线和”#”的妙用

使用”..”和”…”,来循环遍历:

for i in 1..<10{
print(i)
// 打印结果为1-9
}
for i in 1...10{
print(i)
//打印结果为1-10
}


do-while在swift是没有的,而是使用repeat-while来代替,do是用来异常捕获等。

var n = 2;
while n<100 {
n = n*2;
}
print("while \(n)");

var m = 2;
repeat{
m = m * 2;
}while m<100
print("do \(m)");


5.可选值 一个可选的值可能是一个具体的值或者是nil,表示值缺失。在类型后面加一个问号来标记这个变量的值是可选的

var optionalString : String? = "hello";
optionalString = nil;

var optionalName : String? = "John Appleseed";

var greeting = "hello!";

if let name = optionalName{
greeting = "hello,\(name)";
}
print(optionalString);
print(optionalName);
print(greeting);


在第三句代码会有一个警告:



variable ‘optionalName’ was never mutated;consider changing to ‘let’ constant

意思是这个变量,创建后,没有再发生变化,最好用let这个关键字去修饰,Swift的编译器可以对let进行优化,从而获得更好的性能。

在下面的三个print里面,前面两个也是会出现警告的:



swift会提供三个方法,解决这个警告,分别是:

(1)提供一个默认值来,避免这个警告

print(optionalString ?? "1111");


(2)使用强制解包,避免这个警告

print(optionalName!);


(3)显示转换成Any类型,避免这个警告

print(optionalString as Any);


6.函数和闭包

使用func来声明一个函数,使用名字和参数来调用函数。使用->来指定函数返回值。

func greet(name:String,day:String) -> String {
return "hello \(name),today is \(day)";
}

print(greet(name: "bob", day: "thuesday"));


使用一个元组来返回多个值。

func getGasPrices()->(Double,Double,Double){
return (3.59,3.639,3.79);
}
print(getGasPrices());


函数的参数数量是可变的

//数组当参数1
func sumOf(numbers:[Int]) -> Int {
var sum = 0;
for number in numbers {
sum += number;
}
return sum;
}
//数组当参数2
func sumOf(numbers:Int...) -> Int {
var sum = 0;
for number in numbers {
sum += number;
}
return sum;
}
print(sumOf(numbers:[]));
print(sumOf(numbers: [42,597,12]));
print(sumOf());
print(sumOf(numbers: [42,597,12]));


函数可以嵌套。被嵌套的函数可以访问外侧函数的变量,你可以使用嵌套函数来重构一个太长或者太复杂的函数。

//函数嵌套
func returnFifteen() -> Int {
var y = 10;
func add(){
y+=5;
}
add();
return y;
}
print(returnFifteen());


函数可以作为另一个函数的返回值

//函数作为返回值
func makeIncrementer() -> ((Int)->Int) {
func addOne(number:Int)->Int{
return 1+number;
}
return addOne;
}
let increment = makeIncrementer();
print(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;
}
let numbers = [20,19,7,12];
print(hasAnyMatches(list: numbers,condition: lessThanTen));

//函数实际上是一种特殊的闭包,你可以使用{}来创建一个匿名闭包。使用in来分割参数并返回类型。
let res = numbers.map({
(number:Int) -> Int in
let result = 3*number;
return result;
})

print(res);


7.类,对象,属性

class Square: NamedShape {
var sideLength:Double;
init(sideLenght:Double,name:String) {
self.sideLength = sideLenght;
//调用父类的init方法
super.init(name: name);
numberOfSides = 4;
}

func area() -> Double {
return sideLength*sideLength;
}

//子类如果要重写父类的方法的话,需要用override标记——如果没有添加override就重写父类方法的话编译器会报错。编译器同样会检测override标记的方法是否确实在父类中
override func simpleDescription() -> String {
return "a square with sides of length \(sideLength).";
}
}

class NamedShape {
var numberOfSides:Int = 0;
var name:String;

//构造函数
//注意self被用来区别实例变量。当你创建实例的时候,像传入函数参数一样给类传入构造器的参数。每个属性都需要赋值——无论是通过声明(就像numberOfSides)还是通过构造器(就像name)。
init(name:String) {
self.name = name;
}
func simpleDescription() -> String {
return "a shape with \(numberOfSides) sides.";
}

//析构函数
//如果你需要在删除对象之前进行一些清理工作,使用deinit创建一个析构函数。
deinit {

}
}

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

let shape = Shape();
shape.numberOfSides = 7;
let shapeDescription = shape.simpleDescription();
print(shapeDescription);

let square = Square(sideLenght: 5.2, name: "my test square");
print(square.area());
print(square.simpleDescription());


class EquilateralTriangle: NamedShape {
var sideLength:Double = 0.0;
init(sideLength:Double,name:String) {
//设置子类声明的属性值
self.sideLength = sideLength;
//调用父类的构造器
super.init(name: name);
//改变父类定义的属性值。其他的工作比如调用方法、getters和setters也可以在这个阶段完成。
如果你不需要计算属性但是需要在设置一个新值之前运行一些代码,使用willSet和didSet。
numberOfSides = 3;
}
//重写属性的get set 方法
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)";
}
}
let triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle");
print(triangle.perimeter);
triangle.perimeter = 9.9;
print(triangle.perimeter)
print(triangle.sideLength);
print(triangle.simpleDescription());


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(sideLenght: size, name: name);
triangle = EquilateralTriangle(sideLength: size, name: name);
}
print("-------------------");
let triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape");
print(triangleAndSquare.square.sideLength);
print(triangleAndSquare.triangle.sideLength);
triangleAndSquare.square = Square(sideLenght: 50, name: "larger square");
print(triangleAndSquare.triangle.sideLength);
}


class Counter {
var count:Int = 0;
func incrementBy(amount:Int,numberOfTimes times:Int) {
//类中的方法和一般的函数有一个重要的区别,函数的参数名只在函数内部使用,但是方法的参数名需要在调用的时候显式说明(除了第一个参数)。默认情况下,方法的参数名和它在方法内部的名字一样,不过你也可以定义第二个名字,这个名字被用在方法内部。
count += amount*times;
}
}

let counter = Counter();
counter.incrementBy(amount: 2, numberOfTimes: 7)
print(counter.count);


8.枚举和结构体

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

print("-------------------");
let ace = Rank.Ace;
let aceRawValue = ace.simpleDesciption();
print(aceRawValue);
print(ace.rawValue);

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 failure {
case let .Result(sunrise,sunset):
let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)"
print(serverResponse);
case let .Error(error):
let serverResponse = "Failure.. \(error)"
print(serverResponse);
}


//使用struct来创建一个结构体。结构体和类有很多相同的地方,比如方法和构造器。它们结构体之间最大的一个区别就是 结构体是传值,类是传引用。
struct Card {
var rank:Rank;
func simpleDescription() -> String {
return "the \(rank.simpleDesciption())";
}
}
print("-------------------");
let card = Card(rank: .Ace);
let cardDesc = card.simpleDescription();
print(cardDesc);


9.接口与扩展

///声明一个接口
protocol ExampleProtocol {
var simpleDescription:String {get}
mutating func adjust()
}

///类,枚举,结构体可以实现接口
class SimpleClass:ExampleProtocol{
var simpleDescription: String = "a very simple class";
var anotherProperty:Int = 69105
func adjust() {
simpleDescription += " now 100% adjusted"
}
}

//mutating关键字用来标记一个会修改结构体的方法,SimpleClass的声明不需要标记任何方法因为类中的方法经常会修改类
struct SimpleStructure:ExampleProtocol {
var simpleDescription: String = "A simple structure"
mutating func adjust() {
simpleDescription += "(adjusted)"
}
}

print("-------------------");
let a = SimpleClass();
a.adjust();
let aDesc = a.simpleDescription;
print(aDesc)

print("-------------------");
var b = SimpleStructure();
b.adjust();
print(b.simpleDescription);


扩展的写法,一个Int的extension:

//使用extension来为现有的类型添加功能,比如添加一个计算属性的方法。你可以使用扩展来给任意类型添加协议,甚至是你从外部库或者框架中导入的类型。
extension Int:ExampleProtocol{
var simpleDescription:String {
return "the number \(self)"
}
mutating func adjust() {
self += 42
}
}
print("-------------------");
print(3.simpleDescription);

//protocolValue变量运行时的类型是simpleClass,编译器会把它的类型当做ExampleProtocol。这表示你不能调用类在它实现的接口之外实现的方法或者属性。
print("-------------------");
let protocolVaule:ExampleProtocol = a;
print(protocolVaule.simpleDescription);


10.泛型

//在尖括号里写一个名字来创建一个泛型函数或者类型。
func repeatFunc<ItemType>(item:ItemType,times:Int) -> [ItemType] {
var result = [ItemType]();
for _ in 0...times {
result += [item];
}
return result;
}

print("-------------------");
print(repeatFunc(item: "knock", times: 4));


//创建泛型类、枚举和结构体。
enum OptionalValue<T> {
case None
case Some(T)
}

print("-------------------");
var possibleInteger:OptionalValue<Int> = OptionalValue.None;
print(possibleInteger);
possibleInteger = OptionalValue.Some(100);
print(possibleInteger);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息