❤ swift语法的重难点-包含swiftJson

闭包部分的逃逸闭包和自动闭包 https://juejin.cn/post/7000556808863481886

一) 枚举部分的: 递归枚举

https://www.w3xue.com/exp/article/20204/83930.html

//递归枚举值实例
enum Expression{
    //单个数值
    case num(param:Int)
    //表示加法运算 将Expression作为相关值参数类型
    indirect case add(param:Expression,param2:Expression)
    //表示减法运算 将Expression作为相关值参数类型
    indirect case sub(param:Expression,param2:Expression)
    //表示乘法运算 将Expression作为相关值参数类型
    indirect case mul(param:Expression,param2:Expression)
    //表示除法运算 将Expression作为相关值参数类型
    indirect case div(param:Expression,param2:Expression)
}
//使用递归枚举实现((4+4)*2-8)/2的复合表达式
//创建单值4
var num = Expression.num(param: 4)
//进行4+4运算
var num4Add4 = Expression.add(param: num, param2: num)
var num2 = Expression.num(param: 2)
//进行(4+4)*2
var numMul2 = Expression.mul(param: num4Add4, param2: num2)
var num3 = Expression.num(param: 8)
//进行(4+4)*2-8
var numSub8 = Expression.sub(param: numMul2, param2: num3)
var num4 = Expression.num(param: 2)
//进行((4+4)*2-8)/2
var numDiv = Expression.div(param: numSub8, param2: num4)
 
//定义功能方法
func expressionFunc(param:Expression)->Int{
    switch param {
    case let .num(param: val):
        return val
    case let .add(param: val1, param2: val2):
        return expressionFunc(param: val1)+expressionFunc(param: val2)
    case let .mul(param: val1, param2: val2):
        return expressionFunc(param: val1)*expressionFunc(param: val2)
    case let .sub(param: val1, param2: val2):
        return expressionFunc(param: val1)-expressionFunc(param: val2)
    case let .div(param: val1, param2: val2):
        return expressionFunc(param: val1)/expressionFunc(param: val2)
    }
}
//方法调用
print(expressionFunc(param: numDiv))

二) 结构体和类对比

Swift 中结构体和类有很多共同点。两者都可以:

  • 定义属性用于存储值

  • 定义方法用于提供功能

  • 定义下标操作用于通过下标语法访问它们的值

  • 定义构造器用于设置初始值

  • 通过扩展以增加默认实现之外的功能

  • 遵循协议以提供某种标准功能

更多信息请参见 属性、方法、下标、构造过程、扩展 和 协议。

与结构体相比,类还有如下的附加功能:

  • 继承允许一个类继承另一个类的特征

  • 类型转换允许在运行时检查和解释一个类实例的类型

  • 析构器允许一个类实例释放任何其所被分配的资源

  • 引用计数允许对一个类的多次引用

三) @IBDesignable和@IBInspectable

https://blog.csdn.net/tounaobun/article/details/39890667
说,可以将自定义的代码实时渲染到Interface Builder中。而它们之间的桥梁就是通过两个指令来完成,即@IBDesignable和@IBInspectable。我们通过@IBDesignable告诉Interface Builder这个类可以实时渲染到界面中,但是这个类必须是UIView或者NSView的子类。通过@IBInspectable可以定义动态属性,即可在attribute inspector面板中可视化修改属性值。

使用方法:在swift里,@IBDesignable关键字写在class前即可。
在OC里,是IB_DESIGNABLE这个关键字,写在@implementation前即可
IBInspectable
主要作用:使view内的变量可视化,并且可以修改后马上看到

使用方法:在swift里,@IBInspectable关键字写在需要显示的变量前即可
在OC里,是IBInspectable这个关键字,写在需要显示的变量前即可
另外附两个快捷键:
command+shift+O,快速打开需要的文件
control+shift+鼠标左击sb,可以选择需要的sb活着view

四) 闭包 相关

闭包


{ (parameters) -> return type in
    statements
}

  weatherService.retrieveWeatherInfo(location) { (weather, error) -> Void in
      DispatchQueue.main.async(execute: {
        if let unwrappedError = error {
          print(unwrappedError)
          self.update(unwrappedError)
          return
        }

        guard let unwrappedWeather = weather else {
          return
        }
        self.update(unwrappedWeather)
      })
    }

关键词:in

viewModel?.location.observe {
            [unowned self] in
            self.locationLabel.text = $0
            
            let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeText as String)
            attributeSet.title = self.locationLabel.text
            
            let item = CSSearchableItem(uniqueIdentifier: self.identifier, domainIdentifier: "com.rushjet.SwiftWeather", attributeSet: attributeSet)
            CSSearchableIndex.default().indexSearchableItems([item]){error in
                if let error =  error {
                    print("Indexing error: \(error.localizedDescription)")
                } else {
                    print("Location item successfully indexed")
                }
            }
        }

五) 泛型相关

class Observable {
  typealias Observer = (T) -> Void
  var observer: Observer?

