网站打开很慢,微商怎样让客源主动加你,站长之家psd,网页设计论文前言本文是个比较简单的学习笔记#xff0c;更详细的内容见 Swift官方文档
1、相等性比较
Swift标准库用 和 运算符定义了 、、#xff0c;所以实现 Comparable 的 运算符就会自动得到这些运算符的实现#xff0c;实际上 Comparable 继承自 Equatable更详细的内容见 Swift官方文档
1、相等性比较
Swift标准库用 和 运算符定义了 、、所以实现 Comparable 的 运算符就会自动得到这些运算符的实现实际上 Comparable 继承自 Equatable所以 运算也是必须实现的以下是示例代码
struct Point: Comparable, CustomStringConvertible {let x: Intlet y: Intvar description: String {return Point(\(x), \(y))}static func (lhs: Point, rhs: Point) - Bool {return lhs.x rhs.x lhs.y rhs.y}static func (lhs: Point, rhs: Point) - Bool {return lhs.x rhs.x lhs.y rhs.y}static func (left: Point, right: Point) - Point {return Point(x: left.x right.x, y: left.y right.y)}
}let a Point(x: 3, y: 4)
let b Point(x: 3, y: 4)
let abEqual (a b)
a ! blet c Point(x: 2, y: 6)
let d Point(x: 3, y: 7)
c d
c d
c d
c d
c dc dclass Person: Equatable {let name: Stringlet age: Intweak var brother: Person?init(name: String, age: Int) {self.name nameself.age age}static func (lhs: Person, rhs: Person) - Bool {return lhs.name rhs.name}
}let p1 Person(name: JJF, age: 33)
let p2 Person(name: JZF, age: 36)
var people [p1, p2]
if let p1Index people.firstIndex(where: { $0 p2 }) {print(p1Index)
}//自定义运算符
infix operator func (lhs: Person, rhs: Person) {lhs.brother rhsrhs.brother lhs
}
p1 p2
p1.brother?.name
p2.brother?.name
2、日期和时间
import Foundationlet date Date.nowlet dateFormatter DateFormatter()
//dateFormatter.locale Locale(identifier: zh_CN)
dateFormatter.dateFormat yyyy-MM-dd HH:mm:ss.SSS// typealias TimeInterval Double
// A number of seconds.
// TimeInterval 是 Double 类型单位是秒可精确到微秒
//时间戳1970到现在的毫秒数
let timestamp Int(date.timeIntervalSince1970 * 1000)
print(timestamp \(timestamp))//取当前时间的年/月/日/时/分/秒/毫秒
var calendar Calendar.current
let year calendar.component(.year, from: date)
let month calendar.component(.month, from: date)
let day calendar.component(.day, from: date)
let hour calendar.component(.hour, from: date)
let minute calendar.component(.minute, from: date)
let second calendar.component(.second, from: date)
let milliSecond calendar.component(.nanosecond, from: date) / 1000_000
print(\(year)-\(String(format: %02D, month))-\(String(format: %02D, day)) \(String(format: %02D, hour)):\(String(format: %02D, minute)):\(String(format: %02D, second)).\(String(format: %03D, milliSecond)))//使用 DateFormatter 格式化时间
print(\(dateFormatter.string(from: date)))let str Hello World!
let start str.index(str.startIndex, offsetBy: 6)
let end str.index(str.startIndex, offsetBy: 11)
let substr String(str[start..end])
print(substr)3、处理异常
enum Token {case number(Int)case plus
}class Lexer {enum Error: Swift.Error {case invalidCharacter(Character)}let input: Stringvar position: String.Indexinit(input: String) {self.input inputself.position self.input.startIndex}func peek() - Character? {guard position input.endIndex else {return nil}return input[position]}func advance() {//断言只在调试模式下生效发布模式下可使用 precondition(_:_:) 替代assert(position input.endIndex, Cannot advance past endIndex!)position input.index(after: position)}func lex() throws - [Token] {var tokens [Token]()while let nextCharacter peek() {switch nextCharacter {case 0...9:tokens.append(.number(getNumber()))case :tokens.append(.plus)advance()case :advance()default:throw Lexer.Error.invalidCharacter(nextCharacter)}}return tokens}func getNumber() - Int {var value 0while let nextCharacter peek() {switch nextCharacter {case 0...9:let digitValue Int(String(nextCharacter))!value 10 * value digitValueadvance()default:return value}}return value}
}class Parser {enum Error: Swift.Error {case unexpectedEndOfInputcase invalidToken(Token)}let tokens: [Token]var position 0init(tokens: [Token]) {self.tokens tokens}func nextToken() - Token? {guard position tokens.count else {return nil}let token tokens[position]position 1return token}func getNumber() throws - Int {guard let token nextToken() else {throw Parser.Error.unexpectedEndOfInput}switch token {case .number(let value):return valuecase .plus:throw Parser.Error.invalidToken(token)}}func parse() throws - Int {var value try getNumber()while let token nextToken() {switch token {case .plus:let nextNumber try getNumber()value nextNumbercase .number:throw Parser.Error.invalidToken(token)}}return value}
}func evaluate(_ input: String) {print(Evaluating: \(input))let lexer Lexer(input: input)
// let tokens try! lexer.lex()//强制执行可能抛出错误的方法发生错误时触发陷阱
// guard let tokens try? lexer.lex() else {
// print(Lexing failed, but I dont know why)
// return
// }do {let tokens try lexer.lex()print(Lexer ouput: \(tokens))let parser Parser(tokens: tokens)let value try parser.parse()print(value)} catch Lexer.Error.invalidCharacter(let character) {print(Input contained an invalid character: \(character))} catch Parser.Error.unexpectedEndOfInput {print(Unexpected end of input during parsing)} catch Parser.Error.invalidToken(let token) {print(Invalid token during parsing: \(token))} catch {print(An error occurred: \(error))}
}
evaluate(10 3 5 )4、扩展
1扩展类/结构体
typealias Velocity Doubleextension Velocity {var kph: Velocity { return self * 1.60934 }var mph: Velocity { return self }
}protocol Vehicle {var topSpeed: Velocity { get }var numberOfDoors: Int { get }var hasFlatbed: Bool { get }
}struct Car {let make: Stringlet model: Stringlet year: Intlet color: Stringlet nickname: Stringvar gasLevel: Double {willSet {precondition(newValue 1.0 newValue 0.0, New value must between 0 and 1.)}}
}//利用拓展使 Car 实现协议
extension Car: Vehicle {var topSpeed: Velocity { return 180 }var numberOfDoors: Int { return 4 }var hasFlatbed: Bool { return false }
}//利用拓展给 Car 增加初始化方法这样会保留默认的成员初始化方法
extension Car {init(make: String, model: String, year: Int) {self.init(make: make, model: model, year: year, color: Black, nickname: N/A, gasLevel: 1.0)}
}var c Car(make: Ford, model: Fusion, year: 2013)extension Car {enum Kind {case coupe, sedan}var kind: Kind {if numberOfDoors 2 {return .coupe} else {return .sedan}}
}
c.kindextension Car {mutating func emptyGas(by amount: Double) {precondition(amount 1 amount 0, Amount to remove must be between 0 and 1.)gasLevel - amount}mutating func fillGas() {gasLevel 1.0}
}
c.emptyGas(by: 0.3)
c.gasLevel
c.fillGas()
c.gasLevel2扩展协议
protocol Exercise: CustomStringConvertible {var name: String { get }var caloriesBurned: Double { get } //消耗的卡路里var minutes: Double { get }//锻炼的时长
}extension Exercise {var description: String {return Exercise(\(name), burned \(caloriesBurned) calories in \(minutes) minutes)}
}extension Exercise {var title: String {return \(name) - \(minutes) minutes}
}struct EllipticalWorkout: Exercise {let name: String Elliptical Workoutlet title: String Workout using the Go Fast Elliptical Trainer 3000let caloriesBurned: Doublelet minutes: Double
}struct TreadmillWorkout: Exercise {let name: String Treadmill Workoutlet caloriesBurned: Doublelet minutes: Doublelet laps: Double //跑步的圈数
}
extension TreadmillWorkout {var description: String {return TreadmillWorkout(\(caloriesBurned) calories and \(laps) laps in \(minutes) minutes)}
}let ellipticalWorkout EllipticalWorkout(caloriesBurned: 335, minutes: 30)
let runningWorkout TreadmillWorkout(caloriesBurned: 350, minutes: 25, laps: 10.5)
//使用范型定义函数计算每分钟消耗的卡路里
func caloriesBurnedPerMinuteE: Exercise(for exercise: E) - Double {return exercise.caloriesBurned / exercise.minutes
}
print(caloriesBurnedPerMinute(for: ellipticalWorkout))
print(caloriesBurnedPerMinute(for: runningWorkout))//拓展协议
extension Exercise {//所有实现该协议的类型都可以使用通过拓展为该协议添加的属性和方法var caloriesBurnedPerMinute: Double {return caloriesBurned / minutes}
}print(ellipticalWorkout.caloriesBurnedPerMinute)
print(runningWorkout.caloriesBurnedPerMinute)
print(ellipticalWorkout)
print(runningWorkout)//带 where 子句的协议拓展
extension Sequence where Iterator.Element Exercise {func totalCaloriesBurned() - Double {var total: Double 0for exercise in self {total exercise.caloriesBurned}return total}
}let mondayWorkout: [Exercise] [ellipticalWorkout, runningWorkout]
print(mondayWorkout.totalCaloriesBurned())for exercise in mondayWorkout {print(exercise.title)
}
print(ellipticalWorkout.title)5、范型
struct StackIteratorT: IteratorProtocol {
// typealias Element Tvar stack: StackTmutating func next() - T? {return stack.pop()}
}// Sequence 是实现 for-in 循环在内部使用的协议
struct StackE: Sequence {var items [E]()// 使用 where 子句约束 Sequence 的元素类型mutating func pushAllS: Sequence(_ sequence: S) where S.Iterator.Element E {for item in sequence {self.push(item)}}mutating func push(_ newItem: E) {items.append(newItem)}mutating func pop() - E? {guard !items.isEmpty else {return nil}return items.removeLast()}func mapU(_ f: (E) - U) - StackU {var mappedItems [U]()for item in items {mappedItems.append(f(item))}return StackU(items: mappedItems)}func makeIterator() - StackIteratorE {return StackIterator(stack: self)}
}var intStack StackInt()
intStack.push(1)
intStack.push(2)
var doubledStack intStack.map { 2 * $0 }print(intStack.pop())
print(intStack.pop())
print(intStack.pop())
print(doubledStack.pop())
print(doubledStack.pop())func myMapT, U(_ items: [T], _ f: (T) - U) - [U] {var result [U]()for item in items {result.append(f(item))}return result
}
let strings [one, two, three]
//let stringLengths myMap(strings, {(str: String) - Int in
// return str.count
//})
let stringLengths myMap(strings) { $0.count }
print(stringLengths)//类型约束
func checkIfEqualT: Equatable(_ first: T, _ second: T) - Bool {return first second
}
print(checkIfEqual(1, 1))
print(checkIfEqual(a string, a string))
print(checkIfEqual(a string, a different string))//每个占位类型都可以有一个类型约束
func checkIfDescriptionsMatchT: CustomStringConvertible, U: CustomStringConvertible(_ first: T, _ second: U) - Bool {return first.description second.description
}print(checkIfDescriptionsMatch(Int(1), UInt(1)))
print(checkIfDescriptionsMatch(1, 1.0))
print(checkIfDescriptionsMatch(Float(1.0), Double(1.0)))var myStack StackInt()
myStack.push(10)
myStack.push(20)
myStack.push(30)
var myStackIterator StackIterator(stack: myStack)
while let value myStackIterator.next() {print(got \(value))
}for value in myStack {print(for-in loop: got \(value))
}
myStack.pushAll([1, 2, 3])
for value in myStack {print(after pushing: got \(value))
}
var myOtherStack StackInt()
myOtherStack.pushAll([1, 2, 3])
myStack.pushAll(myOtherStack)
for value in myStack {print(after pushing item onto stack, got \(value))
}6、协议
protocol TabularDataSource {var numberOfRows: Int { get }var numberOfColumns: Int { get }func label(forColumn column: Int) - Stringfunc itemFor(row: Int, column: Int) - String
}protocol PrintableTabularDataSource: TabularDataSource, CustomStringConvertible {//
}//组合协议让 printTable 的参数符合 CustomStringConvertible 协议
func printTable(_ dataSource: TabularDataSource CustomStringConvertible) {print(dataSource)var firstRow |var columnWidths [Int]()for i in 0..dataSource.numberOfColumns {let columnLabel dataSource.label(forColumn: i)let columnHeader \(columnLabel) |firstRow columnHeadercolumnWidths.append(columnLabel.count)}print(firstRow)for i in 0..dataSource.numberOfRows {var out |for j in 0..dataSource.numberOfColumns {let item dataSource.itemFor(row: i, column: j)let paddingNeeded columnWidths[j] - item.countlet padding repeatElement( , count: paddingNeeded).joined(separator: )out \(padding)\(item) |}print(out)}
}struct Person {let name: Stringlet age: Intlet yearsOfExperience: Int
}struct Department: TabularDataSource, CustomStringConvertible {let name: Stringvar people [Person]()var description: String {return Department (\(name))}init(name: String) {self.name name}mutating func add(_ person: Person) {people.append(person)}var numberOfRows: Int {return people.count}var numberOfColumns: Int {return 3}func label(forColumn column: Int) - String {switch column {case 0: return Employee Namecase 1: return Agecase 2: return Years of Experiencedefault: fatalError(Invalid column!)}}func itemFor(row: Int, column: Int) - String {let person people[row]switch column {case 0: return person.namecase 1: return String(person.age)case 2: return String(person.yearsOfExperience)default: fatalError(Invalid column!)}}
}var department Department(name: Engineering)
department.add(Person(name: Joe, age: 30, yearsOfExperience: 6))
department.add(Person(name: Karen, age: 40, yearsOfExperience: 18))
department.add(Person(name: Fred, age: 50, yearsOfExperience: 20))printTable(department)7、字符串
import Cocoaextension String {/// 截取字符串/// - Parameter start: 起始索引包含/// - Parameter end: 结束索引不包含func substring(start: Int, end: Int) - String {let firstIndex index(startIndex, offsetBy: start)let lastIndex index(startIndex, offsetBy: end)return String(self[firstIndex..lastIndex])}/// 16进制字符串可以有空格转换成二进制数据func toData() - Data {let hex self.replacingOccurrences(of: , with: )var arr ArrayUInt8()for i in 0..hex.count where i % 2 0 {let byteStr hex.substring(start: i, end: i 2)// print(byteStr \(byteStr))arr.append(UInt8(byteStr, radix: 16) ?? 0)}return Data(arr)}
}extension Data {/// 按照 ASCII 转换成字符串func toAscii() - String {return subdata2ascii(start: 0, end: self.count)}/// 转换成16进制字符串/// - Parameter withSpace: 可选参数默认true输出的字符串是否每两个字节之间放一个空格func toHex(withSpace: Bool true) - String {return subdata2hex(start: 0, end: self.count, withSpace: withSpace)}/// 将指定范围的数据转换成ASCII字符串/// - Parameter start: 起始索引包含/// - Parameter end: 结束索引不包含func subdata2ascii(start: Int, end: Int) - String {if let str String(data: self[start..end], encoding: .ascii) {return str}return }/// 将指定范围的数据转换成16进制字符串/// - Parameter start: 起始索引包含/// - Parameter end: 结束索引不包含/// - Parameter withSpace: 可选参数默认true输出的字符串是否每两个字节之间放一个空格func subdata2hex(start: Int, end: Int, withSpace: Bool true) - String {let arr ArrayUInt8(self[start..end])let hex arr.map({ byte - String inreturn String(format: %02X, byte)}).joined(separator: withSpace ? : )return hex}
}func test() {let hexString 5A 58 48 0C 83 0E 47 07 22 2B 42 41 30 34 56 30 35let data hexString.toData()print(head \(data.subdata2ascii(start: 0, end: 3)))print(mac \(data.subdata2hex(start: 3, end: 9)))print(DeviceType \(data.subdata2ascii(start: 9, end: 14)))print(version \(data.subdata2ascii(start: 14, end: data.count)))print(data.toHex(withSpace: true))
}test()let apples 3
let oranges 5
//只要与结束引号()的缩进匹配就会删除每一行开始处的缩进
let quotation Even though theres whitespace to the left,the actual lines arent indented.Except for this line.Double quotes () can appear without being escaped.I still have \(apples oranges) pieces of fruit.
print(quotation)8、类和结构体
/** struct 类似 Kotlin 的 data class等价写法是data class Person(var firstName: String Matt, var lastName: String Mathias)*/
struct Person {var firstName Mattvar lastName Mathias
}var p Person(firstName: Jia, lastName: Jiefei)
print(p)//如果属性没有提供默认值结构体会根据属性生成默认的成员初始化方法并且直接打印结构体可以看到所有存储属性的值
struct Device {var name: Stringvar address: String// text 是计算属性打印时不会输出var text: String {return name\(name), address\(address)}
}
print(Device(name: Device, address: 11:22:33:44:55:66))//而类就没有默认成员初始化方法了需要自己编写初始化方法并且直接打印类实例不会输出各存储属性的值
class BleDevice {var name: Stringvar address: Stringrequired init(name: String, address: String) {self.name nameself.address address}
}
print(BleDevice(name: BleDevice, address: AA:BB:CC:DD:EE:FF))9、值类型和引用类型
//类是引用类型
class GreekGod {var name: Stringinit(name: String) {self.name name}
}let hecate GreekGod(name: Hecate)
let athena GreekGod(name: Athena)
let zeus GreekGod(name: Zeus)
let anotherHecate hecate
anotherHecate.name AnotherHecate
hecate.name //类是引用类型改变 anotherHecate.namehecate.name也会变//结构体是值类型
struct Pantheon {var chiefGod: GreekGod
}let pantheon Pantheon(chiefGod: hecate)pantheon.chiefGod.name // AnotherHecate
let greekPantheon pantheon
hecate.name Trivia
greekPantheon.chiefGod.name // Trivialet gods [athena, hecate, zeus]
let godsCopy gods
gods.last?.name Jupiter
godsCopy.last?.name // Jupiter//探究写时复制copy on write, COW
fileprivate class IntArrayBuffer {var storage: [Int]init() {storage []}init(buffer: IntArrayBuffer) {storage buffer.storage}
}struct IntArray {private var buffer: IntArrayBufferinit() {buffer IntArrayBuffer()}func describe() {let str buffer.storage.map { i inString(i)}.joined(separator: , )print([\(str)])
// print(buffer.storage)}private mutating func copyIfNeeded() {//判断引用类型是否只有一个引用if !isKnownUniquelyReferenced(buffer) {print(Making a copy of \(buffer.storage))buffer IntArrayBuffer(buffer: buffer)}}mutating func insert(_ value: Int, at index: Int) {copyIfNeeded()buffer.storage.insert(value, at: index)}mutating func append(_ value: Int) {copyIfNeeded()buffer.storage.append(value)}mutating func remove(at index: Int) {copyIfNeeded()buffer.storage.remove(at: index)}
}var integers IntArray()
integers.append(1)
integers.append(2)
integers.append(4)
integers.describe()
var ints integers
ints.insert(3, at: 2)
integers.describe()
ints.describe()10、继承
虽然是讲继承但代码中的注释也会涉及其他知识点例子涉及3个.swift文件
Town.swift
struct Town {let region: Stringvar population: Int {didSet {print(The population has changed to \(population) from \(oldValue))}}var numberOfStoplights: Int//自定义初始化方法问号表示可失败的初始化方法init?(region: String, population: Int, stoplights: Int) {guard population 0 else {return nil}self.region regionself.population populationnumberOfStoplights stoplights}//委托初始化init?(population: Int, stoplights: Int) {self.init(region: N/A, population: population, stoplights: stoplights)}enum Size {case smallcase mediumcase large}//计算属性var townSize: Size {get {print(town size)//每次调用都会打印switch self.population {case 0...10_000:return Size.smallcase 10_001...100_000:return Size.mediumdefault:return Size.large}}}//惰性存储属性注意这里的等号以及结尾的圆括号lazy var name: String {print(town name)//这里只会打印一次即第一次访问该属性时return XiShe}()func printDescription() {print(Population: \(population), number of stoplights: \(numberOfStoplights), region: \(region))}/* 如果结构体确切的说应该是值类型结构体和枚举都是值类型的一个实例方法需要修改结构体的属性就必须使用 mutating 标记该方法 */mutating func changePopulation(by amount: Int) {population amount}/* 对于值类型类型方法使用static标记 */static func xxx() {}
}
Monster.swift
class Monster {// static 属性无法被子类覆盖static let isTerrifying true// class 属性可被子类覆盖class var spookyNoise: String {return Grrr}var town: Town?var name: Stringvar victimPool: Int {get {return town?.population ?? 0}set {town?.population newValue}}//子类必须得实现的初始化方法required init(town: Town?, monsterName: String) {self.town townname monsterName}func terrorizeTown() {if town ! nil {print(\(name) is terrorizing a town!)} else {print(\(name) hasnt found a town to terrorize yet...)}}/* 对于类类型方法使用class或者static标记区别在于static标记的方法无法被子类重写也可以使用final class代替static */static func makeSpookyNoise() {print(Brains...)}
}Zombie.swift
class Zombie: Monster {override class var spookyNoise: String {return Brains...}var walkWithLimp: Bool//只将 set 属性设置为私有get 属性为默认的 internalprivate(set) var isFallingApart: Bool//指定初始化方法init(limp: Bool, fallingApart: Bool, town: Town?, monsterName: String) {walkWithLimp limpisFallingApart fallingApart//如果有父类子类的指定初始化方法必须调用父类的指定初始化方法super.init(town: town, monsterName: monsterName)}//便捷初始化方法必须调用指定初始化方法或者其他便捷初始化方法但最终都要调用指定初始化方法以确保所有属性都进行了初始化convenience init(limp: Bool, fallingApart: Bool) {self.init(limp: limp, fallingApart: fallingApart, town: nil, monsterName: Fred)if walkWithLimp {print(This zombie has a bad knee.)}}required init(town: Town?, monsterName: String) {walkWithLimp falseisFallingApart falsesuper.init(town: town, monsterName: monsterName)}//实例被清除出内存时会触发反初始化deinit {print(Zombie named \(name) is no longer with use.)}//final 禁止子类重写该方法final override func terrorizeTown() {if !isFallingApart {town?.changePopulation(by: -10)}super.terrorizeTown()}
}测试代码
var town Town(region: West, population: 10, stoplights: 6)
town?.printDescription()
for _ in 0..3 {if let townSize town?.townSize, let townName town?.name {print(townSize)print(townName)}town?.changePopulation(by: 1_000_000)
}
//let genericMonster Monster()
//genericMonster.town town
//genericMonster.terrorizeTown()
var fredTheZombie: Zombie? Zombie(limp: false, fallingApart: false, town: town, monsterName: Fred)
//fredTheZombie.terrorizeTown()
//fredTheZombie.town?.printDescription()
//Monster.makeSpookyNoise()
print(Victim pool: \(fredTheZombie?.victimPool))
fredTheZombie?.victimPool 500
fredTheZombie nil
print(Monster.spookyNoise)
print(Zombie.spookyNoise)
11、数组和字典
//初始化数组的3种方式本人习惯上倾向使用第一种
//使用 var 就是可变数组let就是不可变数组
var bucketList: ArrayString []
var bucketList2:[String] [haha]
var arr [Int]()
arr.append(1)
arr.append(3)
arr.append(2)
//print(bucketList.count\(bucketList.count) arr[0]\(arr[0]))
//数组排序
let sortedArray arr.sorted(by: {a, b ina b
})
print(sortedArray)
//注只有ArrayString 才有 joined 方法如果元素类型不是 String得先通过 map 方法转一次
let joinedString arr.map { i inString(i)
}.joined(separator: , )
print([\(joinedString)])//字典也有多种初始化方式这里只列出其中一种
//使用 var 就是可变字典let就是不可变字典
var dict: DictionaryString, Int [:]
dict[one] 1
dict[two] 2
dict[three] 3
//遍历字典
for (key, value) in dict {print(\(key) \(value))
}
dict.removeValue(forKey: one)
dict[two] nil //将值设置为nil来删除键值对
print(dict)