1. Swift to OC

Import in the bridge file swiftdemo-bridge-header. h, as follows:

#import <MJRefresh/MJRefresh.h>
#import "TestView.h"
#import "UIView+HUD.h"
Copy the code

However, it should be noted that after OC methods are automatically converted to Swift codes, the method names may change, such as singleton methods:

+ (instancetype)sharedModel;
Copy the code

The call in Swift is:

UserModel.shared()

Copy the code

2. OC to Swift

Import the project name -swift.h, which is an implicit file with the Swift code automatically converted by the system.

#import "SwiftDemo-Swift.h"
Copy the code

Note that @objc attributes and methods must be annotated before they are automatically converted to OC code. Such as:

Swift attribute: @objc var urlStr: String? @property (nonatomic, copy) NSString * _Nullable urlStr;Copy the code
Objc public cancelAllRequest() {} - (void)cancelAllRequest;Copy the code

Macros in Swift

Swift does not have the concept of macros. You can use global constants, global variables and global methods instead. Such as:

OC # define macros kAppWidth UIScreen. MainScreen. Bounds. Size. The width of Swift global constants let kAppWidth = UIScreen.main.bounds.size.widthCopy the code
#define kImageNamed(NAME) [UIImage imageNamed:NAME] func kImageNamed(_ NAME: String) -> UIImage? { return UIImage.imageNamed(name) }Copy the code

4. Classification processing

Swift classification has more applications than OC. In a Swift class, a classification is often used to implement a function module, such as:

// MARK: - TableView extension SwiftController: UITableViewDelegate, UITableViewDataSource {} // MARK: - Click event Extension SwiftController {}Copy the code

Add methods to the system class, such as:

