Swift005-转型 可选链 其他知识点

Swift005-转型 可选链 其他知识点

转型

is 用于检测值的类型,as 用于转换类型。

import UIKit

class MyBaseClass {
    var baseName: String
    init(name: String) {
        self.baseName = name
    }
}

class MyAppleClass: MyBaseClass {
    var myPrice: Float
    init(name: String, price: Float) {
        self.myPrice = price
        super.init(name: name)
    }
}

class MyPenClass: MyBaseClass {
    var myColor: UIColor
    init(name: String, color: UIColor) {
        self.myColor = color
        super.init(name: name)
    }
}

class CastingTest: NSObject {

    lazy var myClassArray = [MyAppleClass(name: "富士", price: 2.5),
                             MyPenClass(name: "好得利", color: UIColor.blue),
                             MyAppleClass(name: "金帅", price: 3.3)]

    public class func testBasic() {
        CastingTest().testIs()
        CastingTest().testAs()
    }

    private func testIs() {

        for item in myClassArray {
            if item is MyAppleClass {
                let apple = item as! MyAppleClass
                print("\(apple.baseName) \(apple.myPrice)")
            } else if item is MyPenClass {
                let pen = item as! MyPenClass
                print("\(pen.baseName) \(pen.myColor)")
            }
        }
    }

    private func testAs() {
        // 向下转型,用类型转换操作符(as? 或 as!)
        // 当不确定向下转型是否成功时,用类型转换的条件形式(as?)。
        // 只确定向下转型一定会成功时,才使用强制形式(as!)。当试图向下转型为一个不正确的类型时,强制形式会触发一个运行时错误。
        for item in myClassArray {
            if let apple = item as? MyAppleClass {
                print("\(apple.baseName) \(apple.myPrice)")
            } else if let pen = item as? MyPenClass {
                print("\(pen.baseName) \(pen.myColor)")
            }
        }
    }

}

可选链

通过在属性、方法、或下标脚本的可选值后面放一个问号(?),即可定义一个可选链。

  • 如果目标有值,调用就会成功,返回该值
  • 如果目标为nil,调用将返回nil

感叹号(!)强制展开方法,属性,下标脚本可选链

  • 如果目标有值,调用就会成功,返回该值
  • 如果目标为nil,强制展开则报错

fatal error: unexpectedly found nil while unwrapping an Optional value

其他知识点

父类又叫超类
如果要重写父类中的方法,需要加 override
如果要访问父类中的方法(子类对象访问父类方法)用super(此时super表示self当前对象)

重写属性
你可以提供定制的 getter(或 setter)来重写任意继承来的属性,无论继承来的属性是存储型的还是计算型的属性。

子类并不知道继承来的属性是存储型的还是计算型的,它只知道继承来的属性会有一个名字和类型。所以你在重写一个属性时,必需将它的名字和类型都写出来。

注意点:
如果你在重写属性中提供了 setter,那么你也一定要提供 getter。
如果你不想在重写版本中的 getter 里修改继承来的属性值,你可以直接通过 super.someProperty来返回继承来的值,其中someProperty是你要重写的属性的名字。

重写属性观察器
你可以在属性重写中为一个继承来的属性添加属性观察器。这样一来,当继承来的属性值发生改变时,你就会监测到。
注意:你不可以为继承来的常量存储型属性或继承来的只读计算型属性添加属性观察器

防止重写
我们可以使用 final 关键字防止它们被重写。
如果你重写了final方法,属性或下标脚本,在编译时会报错。
你可以通过在关键字class前添加final特性(final class)来将整个类标记为 final 的,这样的类是不可被继承的,否则会报编译错误。

__weak 与__unretained有何区别?
__weak修饰的弱引用,如果指向的对象被销毁,那么指针会立马指向nil
__unretained修饰的弱引用,如果指向的对象被销毁,它的指针依然会指向之前的内存地址,很容易产生野指针(僵尸对象)

swift中Error

public protocol Error {
}

extension Error {
}

extension Error where Self.RawValue : SignedInteger {
}

extension Error where Self.RawValue : UnsignedInteger {
}

苹果文档第一个例子

// 枚举对Int值处理可能的Error分类
enum IntParsingError: Error {
    case overflow
    case invalidInput(Character)
}

// 扩展Int
extension Int {
    init(validating input: String) throws {
        // ...
        let c = _nextCharacter(from: input)
        if !_isValid(c) {
            throw IntParsingError.invalidInput(c)
        }
        // ...
    }
}

// 具体使用(捕获)
do {
    let price = try Int(validating: "$100")
} catch IntParsingError.invalidInput(let invalid) {
    print("Invalid character: '\(invalid)'")
} catch IntParsingError.overflow {
    print("Overflow error")
} catch {
    print("Other error")
}
// Prints "Invalid character: '$'"

第二个例子

// 自定义错误输出结构体
struct XMLParsingError: Error {
    enum ErrorKind {
        case invalidCharacter
        case mismatchedTag
        case internalError
    }

