//从OC到swift1-27 在TestSwift2中查看
//7.String
//swift的字符串类型,跟OC的NSString,在API设计上还是有较大差异
//空字符串
var emptyStr1 = ""
var emptyStr2 = String()
var str: String = "1"
str.append("_2") //拼接
str = str + "_3" //重载
str += "_4" //重载
str = "\(str)_5" //插值
print(str.count) //1_2_3_4_5
var str0 = "123456"
print(str0.hasPrefix("123")) //true
print(str0.hasSuffix("456")) //true
//8.String的插入和删除
var str1 = "1_2"
str1.insert("_", at: str1.endIndex) //1_2_
str1.insert(contentsOf: "3_4", at: str1.endIndex)//1_2_3_4
str1.insert(contentsOf: "666", at: str1.index(after: str1.startIndex)) //1666_2_3_4
str1.insert(contentsOf: "888", at: str1.index(before: str1.endIndex)) //1666_2_3_8884"
str1.insert(contentsOf: "hello", at: str1.index(str1.startIndex, offsetBy: 4)) //1666hello_2_3_8884"
str1.remove(at: str1.firstIndex(of: "1")!) //666hello_2_3_8884
str1.removeAll { $0 == "6" } //hello_2_3_8884
var range = str1.index(str1.endIndex, offsetBy: -4)..<str1.index(before: str1.endIndex)
str1.removeSubrange(range) //hello_2_3_4
//9.Substring
//String可以通过下标、prefix、suffix等截取子串,子串类型不是String、而是Substring.
//Substring和它的base,共享字符串数据
var str2 = "1_2_3_4_5"
var subStr1 = str2.prefix(3) //1_2
var subStr2 = str2.suffix(3) //4_5
var range1 = str2.startIndex..<str2.index(str2.startIndex, offsetBy: 3)
var subStr3 = str2[range1] //1_2
print(subStr3.base) //最初的String 1_2_3_4_5
var str3 = String(subStr3) //Substring -> String 1_2 //Substring转为String时,会分配新的内存字符串数据
subStr3.append(contentsOf: "666") //1_2666 ////Substring发生修改时,会分配新的内存字符串数据
print(str2,subStr3) // 1_2_3_4_5 1_2666
//10.String与Character
for c in "jack" { //c是Character类型
print(c) //j //a //c // k
}
var str4 = "jack"
var c = str4[str4.startIndex] //c是Character类型 //j
//11.String相关的协议
/*
String、Array都遵守了这2个协议
BidirectionalCollection协议包含的部分内容:startIndex、endIndex属性、index方法
RangeReplaceableCollection协议包含的部分内容:append、insert、remove方法
Dictionary、Set也有实现上述协议中声明的一些方法,只是并没有遵守上述协议
*/
//12.多行String,如果要显示3引号,至少转义1个引号, 缩进以结尾的3引号为对齐线
let str5 = """
1 ""\"
"2"
3
'4'
"""
print(str5)
//13.String与NSString
//String与NSString之间可以随时随地桥接转换
//如果你觉得String的API过于复杂难用,可以考虑将String转为NSString
import Foundation
func test0() {
var str1: String = "jack"
var str2: NSString = "rose"
var str3 = str1 as NSString //修改str1不影响str3 它们肯定是2个不同的东西
var str4 = str2 as String //修改str2不影响str4
var str5 = str3.substring(with: NSRange(location: 0, length: 2))
print(str5)
//比较字符串是否相等
//String使用==运算符
//NSString使用isEqual方法,也可用==运算符,本质还是调用了isEqual方法,看汇编看出来的
}
test0()
//14.swift、OC桥接转换表 是通过as的意思
/* //swift不能转OC的可变,其他的都可以
String <=> NSString
String <- NSMutableString
Array <=> NSArray
Array <- NSMutableArray
Dictionary <=> Dictionary
Dictionary <- NSMutableDictionary
Set <=> NSSet
Set <- NSMutableSet
*/
func test1() {
var str = "123456"
// var str2 = str as NSMutableString
var str2 = NSMutableString(string: str) //真要转也可以
}
test1()
//*** class Person和class Person: NSObject内存结构
import Foundation
class Person: NSObject {
var age = 10
var weight = 20
}
var p = Person()
//print(Mems.memStr(ofRef: p))
//不加继承32字节 0x000000010000c338 0x0000000200000002 0x000000000000000a 0x0000000000000014 //meta data、引用计数、age、weight
//加继承32字节 0x011d80010000c331 0x000000000000000a 0x0000000000000014 0x0000000000000000
//isa、age、weight、对齐的
//15.只能被Class继承的协议,就不能被结构体等继承了
protocol Runnable1: AnyObject {} //AnyObject
protocol Runnable2: class {} //class
@objc protocol Runnable3 {} //@objc
//16.可选协议
//第1种方式,通过extension实现
protocol Runnable {
func run1()
func run2()
}
extension Runnable {
func run1() {}
}
//第2种方式:可以通过@objc定义可选协议,这种协议只能被class遵守
@objc protocol Walknabble {
func walk1()
@objc optional func wakl2()
func walk3()
}
class Dog: Walknabble {
func walk1() {
print("Dog walk1")
}
func walk3() {
print("Dog walk3")
}
}
var d = Dog()
d.walk1() //Dog walk1
d.walk3() //Dog walk3
//17.dynamic
//被@objc dynamic修饰的内容会具有动态性,比如调用方法会走Runtime那一套
class Stone: NSObject {
@objc dynamic func test1() {}
func test2() {}
}
var t = Stone()
t.test1() //看汇编 走 objc_msgSend
t.test2() //走虚函数
//18.KVC\KVO
//swift支持KVC\KVO的条件,属性所在类、监听器最终继承自NSObject,用@objc dynamic修饰对应的属性
class Observer: NSObject {
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
print("observeValue", change?[.newKey] as Any)
}
}
class Time: NSObject {
@objc dynamic var age: Int = 0
var observer: Observer = Observer()
override init() {
super.init()
self.addObserver(observer, forKeyPath: "age", options: .new, context: nil)
}
deinit {
self.removeObserver(observer, forKeyPath: "age")
}
}
var tt = Time()
tt.age = 20 //serveValue Optional(20)
tt.setValue(25, forKey: "age") //observeValue Optional(25)
//19.blcok方式的KVO
class Phone: NSObject {
@objc dynamic var age: Int = 0
var observation: NSKeyValueObservation?
override init() {
super.init()
observation = observe(\Phone.age, options: .new, changeHandler: { (phone, change) in
print(change.newValue as Any)
})
}
}
var pp = Phone()
pp.age = 20 //Optional(20)
pp.setValue(25, forKey: "age") //Optional(25)
//20.关联对象
//在swift中,class依然可以使用关联对象,默认情况下,extension不可以增加存储属性,借助关联对象,可以实现类似extension为class增加存储属性的效果
class Egg{}
extension Egg {
private static var AGE_KEY: Void? // Void?类型只占一个字节
private static var WEIGHT_KEY = false //Bool类型只占一个字节
var age: Int {
get {
objc_getAssociatedObject(self, &Self.AGE_KEY) as? Int ?? 0
}
set {
objc_setAssociatedObject(self, &Self.AGE_KEY, newValue, .OBJC_ASSOCIATION_ASSIGN)
}
}
var weight: Int {
get {
objc_getAssociatedObject(self, &Self.WEIGHT_KEY) as! Int
}
set {
objc_setAssociatedObject(self, &Self.WEIGHT_KEY, newValue, .OBJC_ASSOCIATION_ASSIGN)
}
}
}
var egg = Egg()
egg.age = 10 //10
egg.weight = 20 //20
//21.资源名管理
//这种做法实际是参考了Android的资源名管理方式
import UIKit
enum R {
enum string: String {
case add = "添加"
}
enum image: String {
case logo
}
enum segue: String {
case login_main
}
}
//let img = UIImage(named: "logo")
//let btn = UIButton(type: .custom)
//btn.setTitle("添加", for: .normal)
let img = UIImage(named: R.image.logo.rawValue)
let btn = UIButton(type: .custom)
btn.setTitle(R.string.add.rawValue, for: .normal)
//22.资源名管理的其他思路
let img0 = UIImage(named:"logo")
let font0 = UIFont(name: "Arial", size: 14)
enum T {
enum image {
static var logo = UIImage(named: "logo")
}
enum font {
static func arial(_ size: CGFloat) -> UIFont? {
UIFont(name: "Arial", size: size)
}
}
}
let img1 = T.image.logo
let font1 = T.font.arial(14)
//23.多线程开发-异步
//小技巧:swift中NSThread打不出来时用打Thread
print(Thread.current,"main")
DispatchQueue.global().async {
DispatchQueue.main.async {
}
}
//或者
let item = DispatchWorkItem {
print("1", Thread.current)
}
DispatchQueue.global().async(execute: item)
item.notify(queue: DispatchQueue.main) {
}
//或者封装上面的一下 TestSwift2查看多线程即
public typealias Task = () -> Void
public struct Asyncs {
public static func async(_ task: @escaping Task) {
_async(task)
}
public static func async(_ task: @escaping Task, _ mainTask: @escaping Task) {
_async(task, mainTask)
}
private static func _async(_ task: @escaping Task, _ mainTask: Task? = nil) {
let item = DispatchWorkItem(block: task)
DispatchQueue.global().async(execute: item)
if let main = mainTask {
item.notify(queue: DispatchQueue.main, execute: main)
}
}
}
Asyncs.async {
print(1) //1
}
Asyncs.async {
print("1111", Thread.current)
} _: {
print("2222", Thread.current)
}
//1111 <NSThread: 0x600001cf4340>{number = 7, name = (null)}
//2222 <NSThread: 0x600001cb4080>{number = 1, name = main}
//24.多线程开发-延迟
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) {
print("1")
}
//25.多线程开发-异步延迟 TestSwift2查看多线程开发-异步延迟
//26.多线程开发-once TestSwift2查看
//27.多线程开发-加锁 TestSwift2查看
//DispatchSemaphore
public struct Cache0 {
private static var data = [String: Any]()
private static var lock = DispatchSemaphore(value: 1) //同时只有一个线程访问
public static func get(_ key: String) -> Any? {
data[key]
}
public static func set(_ key: String, _ value: Any) {
lock.wait() //锁
defer {
lock.signal() //解锁
}
data[key] = value
}
}
//NSLock
public struct Cache1 {
private static var data = [String: Any]()
private static var lock = NSLock()
public static func get(_ key: String) -> Any? {
data[key]
}
public static func set(_ key: String, _ value: Any) {
lock.lock() //锁
defer {
lock.unlock() //解锁
}
data[key] = value
}
}
//NSRecursiveLock
public struct Cache2 {
private static var data = [String: Any]()
private static var lock = NSRecursiveLock()
public static func get(_ key: String) -> Any? {
data[key]
}
public static func set(_ key: String, _ value: Any) {
lock.lock() //锁
defer {
lock.unlock() //解锁
}
data[key] = value
}
}
网友评论