星星的孩子

摘抄一段星星的孩子的文字:

这个宇宙之中存在另一种现实,存在不同种族的人类,存在更加微妙的世界,只有足够智慧的大脑才能打开那个世界的大门。

From 第一章,阿米的对话(与作者)

作者与阿米的对话,引述出了阿米的观点,对于宇宙的认知,对于世界的理解。
给出了一个更为火爆的观点,更加微妙的世界是存在的,一个普通人是无法感受到的,感受到这个世界的前提条件:足够智慧的大脑
另一种现实也给出了读者一种可能,就是那个世界的组成形式可能不是地球的这种理解的世界。

ios3

今天计算器的小程序完成了,总结一下!

知识点:

  • storyboard使用
    • 为UILabel控件添加置顶的约束
    • 部分网格的动态展开视图
  • ViewController控制逻辑编写
    • 为了功能模块的复用->抽象为方法
    • 匿名方法使用(可以缩略写,利用了类型推断的强大语言特性)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//
// ViewController.swift
// Cracker
//
// Created by hackingangle on 16/10/2.
// Copyright © 2016年 hackingangle. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
// 定义了当前视图下的label标签的封装对象
// 可以通过在行为中调用此对象来更新对应的标签内容(label.text)
@IBOutlet weak var display: UILabel!
// var isFirstClick = true
var userIsTheMiddleOfTypingANumber = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// 接收了点击按钮发送的事件,在这里定义了事件触发时候的行为
// sender是点击按钮的封装,可以通过sender.currentTitle来获取按钮显示的内容
@IBAction func sendNum(_ sender: UIButton) {
let digit:String = sender.currentTitle!
if userIsTheMiddleOfTypingANumber {
// 更新了标签内容
display.text = display.text! + digit
} else {
// 更新标签内容
display.text = digit
userIsTheMiddleOfTypingANumber = true
}
}
@IBAction func clear() {
display.text = "0"
userIsTheMiddleOfTypingANumber = false
numStack = []
}
// v1.1新增:1>计算属性,自动格式化字符串为双精度浮点型;2>设置数据到双精度数组中
// 计算属性,格式化字符串为双精度浮点型
var displayValue:Double {
get {
let fNum:Double = NumberFormatter().number(from: display.text!)!.doubleValue
print("get called")
return fNum
}
set {
print("set called, newValue = \(newValue)")
// 更新label内容
display.text = "\(newValue)"
// 重新计数
userIsTheMiddleOfTypingANumber = false
}
}
// 初始化浮点型数组
var numStack = Array<Double>()
@IBAction func enter() {
// 存储数据到数组
numStack.append(displayValue)
// 重新计数
userIsTheMiddleOfTypingANumber = false
// 输出当前数组
print("numStack is \(numStack)")
}
// +-*/的操作符
@IBAction func operate(_ sender: UIButton) {
if userIsTheMiddleOfTypingANumber {
enter()
}
if let btnValue = sender.currentTitle {
switch btnValue {
case "+":
// performOperation(operation: inc)
// 匿名:最初
performOperation(operation: {(opt1:Double, opt2:Double) in return opt1 + opt2})
case "-":
// performOperation(operation: dec)
// 匿名:通过类型推断,预知参数类型,返回值表达式
performOperation(operation: {(opt1, opt2) in opt1 - opt2})
case "*":
// performOperation(operation: multiply)
// 匿名函数位于调用参数最后一个,可以外置
performOperation(operation: ) {$0 * $1}
case "/":
// performOperation(operation: devide)
// performOperation {$0 / $1}
// 如果参数只有一个匿名函数,则可以直接不带参数
performOperation {$0 / $1}
default:
break
}
} else {
print("click invalid button, newValue")
}
}
// 加减乘除基础方法
func multiply(opA:Double, opB:Double) -> Double {
return opA * opB
}
func devide(opA:Double, opB:Double) -> Double {
return opA / opB
}
func inc(opA:Double, opB:Double) -> Double {
return opA + opB
}
func dec(opA:Double, opB:Double) -> Double {
return opA - opB
}
// 参数声明了方法
func performOperation(operation: (Double, Double) -> Double) {
if numStack.count >= 2 {
displayValue = operation(numStack.removeLast(), numStack.removeLast())
enter()
}
}
// 参数声明了方法, swift3中貌似已经废除
// func performOperation(operation: (Double) -> Double) {
// if numStack.count >= 1 {
// displayValue = operation(numStack.removeLast())
// enter()
// }
// }
}

ios2

我们在ios1基础之上再增强我们的功能,每一次在刷新label显示的同时,完成的是一个数字的录入操作,如果保存录入的数字呢?