    let line: Int
    let column: Int
    let kind: ErrorKind
}
// 抛出错误
func parse(_ source: String) throws -> XMLDoc {
    // ...
    throw XMLParsingError(line: 19, column: 5, kind: .mismatchedTag)
    // ...
}
// 具体应用
do {
    let xmlDoc = try parse(myXMLData)
} catch let e as XMLParsingError {
    print("Parsing error: \(e.kind) [\(e.line):\(e.column)]")
} catch {
    print("Other error: \(error)")
}
// Prints "Parsing error: mismatchedTag [19:5]"

Alamofire中的错误示例

Alamofire中的错误处理,用单独的一个文件AFError来管理使用中的错误,其中自定义了枚举

public enum AFError: Error {
                                encoding process.
    public enum ParameterEncodingFailureReason {
        case missingURL
        case jsonEncodingFailed(error: Error)
        case propertyListEncodingFailed(error: Error)
    }

    
    public enum MultipartEncodingFailureReason {
        case bodyPartURLInvalid(url: URL)
        case bodyPartFilenameInvalid(in: URL)
        case bodyPartFileNotReachable(at: URL)
        case bodyPartFileNotReachableWithError(atURL: URL, error: Error)
        case bodyPartFileIsDirectory(at: URL)
        case bodyPartFileSizeNotAvailable(at: URL)
        case bodyPartFileSizeQueryFailedWithError(forURL: URL, error: Error)
        case bodyPartInputStreamCreationFailed(for: URL)

        case outputStreamCreationFailed(for: URL)
        case outputStreamFileAlreadyExists(at: URL)
        case outputStreamURLInvalid(url: URL)
        case outputStreamWriteFailed(error: Error)

        case inputStreamReadFailed(error: Error)
    }

    
    public enum ResponseValidationFailureReason {
        case dataFileNil
        case dataFileReadFailed(at: URL)
        case missingContentType(acceptableContentTypes: [String])
        case unacceptableContentType(acceptableContentTypes: [String], responseContentType: String)
        case unacceptableStatusCode(code: Int)
    }

    
    public enum ResponseSerializationFailureReason {
        case inputDataNil
        case inputDataNilOrZeroLength
        case inputFileNil
        case inputFileReadFailed(at: URL)
        case stringSerializationFailed(encoding: String.Encoding)
        case jsonSerializationFailed(error: Error)
        case propertyListSerializationFailed(error: Error)
    }

    case invalidURL(url: URLConvertible)
    case parameterEncodingFailed(reason: ParameterEncodingFailureReason)
    case multipartEncodingFailed(reason: MultipartEncodingFailureReason)
    case responseValidationFailed(reason: ResponseValidationFailureReason)
    case responseSerializationFailed(reason: ResponseSerializationFailureReason)
}

作者还将AFError进行了扩展,增加部分判断的方法,比如判断是否是无效的URL:

// MARK: - Error Booleans

extension AFError {
    /// Returns whether the AFError is an invalid URL error.
    public var isInvalidURLError: Bool {
        if case .invalidURL = self { return true }
        return false
    }
}

同时拓展中也遵守了LocalizedError协议来重写errorDescription属性,并且对已经分类enum的自定义错误类型进行拓展重写了属性localizedDescription,这样就构成了项目中完整的错误处理机制。比如在Alamofire编码解析方法方法encode中,有这么一段代码

do {
    let data = try JSONSerialization.data(withJSONObject: jsonObject, options: options)
    if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
        urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
    }
    urlRequest.httpBody = data
} catch {
    throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
}

其中就是对于JSON序列化时,通过 do { try } catch 的方式来捕获错误,如果捕获到,将抛出已经自定义好的 AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error)) 类型错误。

致命错误

喵神举例的两个使用的场景:

1.父类中的某些方法,不想让别人调用,可以在方法中加上fatalError,这样子类如果想到用必须重写
2.对于其他一切我们不希望别人随意调用,但是又不得不去实现的方法,我们都应该使用 fatalError 来避免任何可能的误会。

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

原文请移步

图片放入工程两个方式

1.Assets.xcassets内,同时生成描述文件Contents.json。且在打包后以Assets.car的形式存在,不能直接打开(据说工具ThemeEngine可以打开)。
以此方式放入的图片并不在mainBundle中,不能使用contentOfFile这样的API来加载图片,interface builder中使用图片时不需要后缀和倍数标识(@2x这样的)
2.在工程建立专门放图片的文件夹,然后放入图片

Assets优势:

1.性能好,节省Disk。Asset Catalogs会用一个高度优化的特殊格式来存所有图片,而不是一个一个的单独的图片资源,会更少的涉及频繁Disk I/O操作,且会按需下载适合你机型的合适分辨率的图片资源;
2.相对安全。图片资源得到一定程度保护(Asset.car不易打开)

swift中Data获取bytes数组

方法1:使用 [UInt8] 新的构造函数

/// 使用(data as NSData).bytes 并不优雅  毕竟要尽量脱离OC的框架
/// data是结构体  使用[UInt8]构造方法得到data的byte数组
let bytes = [UInt8](data)

方法2:通过 Pointer 指针获取

let bytes = data.withUnsafeBytes {
    [UInt8](UnsafeBufferPointer(start: $0, count: data.count))
}
print(bytes)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容