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