2. Basic problem solving area
▐ 2.1 Class and struct
Class is a class, struct is a struct, class is a reference type, struct is a value type, struct can not inherit
▐ 2.2 What are the ways code can be reused (shared) without inheritance
Extension, global function
▐ 2.3 What methods are unique to Set?
SetB: set <Int> = [1, 2, 3, 4, 4] {1, 2, 3, 4} Set < Int > = [1, 3, 5, 7, 9] / / {1, 3, 5, 7, 9} / / and Set A | B let setUnion = setA. Union (setB) / / {1, 2, 3, 4, 5, 7, A &b let setIntersect = setA. Intersection (setB)// {1, {2, 4}} // setA - B let setRevers = setA. Subtracting (setB) {2, 4} A XOR B = A - B | B - A let setXor = setA.symmetricDifference(setB) //{2, 4, 5, 7, 9}Copy the code
▐ 2.4 Implement a min function that returns two smaller elements
func myMin<T: Comparable>(_ a: T, _ b: T) -> T {
return a < b ? a : b
}
myMin(1, 2)
Copy the code
▐ 2.5 Map, Filter, and Reduce functions
Maps are used for mapping, and you can transform one list into another
Map for [1, 2, 3]. {" ($0) "} / / digital array into a string array (" 1 ", "2", "3"]Copy the code
Filter Is used to filter out the desired elements
[1, 2, 3]. Filter {$0%2 == 0}Copy the code
Reduce merger
[1, 2, 3]. The reduce (" ") {$0 + "($1)"} / / converted to a string and stitching / / "123"Copy the code
Combination of the sample
(0 ..< 10).filter{$0 % 2 == 0}.map{"($0)"}.reduce(""){$0 + $1}// 02468
Copy the code
▐ 2.6 Differences between map and FlatMap
Public func flatMap
(_ transform: (Element) throws -> ElementOfResult?) Rethrows -> [ElementOfResult]. The middle function returns an optional value, while flatMap throws out values that return nil for example
["1", "@", "2", "3", "a"].flatMap{Int($0)}
// [1, 2, 3]
["1", "@", "2", "3", "a"].map{Int($0) ?? -1}//[Optional(1), nil, Optional(2), Optional(3), nil]
Copy the code
Public func flatMap
(_ transform: (Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Iterator.Element] where SegmentOfResult : The function in the middle of the Sequence returns an array, while the flapmap object returns an array of the same type as its element
func someFunc(_ array:[Int]) -> [Int] {
return array
}
[[1], [2, 3], [4, 5, 6]].map(someFunc) // [[1], [2, 3], [4, 5, 6]]
[[1], [2, 3], [4, 5, 6]].flatMap(someFunc)// [1, 2, 3, 4, 5, 6]
Copy the code
In fact, this implementation is similar to using map, and then put together the groups of numbers
[[1], [2, 3], [4, 5, 6]].map(someFunc).reduce([Int]()) {$0 + $1}
// [1, 2, 3, 4, 5, 6]
Copy the code
▐ 2.7 What is copy on write
Copy-on-write, which refers to the type of value in Swift, is not copied at the beginning of assignment, but only if it needs to be modified.
▐ 2.8 How do I get the function name and line number of the current code
#file for the current file name #line for the current line number #column for the current column number #function for the current function name these are special literals, mostly used for debugging output logs
▐ 2.9 How to declare a protocol that can only be conform
To declare a protocol, add a class
protocol SomeClassProtocl: class {
func someFunction()
}
Copy the code
▐ 2.10 Guard Usage Scenarios
Guard is similar to if, except that guard always has an else statement. If the expression is false or the value binding fails, the else statement is executed, and the function call must be stopped in the else statement for example
guard 1 + 1 == 2 else {
fatalError("something wrong")
return
}
//true
....
Copy the code
When a user logs in, verify that the user has entered a user name or password
guard let userName = self.userNameTextField.text,
let password = self.passwordTextField.text else {
return
}
Copy the code
▐ 2.11 Use scenarios of defer
The code in the defer statement block is called before the current scope ends, with common scenarios such as closing the database connection after an abnormal exit
func someQuery()-> ([Result], [Result]){
let db = DBOpen("xxx")
defer {
db.close()
}
guard results1 = db.query("query1") else {
return nil
}
guard results2 = db.query("query2") else {
return nil
}
return (results1, results2)
}
Copy the code
It is important to note that if there are multiple deferred, the last deferred will be executed first
func someDeferFunction() { defer { print("\(#function)-end-1-1") print("\(#function)-end-1-2") } defer { print("\(#function)-end-2-1") print("\(#function)-end-2-2") } if true { defer { print("if defer") } print("if end") } Print ("function end")} someDeferFunction() // if end // if defer // function end // someDeferFunction()-end-2-1 // someDeferFunction()-end-2-2 // someDeferFunction()-end-1-1 // someDeferFunction()-end-1-2Copy the code
▐ 2.12 The relationship and difference between String and NSString
NSString and String can be converted at will
let someString = "123"
let someNSString = NSString(string: "n123")
let strintToNSString = someString as NSString
let nsstringToString = someNSString as String
Copy the code
String is a structure, value type, NSString is a class, reference type. In general, there is no need to use the NSString class unless you are using some special method, such as the pathExtension property
▐ 2.13 How do I get the length of a String
I don’t care about encoding, I just want to know the number of characters, Devs. Count // 5 “Hello “. Devs. Count // 2” Proverb: Hello “. Devs
LengthOfBytes (using:.ascii) // 5 “hello”. LengthOfBytes (using: .unicode) // 10 “hello “. LengthOfBytes (using:.unicode) // 4” hello “. LengthOfBytes (using:.unicode) Utf8) / / 6 “こ ん に ち は”. LengthOfBytes (unicode) using: / / 10 “こ ん に ち は”. LengthOfBytes (using: utf8) / / 15
▐ 2.14 How to intercept St A string for ring
Swift has three substring fetching functions, substring:to, substring:from, and substring:with.
let simpleString = "Hello, world" simpleString.substring(to: simpleString.index(simpleString.startIndex, offsetBy: 5)) // hello simpleString.substring(from: simpleString.index(simpleString.endIndex, offsetBy: -5)) // world simpleString.substring(with: simpleString.index(simpleString.startIndex, offsetBy: 5) .. < simpleString.index(simpleString.endIndex, offsetBy: -5)) // ,Copy the code
▐ 2.15 Throws and rethrows usage and functions
Throws throws throws throws. There are two cases in which an error is thrown: _____ when thrown directly with a throw, _____ when another function that throws an exception is called without handling the exception directly with try xx. Such as
enum DivideError: Error { case EqualZeroError; } func divide(_ a: Double, _ b: Double) throws -> Double { guard b ! = Double (0) the else {/ / 1. Within a method directly throw throw DivideError. EqualZeroError} return a/b} func split (pieces: Int) throws -> Double {//2. Try calls the inner method to throw return Try divide(1, Double(pieces))}Copy the code
Rethrows is similar to throws, but only applies to functions that throw exceptions in parameters. Rethrows can be replaced with throws
func processNumber(a: Double, b: Double, functionC: (Double, Double) throws -> Double) rethrows -> Double {
return try functionC(a, b)
}
Copy the code
▐ 2.16 The try? And the try! What does that mean?
Both of these are used to handle functions that can throw exceptions, so you can use them without writing do catch. The difference is, try? When used to handle a function that can throw an exception, returns nil if the function throws an exception, otherwise returns an optional value of the value returned by the function, such as:
print(try? Divide (2, 1)) // Optional(2.0) print(try? divide(2, 0)) // nilCopy the code
But the try! It crashes when the function throws an exception, otherwise it returns a value equivalent to (try? xxx)! , such as:
print(try! Divide (2, 1)) // 2.0 print(try! Divide (2, 0)) // CrashCopy the code
▐ 2.17 The role of associatedtype
In simple terms, protocol uses generics to define a list protocol for example
protocol ListProtcol {
associatedtype Element
func push(_ element:Element)
func pop(_ element:Element) -> Element?
}
Copy the code
When the protocol is implemented, typeAlias can be specified as a specific type using typeAlias, or it can be inferred automatically, for example
class IntList: ListProtcol {typeAlias Element = Int var list = [Element]() func push(_ Element: Element) { self.list.append(element) } func pop(_ element: Element) -> Element? { return self.list.popLast() } } class DoubleList: ListProtcol { var list = [Double]() func push(_ element: Self. List. Append (element)} func pop(_ element: Double) -> Double? { return self.list.popLast() } }Copy the code
You can also use generics
class AnyList<T>: ListProtcol {
var list = [T]()
func push(_ element: T) {
self.list.append(element)
}
func pop(_ element: T) -> T? {
return self.list.popLast()
}
}
Copy the code
You can use the WHERE clause to qualify the Element type, as in:
extension ListProtcol where Element == Int {
func isInt() ->Bool {
return true
}
}
Copy the code
▐ 2.18 When to use final
Final is used to restrict inheritance and overwriting. If you just want a final in front of an attribute. If you need to restrict the entire class from being inherited, you can add a final before the class name
▐ 2.19 The difference between public and Open
Both of these are used to declare functions in modules that need to be exposed to the outside world. The difference is that classes that are modified by public cannot be inherited outside the module, while open can be inherited arbitrarily
▐ 2.20 Declare an alias for a closure with one argument and no return value
There is no return value which means the return value is Void
typealias SomeClosuerType = (String) -> (Void)
let someClosuer: SomeClosuerType = { (name: String) in
print("hello,", name)
}
someClosuer("world")
// hello, world
Copy the code
▐ 2.21 What is the difference between the static and class keywords when defining static methods
Methods defined as static cannot be inherited by subclasses, whereas class can
class AnotherClass {
static func staticMethod(){}
class func classMethod(){}
}
class ChildOfAnotherClass: AnotherClass {
override class func classMethod(){}
//override static func staticMethod(){}// error
}
Copy the code
▐ 2.22 Use scenarios for Self
Self is usually used in a protocol to represent the implementer or subclass type of the implementer. For example, define a protocol for replication
protocol CopyProtocol {
func copy() -> Self
}
Copy the code
If implemented as a structure, change Self to a concrete type
struct SomeStruct: CopyProtocol {
let value: Int
func copySelf() -> SomeStruct {
return SomeStruct(value: self.value)
}
}
Copy the code
If implemented by a class, this is a bit more complicated and requires a required initialization method
class SomeCopyableClass: CopyProtocol {
func copySelf() -> Self {
return type(of: self).init()
}
required init(){}
}
Copy the code
▐ 2.23 The effect of the dynamic
Because Swift is a static language, there are no dynamic mechanisms for sending messages in Objective-C, and dynamic is what allows swift code to have dynamic mechanisms in Objective-C, and KVO is a common place to do that, If you want to monitor a property, you must mark it as Dynamic
▐ 2.24 When to use @objc
The @objc purpose is to be able to call Swift code normally when objective-C and Swift are mixed. Can be used to modify classes, protocols, methods, and properties. The common thing is when you define the delegate protocol, you declare some of the methods in the protocol as optional methods, using @objc
@objc protocol OptionalProtocol { @objc optional func optionalFunc() func normalFunc() } class OptionProtocolClass: OptionalProtocol { func normalFunc() { } } let someOptionalDelegate: OptionalProtocol = OptionProtocolClass() someOptionalDelegate.optionalFunc? (a)Copy the code
▐ 2.25 What is Optional implemented with
Optional is a generic enumeration defined roughly as follows:
enum Optional<Wrapped> {
case none
case some(Wrapped)
}
Copy the code
In addition to using let someValue: Int? In addition to = nil, let optional1: Optional
= nil
▐ 2.26 How do I customize subscript fetching
Implement subscript, such as \
extension AnyList { subscript(index: Int) -> T{ return self.list[index] } subscript(indexString: String) -> T? { guard let index = Int(indexString) else { return nil } return self.list[index] } }Copy the code
Indexes of other types than numbers are also allowed
▐ 2.27 ?? The role of
The default value of the optional value, which is returned if the optional value is nil. Such as \
let someValue = optional1 ?? 0
▐ 2.28 The role of the lazy
Lazy loading, when the property is to be used, to complete the initialization such as
class LazyClass { lazy var someLazyValue: Int = { print("lazy init value") return 1 }() var someNormalValue: Int = { print("normal init value") return 2 }() } let lazyInstance = LazyClass() print(lazyInstance.someNormalValue) Print (lazyInstance. SomeLazyValue) / / print / / normal init value / / 2 / / lazy init value / / 1Copy the code
▐ 2.29 A type represents an option that can represent several options at the same time (similar to UIViewAnimationOptions). What type is represented
public struct AnimationOptions : OptionSet {
public init(rawValue: UInt)
public static var layoutSubviews: UIView.AnimationOptions { get }
public static var curveEaseInOut: UIView.AnimationOptions { get } // default
public static var curveEaseIn: UIView.AnimationOptions { get }
...
Copy the code
public protocol OptionSet : RawRepresentable, SetAlgebra {
/// The element type of the option set.
///
/// To inherit all the default implementations from the `OptionSet` protocol,
/// the `Element` type must be `Self`, the default.
associatedtype Element = Self
init(rawValue: Self.RawValue)
}
Copy the code
Need to implement from OptionSet, generally using struct implementation. Because OptionSet requires a non-failable init(rawValue:) constructor, enumerations cannot do this. (the original value constructor of enumerations is failable, and some composite values cannot be represented by an enumeration value.)
struct SomeOption: OptionSet { let rawValue: Int static let option1 = SomeOption(rawValue: 1 << 0) static let option2 = SomeOption(rawValue:1 << 1) static let option3 = SomeOption(rawValue:1 << 2) } let options: SomeOption = [.option1, .option2]Copy the code
▐ 2.30 The role of inout
Input and output parameters, such as:
func swap( a: inout Int, b: inout Int) {
let temp = a
a = b
b = temp
}
var a = 1
var b = 2
print(a, b)// 1 2
swap(a: &a, b: &b)
print(a, b)// 2 1
Copy the code
▐ 2.31 What does Error need to do to be compatible with NSError
You can just convert it to SomeError. SomeError as NSError but there’s no error code, description, etc., if you want to have the same stuff as NSError, You only need to implement LocalizedError and CustomNSError. Some methods have default implementations and can be skipped. For example:
enum SomeError: Error, LocalizedError, CustomNSError {
case error1, error2
public var errorDescription: String? {
switch self {
case .error1:
return "error description error1"
case .error2:
return "error description error2"
}
}
var errorCode: Int {
switch self {
case .error1:
return 1
case .error2:
return 2
}
}
public static var errorDomain: String {
return "error domain SomeError"
}
public var errorUserInfo: [String : Any] {
switch self {
case .error1:
return ["info": "error1"]
case .error2:
return ["info": "error2"]
}
}
}
print(SomeError.error1 as NSError)
// Error Domain=error domain SomeError Code=1 "error description error1" UserInfo={info=error1}
Copy the code
▐ 2.32 What syntax sugars are used in the following code
[1, 2, 3].map{ $0 * 2 }
- [1, 2, 3], ExpressibleByArrayLiteral protocol realized with Array, used to receive Array literals \
- When map{XXX} uses a closure as the last argument, it can be written directly after the call, and the parentheses can be omitted if it is the only argument
- Closures do not declare function parameters, return value types, and quantities, relying on automatic inference of closure types \
- When there is only one sentence in a closure, the result of that sentence is automatically returned as the value \
▐ 2.33 What is a higher-order function
A function that can take a function as a parameter or return value is called a higher-order function, such as Map, Reduce, or filter
▐ 2.34 How to solve the reference loop
- When converted to a value type, only a class has a reference loop, so you can dereference the loop if you can do without the class
- The delegate uses the weak attribute
- In a closure, use the weak or unowned modifier for objects that are likely to have cyclic references
▐ 2.35 The following Does your code crash and say why
Var mutableArray = [1,2,3] for _ in mutableArray {mutablearray.removelast ()}Copy the code
Even if removeLast() is changed to removeAll(), this loop will execute count of times. Array is a value type, and removeLast() does not modify the captured value.
▐ 2.36 How to declare an extension method for a type whose element is a string in a collection
Use the WHERE clause to restrict Element to a String
extension Array where Element == String {
var isStringElement:Bool {
return true
}
}
["1", "2"].isStringElement
//[1, 2].isStringElement// error
Copy the code