Swift

Swift小知识

2020-08-28  本文已影响0人  91阿生
1. 关于Swift中Protocol

1. 在 Swift 中,Delegate 就是基于 Protocol 实现的。
2. 定义委托时,我们让 protocol 继承自 AnyObject。这是由于,在 Swift 中,这表示这一个协议只能被应用于 class(而不是 struct 和 enum)。
3. 那么为什么不使用 class 和 NSObjectProtocol,而要使用 AnyObject 呢?NSObjectProtocol 来自 Objective-C,在 pure Swift 的项目中并不推荐使用。class 和 AnyObject 并没有什么区别,在 Xcode 中也能达到相同的功能,但是官方还是推荐使用 AnyObject。

2. 关于SnapKit适配 #available(iOS 11.0, *) 刘海适配
make.bottom.equalTo(self.view.safeAreaLayoutGuide.snp.bottom)
3. 是否全面屏(刘海屏) 适配 iOS 13.0+
    var cc_isFullScreen: Bool {
    if #available(iOS 13, *) {
        let scene = UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate
        guard let unwrappedWindow = scene?.window else {
        return false
    }
    
    if unwrappedWindow.safeAreaInsets.left > 0 ||
        unwrappedWindow.safeAreaInsets.bottom > 0 {
        return true
    }
    
    } else if #available(iOS 11, *) {
        guard let window = UIApplication.shared.delegate?.window, let unwrapped = window else {
          return false
       }
    
    if unwrapped.safeAreaInsets.left > 0 || unwrapped.safeAreaInsets.bottom > 0 {
        return true
    }
  }
  return false
}
4. 关于CGSize转String; String转CGSize
let size = CGSize(width: 200, height: 80)

 // CGSize转String
🌰:  let sizeString = "\(size)"  →  (200.0, 80.0)

 // String转CGSize
 字符串的size格式: {width, height}
 🌰:  let rsSize = NSCoder.cgSize(for: sizeString)  →  (200.0, 80.0)

注: NSCoder类, 需注意字符串格式

public class func string(for offset: UIOffset) -> String
public class func cgPoint(for string: String) -> CGPoint
public class func cgVector(for string: String) -> CGVector
public class func cgSize(for string: String) -> CGSize
public class func cgRect(for string: String) -> CGRect
public class func cgAffineTransform(for string: String) -> CGAffineTransform
public class func uiEdgeInsets(for string: String) -> UIEdgeInsets
5. 关于将字面量转换为特定的类型

Swift枚举中支持以下四种关联值类型:

Swift 3.0之前,字面量协议的名称:

- ExpressibleByArrayLiteral  数组字面量协议
- ExpressibleByBooleanLiteral  布尔值字面量协议
- ExpressibleByDictionaryLiteral  字典字面量协议
- ExpressibleByFloatLiteral 浮点数字面量协议
- ExpressibleByNilLiteral  nil字面量协议
- ExpressibleByIntegerLiteral 整数字面量协议
- ExpressibleByStringLiteral 字符串字面量协议

其中,ExpressibleByStringLiteral 字符串字面量协议还依赖于以下 2 个协议:
ExpressibleByUnicodeScalarLiteral
ExpressibleByExtendedGraphemeClusterLiteral
也就是说,实现 ExpressibleByStringLiteral 协议时,还需要实现其依赖的另外 2 个协议

🌰例子:

// 实现 CGSize 的字符串字面量协议
// NSCoder.cgSize(for: String), 针对CGSize时String的格式是: {width, height}

extension CGSize: ExpressibleByStringLiteral {
    public init(stringLiteral value: String) {
       let size = NSCoder.cgSize(for: value)
       self.init(width: size.width, height: size.height)
    }

    public init(extendedGraphemeClusterLiteral value: String) {
       let size = NSCoder.cgSize(for: value)
       self.init(width: size.width, height: size.height)
    }

   public init(unicodeScalarLiteral value: String) {
       let size = NSCoder.cgSize(for: value)
       self.init(width: size.width, height: size.height)
   }
}

enum Devices: CGSize {
  case i5 = "{320, 568}" // 设置值需要字符串类型
}

// 获取Devices.i5真实值, 需要访问枚举的是 rawValue 属性;  rawValue类型为CGSize
print(Devices.i5.rawValue) → (320.0, 568.0)

针对官方文档连接:
https://developer.apple.com/documentation/foundation/nscoder/1624484-cgsize

