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

  1. 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
  2. The delegate uses the weak attribute
  3. 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