我们在swift当中存在各种数据类型,如:数组,字典,集合等,本次我们使用数组就可以完成数据录入后的保存工作,是不是很赞👍!

好吧,先来介绍下数组的简单使用:
声明、初始化、操作

  • 声明、初始化:
      • var arr:[String] = []
      • var arr = [String]()
      • var arr:Array<String> = []
      • var arr = Array<String>()
  • 操作
    • 新增
      • arr.append("hello")

在知道了如何使用数组来缓存数据之后,我们再来学习一个新的概念。
这个概念有点像是JAVA中的setter和getter,也类比与php中的魔术方法setter和getter。
在swift中,我们称之为:可计算属性(computed property),使用方法如下:

1
2
3
4
5
6
7
8
9
var demoValue:String {
set: {
}
get: {
return "Hello,World."
}
}

修改ViewController.swift源码,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
//
// ViewController.swift
// Cracker
//
// Created by hackingangle on 16/10/2.
// Copyright © 2016年 hackingangle. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
// 定义了当前视图下的label标签的封装对象
// 可以通过在行为中调用此对象来更新对应的标签内容(label.text)
@IBOutlet weak var display: UILabel!
var isFirstClick = true
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// 接收了点击按钮发送的事件,在这里定义了事件触发时候的行为
// sender是点击按钮的封装,可以通过sender.currentTitle来获取按钮显示的内容
@IBAction func sendNum(_ sender: UIButton) {
if isFirstClick {
// 更新标签内容
display.text = sender.currentTitle!
isFirstClick = false
} else {
// 更新了标签内容
display.text = display.text! + sender.currentTitle!
}
}
@IBAction func clear() {
display.text = "0"
isFirstClick = true
numStack = []
}
// v1.1新增:1>计算属性,自动格式化字符串为双精度浮点型;2>设置数据到双精度数组中
// 计算属性,格式化字符串为双精度浮点型
var displayValue:Double {
get {
let fNum:Double = NumberFormatter().number(from: display.text!)!.doubleValue
print("computed property get called. value is \(fNum)")
return fNum
}
set {}
}
// 初始化浮点型数组
var numStack = Array<Double>()
// 新增加入按钮,把输入的数字缓存起来
@IBAction func enter() {
// 存储数据到数组
numStack.append(displayValue)
// 重新计数
isFirstClick = true
// 输出当前数组
print("numStack is \(numStack)")
}
}

ios1

概述

ios开发除了解决语言(oc,swift)的学习之外,还要了解apple对于ios的N多封装的使用。
ios利用了MVC模型来搭建用户交互行为。
例如本讲所讲,利用storyboard来快速搭建一个UI界面;为UI界面上的按钮来添加点击事件,并且对点击事件的行为进行更新,从而控制视图的显示。
视图的定位在默认的Main.storyboard文件中,利用xcode提供的工具就可以搭建了。

点击事件行为的定义在ViewController.swift中。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//
// ViewController.swift
// Cracker
//
// Created by hackingangle on 16/10/2.
// Copyright © 2016年 hackingangle. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
// 定义了当前视图下的label标签的封装对象
// 可以通过在行为中调用此对象来更新对应的标签内容(label.text)
@IBOutlet weak var display: UILabel!
var isFirstClick = true
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// 接收了点击按钮发送的事件,在这里定义了事件触发时候的行为
// sender是点击按钮的封装,可以通过sender.currentTitle来获取按钮显示的内容
@IBAction func sendNum(_ sender: UIButton) {
if isFirstClick {
// 更新标签内容
display.text = sender.currentTitle!
isFirstClick = false
} else {
// 更新了标签内容
display.text = display.text! + sender.currentTitle!
}
}
@IBAction func clear() {
display.text = "0"
isFirstClick = true
}
}

总结

  1. 按钮上可以添加事件
    • 事件可为多个
    • 每个事件都依次会被触发
  2. Controller类的成员变量在App的整个存活周期内都会持有,不会被触发
  3. 成员变量使用,比较php而言,不用this.关键词,直接使用即可
  4. “ALT”按键配合鼠标点击,可以知道Swift类型推断的结果(在不指定类型的情况下)
  5. “CONTROL”按键配合鼠标点击,可以查看API简介
  6. UIButton
    • currentTitle(String?)
  7. UILabel
    • text(String?)
  8. Value Binding技术可以来结包Optional类型
    • demo如下:
      1
      2
      3
      4
      5
      6
      7
      var username:String?= "hackingangle"
      if let username = username
      {
      print("username = \(username)")
      } else {
      print("invalid username")
      }

swift 12

swift中的数组作为强类型,是不允许初始化的时候直接不指定类型的空数组创建的。