4. 关于iOS 15.0+ 列表滚动到导航栏后,导航栏颜色发生变化。禁止导航栏颜色发生变化
全局设置
if #available(iOS 15.0, *) { //UINavigationBarAppearance属性从iOS13开始
   let navBarAppearance = UINavigationBarAppearance()
   navBarAppearance.configureWithOpaqueBackground()
   // 背景色
   navBarAppearance.backgroundColor = UIColor.white

   self.navigationController?.navigationBar.standardAppearance = navBarAppearance
   self.navigationController?.navigationBar.scrollEdgeAppearance = navBarAppearance
 }
5. 关于iOS 11.0+ 禁止有导航栏 scrollView会默认把 scrollview 向下平移一个导航栏高度
if #available(iOS 11.0, *) {
     self.scrollView.contentInsetAdjustmentBehavior = .never
} else {
     self.automaticallyAdjustsScrollViewInsets = false
 }
6. 关于 百度地图SDK组件化 和 BMKLocationKit,Podfile 以及 xxx.podspec的配置
1、在 Podfile 里配置:
    #百度地图SDK现在使用的7个framework,为了支持ssl所以还添加了两个.a的静态库,这个时候需要使用如下命令来让cocoapods对静态库支持
    pre_install do |installer|
      # workaround for https://github.com/CocoaPods/CocoaPods/issues/3289
      Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_static_framework_transitive_dependencies) {}
    end

2、依赖 BaiduMapKit、BMKLocationKit时,需要配置的 podspec:
    # 依赖百度地图 SDK; 由于 BMKLocationKit 库中没有组件化文件,
    # 第一种方式 :自行添加 Modules文件夹 -> 修改 module.modulemap。问题:直接移进去,这样会导致 `pod install` 时可能丢失该文件
    # 第二种方式:使用 prepare_command 下载库文件完成时,执行一个脚本

  s.dependency 'BaiduMapKit'
  s.dependency 'BMKLocationKit'
  s.frameworks   = "BMKLocationKit", "BaiduMapAPI_Base", "BaiduMapAPI_Map", "BaiduMapAPI_Search", "BaiduMapAPI_Utils", "Accelerate"
  s.libraries    = "z", "crypto", "ssl", "c++", "sqlite3.0"
  # -undefined dynamic_lookup 这个表明了当主工程和framework都包含同一个库时,会优先使用主工程的库。
  s.pod_target_xcconfig = {
      # 'FRAMEWORK_SEARCH_PATHS'   => '$(inherited) $(PODS_ROOT)/BaiduMapKit/BaiduMapKit ${PODS_ROOT}/BMKLocationKit/framework',
      'LIBRARY_SEARCH_PATHS'     => '$(inherited) $(PODS_ROOT)/BaiduMapKit/BaiduMapKit/thirdlibs',
      'OTHER_LDFLAGS'            => '$(inherited) -undefined dynamic_lookup -ObjC',
      'ENABLE_BITCODE'           => 'NO'
  }
  # mkdir:创建目录(文件夹)touch:创建文件
  s.prepare_command     = <<-EOF
  mkdir ../../Pods/BMKLocationKit/framework/BMKLocationKit.framework/Modules
  touch ../../Pods/BMKLocationKit/framework/BMKLocationKit.framework/Modules/module.modulemap
  cat <<-EOF > ../../Pods/BMKLocationKit/framework/BMKLocationKit.framework/Modules/module.modulemap
  framework module BMKLocationKit {
    umbrella header "BMKLocationComponent.h"

    export *
    module * { export * }
  }
  \EOF
  EOF

7、记录 Podfile 相关指令

# as mentioned here https://github.com/react-native-maps/react-native-maps/issues/3597#issuecomment-745026120
#禁用 bitcode
post_install do |installer|
  installer.pods_project.targets.each do |target|
#    设置全部target ENABLE_BITCODE = NO
#    target.build_configurations.each do |config|
#      config.build_settings['ENABLE_BITCODE'] = 'NO'
#    end


#    target为 TUIChat || TUICore时,设置以下属性
    if target.name == 'TUIChat' || target.name == 'TUICore' || target.name == 'TUIConversation'
      target.build_configurations.each do |config|
        config.build_settings['ENABLE_BITCODE'] = 'NO'
        
#        config.build_settings['MACH_O_TYPE'] = 'Static Library'
#        config.build_settings['CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES'] = 'YES'
#        'LIBRARY_SEARCH_PATHS'     => '$(inherited) $(PODS_ROOT)/TUIChat/TUIChat/VoiceConvert',
#        'OTHER_LDFLAGS'            => '$(inherited) -undefined dynamic_lookup -ObjC',
      end
    end
  end
end

上一篇 下一篇

猜你喜欢

热点阅读