swiftiOS学习

Swift小结

2019-09-25  本文已影响0人  纳兰沫

//TODO: 用于标记未完成的任务
// FIXNE: 用于标记待修复的问题
//#warning("todo") 警告

条件编译

//操作系统
#if os(macOS) || os(iOS)
//CPU架构
#elseif arch(x86_64) || arch(arm64)
//swift版本
#elseif swift(<5) && swift(>=3)
//模拟器
#elseif targetEnvironment(simulator)
//可以导入某模块
#elseif canImport(Foundation)
#else
#endif
强制断言.png
#if DEBUG
DEBUG 模式
#else
release 模式
#endif

如果需要自己自定义编译器模式 那么可以
第一种方法

WeChat0515ae36c50635b683ea74b2c317dff1.png

在DEBUG 后面加空格再加上自己的编译器模式
第二种方法

WeChatd1616ca286b55d8900a2cfbd09956e69.png

在里面填写-D 自己的自定义编译器模式

打印

func log<T>(_ msg: T,
            file: NSString = #file,
            line: Int = #line,
            fn: String = #function) {
    
    #if DEBUG
    let prefix = "\(file.lastPathComponent)_\(line)_\(fn):"
    print(prefix, msg)
    #endif
}

系统版本检测

if #available(iOS 10,macOS 10.12, *){
    //对与ios平台 只在ios10以及以上版本执行
    //对于macOS平台 只在macOS 10.12及以上版本执行
    //最后的* 表示在其他所有平台都执行
}

API可用性

struct Student {
    //study_不可用 改名为study
    @available(*,unavailable,renamed: "study")
    func study_() {
        
    }
    func study() {
        
    }
    @available(iOS, deprecated: 11)
    //macOS 的10.12开始 这个run方法不可用
    @available(macOS, deprecated: 10.12)
    func run() {
        
    }
}

var stu = Student()
stu.run()
错误.png

ios程序入口

1.在AppDelegate上面默认有个@UIApplicationMain标记 表示
  编译器自动生成入口代码(main函数代码) 自动设置AppDelegate为App的代理
2.也可以删除@UIApplicationMain 自定义入口代码 新建一个main.swift文件
import Foundation
import UIKit

class MyApplication: UIApplication {
    
}

UIApplicationMain(CommandLine.argc,
                  CommandLine.unsafeArgv,
                  NSStringFromClass(MyApplication.self),
                  NSStringFromClass(AppDelegate.self))

Swift调用OC

- 新建一个桥接头文件 文件名格式默认为 {targetName}-Bridging-Header.h
- 在相应的位置写入桥接头文件的位置
写入桥接头文件的位置.png

如果C语言暴露给Swift的函数跟Swift的函数冲突了 可以在swift中使用@_silgen_name 修改C函数名

@_silgen_name("sum")
func swift_sum(_ v1: Int32,_ v2: Int32) -> Int32

@_silgen_name 函数必须是存在的

OC调用Swift

- 默认生成一个桥接头文件 文件名格式默认为 {targetName}-Swift.h
文件存放的位置.png

Swift里面的类要想暴露给OC 必须继承于NSObject 要用@objc 修饰需要暴露给OC的成员和方法
可以使用@objcMembers 修饰Swift里面的类 使得整个类所有内容暴露给OC
Xcode会根据Swift代码默认生成相对应的OC代码 放在{targetName}-Swift.h中
可以使用@objc () 的方法重命名暴露给OC的类名 属性名 函数名等

Selector 选择器

使用#selector(name )定义一个选择器 

必须是被@objc 或者 @objcMembers 修饰的方法才可以定义选择器
因为选择器依赖于Runtime 而Runtime只在OC中有 Swift里面没有 所以 必须暴露给OC 才可以选择器

方法调用.png

为什么swift 中的暴露给OC的类最终要继承自NSObject

 OC依赖于Runtime Runtime要求有isa指针 isa指针一定要继承自NSObject
 OC的初始化alloc 也要继承自NSObject

Swift调用OC中的内容 底层是怎么调用的 返回来 OC调用Swift底层又是如果调用的

纯Swift 调用方法是虚表 也就是一个call一个假地址 然后寻找到真正的地址去调用方法
- Swift调用OC中方法是走的msg_send方法
- OC调用Swift方法是runtime流程  msg_send

如果swift类继承自NSObject 使用@objcMembers修饰 那么在swift里面调用swift方法走的是swift的方式 不走OC的msg_send流程
当你想走OC的msg_send流程 的时候 那么在方法前加dynamic进行修饰

上一篇下一篇

猜你喜欢

热点阅读