  func observe(_ observer: Observer?) {
    self.observer = observer
    observer?(value)
  }

  var value: T {
    didSet {
      observer?(value)
    }
  }

  init(_ value: T) {
    self.value = value
  }
}

六) fileprivate

private 表示代码只能在当前作用域或者同一文件中同一类型的作用域中被使用,
fileprivate 表示代码可以在当前文件中被访问,而不做类型限定。

https://blog.csdn.net/a18339063397/article/details/87862081

一个当前文件可用, 一个当前的文件不可用

//ViewController.swift
class Person: NSObject {
 
    fileprivate var name:String = "man"
    
    private var age:Int = 1
}
 
class ViewController: UIViewController {
 
    override func viewDidLoad() {
        super.viewDidLoad()
    
        let p = Person()
        print(p.name)
        
        //编译器不会提示age属性 如果强行写p.age
        //会报错'age' is inaccessible due to 'private' protection level
        //print(p.age)
    }
}
log:  man
//ViewController.swift
extension Person {
    
    func printAge()  {
        print(self.age)
        //在 当前文件的 extension 中,调用private 修饰的属性没问题
    }
    
    func prinName()  {
      //在 当前文件的 extension 中,调用fileprivate 修饰的属性没问题
        print(self.name)
    }
}
 
    override func viewDidLoad() {
        super.viewDidLoad()
    
        let p = Person()        
        p.printAge()
        p.prinName()
    }

七) QuickSpec 写单元测试

qucik 写单元测试
https://juejin.cn/post/6844903510870327303

八) qucik 写 UItest

九 @objc

Objective-C 对象是基于运行时的,方法或属性使用动态派发 ,在运行调用时再决定实际调用的具体实现。而 Swift 为了追求性能,如果没有特殊需要的话,是不会在运行时再来决定这些的。也就是说,Swift 类型的成员或者方法在编译时就已经决定,而运行时便不再需要经过一次查找,而可以直接使用。

Objective-C 中所有类都继承自NSObject,Swift 中的类如果要供 Objective-C 调用,必须也继承自NSObject。

十 . 若扩展名前加@noobjc,则该扩展的所有方法都不会隐式添加@objc(排除类名前加@objcMembers的影响);

swift json 的语法解析:

public enum SwiftyJSONError: Int, Swift.Error {
   case unsupportedType = 999
   case indexOutOfBounds = 900
   case elementTooDeep = 902
   case wrongType = 901
   case notExist = 500
   case invalidJSON = 490
}

Swift.Error 是一种协议 。

extension SwiftyJSONError: CustomNSError {

扩展遵守协议

  public var errorCode: Int { return self.rawValue }
  public init(data: Data, options opt: JSONSerialization.ReadingOptions = []) throws {
        let object: Any = try JSONSerialization.jsonObject(with: data, options: opt)
        self.init(jsonObject: object)
    }

   public mutating func merge(with other: JSON) throws {
        try self.merge(with: other, typecheck: true)
    }

    /// JSON type, fileprivate setter
    public fileprivate(set) var type: Type = .null
 public subscript(path: JSONSubscriptType...) -> JSON {
        get {
            return self[path]
        }
        set {
            self[path] = newValue
        }
    }

一个叫做 path 的 JSONSubscriptType... 型可变参数,在函数体内可以当做一个叫 path 的 [JSONSubscriptType] 型的数组常量。

            case .key(let key):     self[key: key] = newValue
   public enum JSONKey {
    case index(Int)
    case key(String)
}

    func encode(_ parameters: Parameters?, into request: URLRequest) throws -> URLRequest

为了表示一个函数、方法或构造器可以抛出错误,在函数声明的参数之后加上 throws 关键字。一个标有 throws 关键字的函数被称作 throwing 函数。如果这个函数指明了返回值类型,throws 关键词需要写在返回箭头(->)的前面。

func canThrowErrors() throws -> String

func cannotThrowErrors() -> String

只读计算属性的声明可以去掉 get 关键字和花括号:

struct Cuboid {
   var width = 0.0, height = 0.0, depth = 0.0
   var volume: Double {
       return width * height * depth
   }
}

如果一个函数的整个函数体是一个单行表达式,这个函数可以隐式地返回这个表达式。举个例子,以下的函数有着同样的作用:

public static func userAgent(_ value: String) -> HTTPHeader {
        HTTPHeader(name: "User-Agent", value: value)
    }

swift的 static
总结

 static能修饰class/struct/enum的计算属性、存储属性、类型方法;class能修饰类的计算属性和类方法
 static修饰的类方法不能继承;class修饰的类方法可以继承
 在protocol中要使用static
func tryMapError(_ transform: (Failure) throws -> NewFailure) -> Result {
     switch self {
     case let .failure(error):
         do {
             return try .failure(transform(error))
         } catch {
             return .failure(error)
         }
     case let .success(value):
         return .success(value)
     }
 }

NewFailure: Error 是泛型的约束

image.png
image.png

你可能感兴趣的:(❤ swift语法的重难点-包含swiftJson)