因为一切变量,都要求我们必须知道他们的类型,如果声明了一个没有初始化的没有指定类型的空数组,编译器也不知道应该指定什么类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// array and dictionary
var arr = ["hackingangle", "john"]
var arr2:[String] = ["a", "b"]
var arr3:Array<String> = ["c", "d", "e", "f"]
// 类型指定后不能修改,否报错:Cannot assign value of tyoe 'Int' to type 'String'
//arr[0] = 1
arr[0] = "Hello"
// 初始化
var arr4:Array<String> = []
arr4.append("a")
var arr5:[String] = []
arr5.append("b")
var arr6 = Array<String>()
arr6.append("c")
var arr7 = [String]()
arr7.append("d")
// 数组合并
let arr8 = arr4 + arr5 + arr6 + arr7

swift 11

如何去继承使用原来OC中对于字符串操作的方法?

我们只需要引入Foundation就可以了。

我们来介绍下字符串的驼峰化,大写,小写,trim,split,join这些常用的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var str = "hi, hackingangle"
// 驼峰化
str.capitalized
// 大写
str.uppercased()
str.lowercased()
// trim
var str2 = " !!!hi!! "
str2.trimmingCharacters(in: CharacterSet.whitespaces)
str2.trimmingCharacters(in: CharacterSet.init(charactersIn: " !"))
// split
var str3 = "welcome to the swift world."
str3.components(separatedBy: " ")
var str4 = "Welcome to the swift world.NOW-LET-US-START!"
str4.components(separatedBy: CharacterSet.init(charactersIn: " -"))
// join[swift3被废弃了]
var str5 = "-"

swift 10

如何更好的去操作字符串,我们在编写程序的过程中,必须要学习的内容。

字符串常见的操作有:拼接字符串,字符串比较,字符串前缀后缀匹配等

字符串比较要注意:比较的是从第一位开始的asc码表的位置,A<a,a<b,不比较长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
let msg = "Hello,"
let name = "hackingangle"
// 字符串的拼接
let welcome = msg + name
// 比较字符串大小
let str1 = "abc"
let str2 = "abc"
// true
str1 == str2
let str3 = "abd"
// true
str1 < str3
let str4 = "abcd"
// true
str3 > str4
let names = [
"hackingangle",
"john smith",
"lili smith",
"lili zhang",
]
// 直接输出字符串
for name in names {
print("\(name)")
}
// 匹配字符串前缀或者后缀
var countPrefix = 0
var countSubffix = 0
for name in names {
if name.hasPrefix("lili") {
// swift3 废弃了 count++语法
countPrefix += 1
}
if name.hasSuffix("smith") {
countSubffix += 1
}
}

swift 09

今天我们来介绍下字符串,字符串是每一个编程语言中最常用的类型,请允许我这么介绍今天的主人公-字符串!

来一起看看如何使用他吧!

字符串分为变量字符串和常量字符串,常量字符串不可以进行覆盖值操作和拼接操作。

初始化空字符串可以使用""String()

今天在使用过程中发现,swift的新老版本api差异很大,很多方法都被废弃了,如:countElements等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//: Playground - noun: a place where people can play
import UIKit
// 常量和变量区别
let str = "hello,"
// hackingangle💖
var name = "hackingangle\u{1F496}"
// 提示:Left side of mutating operator isn`t mutable: 'str' is a 'let' constant
// str += "guest"
name = str + name
// 初始化空字符串
var str2 = ""
var str3 = String()
// Init
str2 += "Init"
// false
str2.isEmpty
// true
str3.isEmpty
// 使用for...in循环字符串
// 提示:Type 'String' does not conform to protocol 'Sequence'
//for c in str2 {
// println(c)
//}
// 拼字符
var ch:Character = "!"
str2.append(ch)
str2

swift 08

swift中逻辑运算符比较简单,分为三种:&&||!

另外,要与之区分的是位运算符,分为两种:&|

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 位运算符
// 00000001
let a = 1
// 00000110
let b = 6
// 0
let c = a & b
// 7
let d = a | b
// 逻辑运算符
let bol1 = true
let bol2 = false
bol1 && bol2
bol1 || bol2
!bol1
!bol2

swift 07

今天让我们来讲讲循环for..in和区间运算符m…n。

区间运算符可以快速初始化一组变量,然后使用for…in将这些变量循环出来。

区间运算符分为两种:1…100与1..<100。第二种使用场景是从0开始的数组输出。

1
2
3
4
5
6
7
8
9
10
// 循环数组
for num in 1...100 {
print("num = \(num)")
}
// 利用半开区间来循环数组
let names = ["hackingangle", "hackingangle2", "hackingangle3"]
for i in 0..<names.count {
names[i]
}