Extension Dictionary {// MARK: func stringValue() -> String? { let data = try? JSONSerialization.data(withJSONObject: self, options: []) let str = String(data: data! , encoding: String.Encoding.utf8) return str } }Copy the code

OC can be called directly after importing from swiftdemo-bridge-header. h, for example:

@interface UIImage (Extention) /// waterImage - (UIImage *)waterImage; @end Swift calls let waterImg: UIImage = image! .water()Copy the code

5. Some special grammar

Syntax: swiftgg.gitbook. IO /swift

5.1. Type conversion

In Swift, values are never implicitly converted to other types, only explicitly, such as:

let a = 10;
let b = 1.0;
let c = a + Int(b);
let d = Double(a) + b;
let f = String(a)
let g = "\(a)"
Copy the code

5.2. Array dictionary initialization

let arr0: [Int] = [] let arr1: [Int] = [Int]() let arr2: [Int] = [Int].init() let arr3: [Int] = [Int].init(repeating: 0, count: 5) let dict0: [String: Int] = [:] let dict1: [String: Int] = [String: Int]() let dict2: [String: Int] = [String: Int].init() // Let arr4: (Int) = {() - > (Int) in the return} [1, 2] initialize () / / closure type, can be omitted () - > (Int) in the let arr5: [Int] = {return} [3, 4] ()Copy the code

5.3. Loop/Traverse

Forin cycle:

let interestingNumbers = [
    "Prime": [2, 3, 5, 7, 11, 13]
]
for (key, numbers) in interestingNumbers {
    for number in numbers {
    }
    
    for (index, value) in numbers.enumerated() {
	}
}
Copy the code

The while loop:

var n = 2
while n < 100 {
    n *= 2
}

var m = 2
repeat {
    m *= 2
} while m < 100
Copy the code

Interval loop:.. < create a scope that does not contain an upper bound, use…

for i in 0.. <4 {} for i in 0... 4 {} let names: [String] = ["a", "b", "c", "d"] for name in names[2...]  { print(name) } for name in names[...2] { print(name) }Copy the code

5.4 and unpack

If with an exclamation point (!) Forced unpacking:

if convertedNumber != nil {
    print("convertedNumber has an integer value of \(convertedNumber!).")
}
Copy the code

If let unpack:

If let constantName = someOptional {// someOptional has a value} else {// someOptional is empty} if let num = Int(optionalNum), Let constantName = optionalName, num > 10 {Copy the code

Guard let unpack:

Guard let name = person["name"] else {// person["name"] if empty, return} // person["name"] if there is a value, proceed furtherCopy the code

5.5. Strings

Seamless bridge between String and NSString:

var str: String = "a"
let nsStr: NSString = str as NSString
str = nsStr as String
Copy the code

Multi-line string (“””) :

let quotation = """
The White Rabbit put on his spectacles.  "Where shall I begin,
please your Majesty?" he asked.

"Begin at the beginning," the King said gravely, "and go on
till you come to the end; then stop."
"""
Copy the code

Through:

for character in "Dog! 🐶" {print(character)} for character in [character]("Dog! 🐶") {print(character)} for character in Array("Dog! 🐶 ") {print (character)}Copy the code

Character to string:

let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"] let catString = String(catCharacters) print(catString) // 🐱"Copy the code

String index, insert, delete, etc., is a tedious operation, usually converted to NSString and processed:

let str = "Guten Tag!" str[str.startIndex] // G str[str.index(before: str.endIndex)] // ! str[str.index(after: str.startIndex)] // u let index = str.index(str.startIndex, offsetBy: 7) str[index] // a var welcome = "hello" welcome.insert("!" , at: welcome.endIndex) let range = welcome.index(welcome.endIndex, offsetBy: -2).. <welcome.endIndex welcome.removeSubrange(range)Copy the code

Value types and reference types

In Swift, structs and enumerations are value types, and classes are reference types.

All of the basic types in Swift: Int, Float/Double, Bool, String, Array, and Dictionary are value types, and the underlying structure is implemented using structs.

When a value type is assigned to a variable, constant, or passed to a function, it is passed the copied value. let str0: String = "a" var str1 = str0 str1 += "b" print("str0 = \(str0), str1 = \(str1)") // str0 = a, str1 = abCopy the code
When a reference type is assigned to a variable, constant, or passed to a function, it passes the memory address. let nsStr0: NSMutableString = NSMutableString.init(string: "a") let nsStr1 = nsStr0 nsStr1.append("b") print("nsStr0 = \(nsStr0), nsStr1 = \(nsStr1)") // nsStr0 = ab, nsStr1 = abCopy the code

5.7, the set/get

Rewrite the set/get:

var num: Int {
    get {
        return 0
    }
    set(newNum) {
        print("\(newNum)")
    }
}
Copy the code

To simplify Setter declarations, use the default name newValue when the Setter for a property does not define a parameter name representing the newValue:

var num: Int {
    get {
        return 0
    }
    set {
        print("\(newValue)")
    }
}
Copy the code

Simplify Getter declarations by ignoring return in the Getter:

var num: Int {
    get {
        0
    }
    set {
        print("\(newValue)")
    }
}
Copy the code

A read-only computed property has only getters and no setters:

/ / the read-only attribute to the simplicity of the get method and will perform the code inside var kTopWindow: each UIWindow {var window = UIApplication. Shared. KeyWindow! if #available(iOS 13, *) { for wScene in UIApplication.shared.connectedScenes where wScene.activationState ! = UIScene.ActivationState.unattached { if let windowScene = wScene as? UIWindowScene, windowScene.windows.count > 0 { window = windowScene.windows.last! break } } } return window }Copy the code

5.8. Type Conversion

Checking types, using the type checking operator (is) to check whether an instance belongs to a particular subtype:

let num = 10
if num is Int {
    print(num)
}
Copy the code

The type conversion operator (as? Or as! :

let num = 10
if let newNum = num as? Int {
    print(newNum)
} else {}
    
let newNum = num as! Int
Copy the code

5.9 weak References

weak var weakSelf = self
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
    guard let strongSelf = weakSelf else {
        return
    }
}
Copy the code

5.10. Access control

The Open and public levels allow entities to be accessed by all entities in the same module source file, and outside the module, all entities in the source file can be accessed by importing the module. Typically, you can use the open or public level to specify the framework's external interface. Open only applies to classes and their members. The difference between open and public is that classes and members that open defines can be inherited and overridden outside the module. The internal level allows entities to be accessed by any entity in the same module source file, but not by entities outside the module. Typically, if an interface is only used within an application or framework, it can be set to the internal level, which is the default system access level. Fileprivate restricts access to entities only within the files they define. Fileprivate can be used to hide partial implementation details of functionality that only need to be used within a file. Private restricts entities to be accessible only in their defined scope, as well as extension within the same file. You can use private to hide some of the details of a function if they only need to be used in the current scope.Copy the code

5.11, singleton

static let sharedInstance: NetWorkSwift = NetWorkSwift()
Copy the code

5.12, the GCD

DispatchQueue.main.async {}

DispatchQueue.global().async {}

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2) {}
Copy the code

5.12, closures

Closure expression syntax:

{ (parameters) -> return type in
    statements
}
Copy the code

Common closures, executed sequentially without delay:

private func p_normal(finish: (_ num: Int) -> Void) {
    finish(10)
}

Copy the code

Escape closures can be delayed: when a closure is passed to a function as an argument, but the closure is not executed until the function returns, the closure is said to escape from the function.

private func p_escaping(finish: @escaping (_ num: Int) -> Void) { DispatchQueue.main.asyncAfter(deadline: .now() + 1) {finish(20)} print(30)} call p_escaping {num in print(num)} // Print 30 first, then 20Copy the code

5.13. Determine the system version

if #available(iOS 13, *) {}
Copy the code

5.14 protocol oriented programming

General Agreement:

Shakeable {func shake()} class ShakeView: UIView, Shakeable { func shake() { let animation = CABasicAnimation(keyPath: "Position ") animation.duration = 0.25 animation.repeatCount = 5 animation.autoreverses = true animation.fromValue = Init (x: self.center. X -4.0, y: self.center. Y) animation.toValue = cgPoint.init (x: self.center. Y) self.layer.add(animation, forKey: "position")}} class AnotherShakeView: UIView, Shakeable { func shake() { let animation = CABasicAnimation(keyPath: "Position ") animation.duration = 0.05 animation.repeatCount = 5 animation.autoreverses = true animation.fromValue = Init (x: self.center. X -4.0, y: self.center. Y) animation.toValue = cgPoint.init (x: self.center. self.center.y) self.layer.add(animation, forKey: "position") } }Copy the code

Protocol-oriented:

Shakeable {} extension Shakeable where Self: UIView { func shake() { let animation = CABasicAnimation(keyPath: "Position ") animation.duration = 0.25 animation.repeatCount = 5 animation.autoreverses = true animation.fromValue = Init (x: self.center. X -4.0, y: self.center. Y) animation.toValue = cgPoint.init (x: self.center. self.center.y) layer.add(animation, forKey: "position") } } class ShakeView: UIView, Shakeable {} class AnotherShakeView: UIView, Shakeable {}Copy the code

Code specification detection tool SwiftLint

Github.com/realm/Swift…

www.bbsmax.com/A/xl56GAykd…

Use Cocoapods to introduce:

pod 'SwiftLint'
Copy the code

Xcode will add a Run Script to Build Phases:

"${PODS_ROOT}/SwiftLint/swiftlint"
Copy the code

Configuring a custom rule:

To create configuration files using the command line: touch.swiftlint. yml To display hidden files using the command line: Finder AppleShowAllFiles -bool true Find. Swiftlint. yml. https://github.com/realm/SwiftLint note: when using, will. Swiftlint. Yml on the need to perform swiftlint project root directory, the whole project will perform. Swiftlint. Yml configuration; If the. Swiftlint. yml file is also configured in the secondary directory, the swiftlint.yml file is configured in the secondary directoryCopy the code

7. Common third parties

Network class uses Alamofire and Moya

Layout snapkit

Json processing SwiftJson and HandyJSON are introduced

The gallery Kingfisher

Responsive programming RxSwift

Encryption CryptoSwift

Swift, wCdb. swift