OOP and POP
The essence of Object Oriented Programming is the abstract thinking process and Object Oriented method reflected by establishing model. Models are meant to characterize things in the real world. Any model can not reflect all the specific characteristics of objective things, but can only be an abstraction of the characteristics and change rules of things, and describe the characteristics of the object more generally, more centrally and more profoundly within the scope it involves. The abstraction achieved through the establishment of models is the deepening of people’s understanding of objects
It is because of the efficacy of the whole, convenient storage and transmission of data! Object-oriented design, adopted in many languages! Oc-swift is also OOP. This is already very familiar to everyone, and it is no longer verbose here. Today’s main character is Protocol Oriented Programming (POP) a Protocol Oriented Programming
Object oriented dilemma
Wang Wei for protocol programming this article there is a detailed expression!
- Crosscutting concern
- Dynamic distribution security
- Diamond defects
POP protocol oriented programming
Protocol-oriented programming thinking is very, very important in Swift development! It can be said that if you use POP well, then your project is definitely not a level
POP addresses crosscutting concerns
Cross-cutting Concerns are that it’s hard to share code in classes with different inheritance relationships! Now that we’re protocol oriented, anyone that follows the protocol can add the name attribute and the sayHello() method by default!
Protocol LGProtocl {var name: String {get} func sayHello()}Copy the code
- But there’s a problem: lack of implementation! If I did that, I would have to implement it in every single class, and a lot of times these methods are actually common and don’t need a lot of implementation specificity
- Fortunately, in
WWDC 2015
εSwift 2
When released,Apple
A new feature has been introduced for the protocolProtocol extensionsIt brought about a revolutionary change in the Swift language.
struct LGTeacher: LGProtocl{
var name: String
func sayHello() {
print("Hello")}}Copy the code
- The protocol definition provides an entry point for implementation, which must be implemented according to the protocol type
- Protocol extension to provide a default implementation of the entry. Additional implementations are provided depending on the entry
What does this operation do? Everything is LG
Extension LGCompatible {Reactive extensions. Public static var Reactive extensions: LGRxSwift.Reactive<Self>.Type /// Reactive extensions. public var lg: LGRxSwift.Reactive<Self>} NSObject: LGCompatible {}Copy the code
- This perfectly realizes lg’s feature that everything is lg
- Then through
LGCompatible
Only theReactive
A responsive class or structure - And finally by expanding
Reactive
The ability to fit in perfectly
POP addresses dynamic distribution security
For types that do not implement LGProtocl, the compiler returns an error, so there is no case of messages being sent by mistake
// Compiler Error:
// 'LGTeacher' does not conform to protocol 'LGProtocl'
// protocol requires function 'sayHello()'
Copy the code
POP addresses the diamond defect
Finally, let’s look at multiple inheritance. An important problem with multiple inheritance is the diamond defect, in which subclasses cannot determine which parent class’s methods to use. In terms of protocol correspondence, this problem remains, but it can only be safely determined.
Unfortunately, POP has the same BUG in solving the rhombus BUG, because multiple protocols have the same protocol attributes, protocol methods, and adherence is not determined! β οΈ we in the usual development must try to avoid the same protocol to follow the problem, we must do in the module division above thoroughly, although Swift can not deal with the conflict of multiple protocols well, but we can in the protocol layer function extraction layer strictly intelligent processing up and down function.
For example: π°
-
Did we just make LGCompatible, which is the gateway to our functionality, where everything comes in lg, so this layer protocol just needs to provide the gateway
-
At the same time, it provides interface transition capability to transition LG of LGReactiveCompatible to Reactive
extension LGReactiveCompatible {
/// Reactive extensions.
public static var lg: Reactive<Self>.Type {
get { return Reactive<Self>.self }
set {// this enables using Reactive to "mutate" base type }
}
/// Reactive extensions.
public var lg: Reactive<Self> {
get { return Reactive(self) }
set { // this enables using Reactive to "mutate" base object }
}
}
Copy the code
Reactive
Layer, according to the business division, to achieve the effect of logic code sinking!
public struct Reactive<Base> {
public let base: Base
public init(_ base: Base) {
self.base = base
}
}
Copy the code
- According to the
Reactive
Inwardly relatedBase
Type to identify different responsive functions - Such as:
extension Reactive where Base: UISwitch
Among themUISwitch
Can be replaced byUITableView, UITextField, UIView
. Continuous business sinking!
I’m sure you’ve seen the benefits of protocol-oriented programming here, but there’s one very important feature that doesn’t show up: much less coupling, more layered code, and clearer logic
POP network
In our actual development, network request is a very important module
Alamofire.request("http://127.0.0.1:5000/pythonJson/") .validate(statusCode: 200.. <300) .validate(contentType: ["application/json"])
.responseData { response in
switch response.result {
case .success:
print(response)
let _ = LGLoginClient.lgJson(data: response.data)
case .failure(let error):
print(error)
}
}
Copy the code
- The above code, there is no mistake! But if you are an experienced iOS developer, you will find problems!
- If you were directly in
ViewController
(on behalf of the application layer) directly such a network request, the degree of coupling is very large (application layer and network layer coupled together) - There are nesting everywhere, reusability is particularly low
- The application layer shouldn’t care about network requests at all
Method, interface, and parameter
Frankly, I don’t want to care - If the system is modular, then I am very happy πππ
1οΈ retail: Network information capacity
enum LGHTTPMethod: String {
case GET
case POST
}
protocol LGRequest {
var host: String { get }
var path: String { get }
var method: LGHTTPMethod { get }
var parameter: [String: Any] { get }
associatedtype Response
func parse(data: Data) -> Response?
}
Copy the code
LGHTTPMethod
Provide this moduleLGRequest
Enumeration of required request methodsLGRequest
Is the request enabler of the login registration module, which provides capabilities to our module in a protocol-oriented mannerResponse
This association type is convenient for laterjson
Go to the model and set the generic type to be generic
2οΈ retail: Module information layer
struct LGLoginRequest: LGRequest {
typealias Response = LGPerson
let name: String
let host = "http://127.0.0.1:5000"
var path: String {
return "/pythonJson/getTeacherInfo/? username=\(name)"
}
let method: LGHTTPMethod = .GET
let parameter: [String: Any] = [:]
func parse(data: Data) -> LGPerson? {
return LGPerson(data: data)
}
}
Copy the code
LGLoginRequest
followLGRequest
To obtainHost, path, method, parameter, parse
Processing power, here can be directly processed, there is no need to go to the application layer to pass the value!
3οΈ discount: network request capacity
extension LGRequest {
func send(handler: @escaping (Response?) -> Void) {
let url = URL(string: host.appending(path))!
var request = URLRequest(url: url)
request.httpMethod = method.rawValue
let task = URLSession.shared.dataTask(with: request) {
data, response, error in
if let data = data, let res = self.parse(data: data) {
DispatchQueue.main.async { handler(res) }
} else {
DispatchQueue.main.async { handler(nil) }
}
}
task.resume()
}
}
Copy the code
- Because of protocol orientation, we use protocols to provide common network request capabilities
- Among them
Response
Is the specific type of the corresponding model
4οΈ retail: application layer call
override func viewDidLoad() {
super.viewDidLoad()
let request = LGPersonRequest(name: "Cooci")
request.send { (person) inself.updataUI(person: person!) }}Copy the code
- The application layer is completely separated from the network layer
- The application layer only provides necessary parameter information. Which interface to call and how to handle it
LGPersonRequest
Module information processing provides layerLGPersonRequest
It also has the ability to call the network
5οΈ retail: Optimization and reconstruction of POP network
Apparently our LGRequest guy is too capable! Can provide information, can also initiate requests, even serialization processing power is provided by LGRequest! Optimization and reconstruction is imminent…
1: Information provider
protocol LGRequest {
var path: String { get }
var method: LGHTTPMethod { get }
var parameter: [String: Any] { get }
associatedtype Response: LGDecodable
}
struct LGPersonRequest: LGRequest {
typealias Response = LGPerson
let name: String
var path: String {
return "/pythonJson/getTeacherInfo/? username=\(name)"
}
let method: LGHTTPMethod = .GET
let parameter: [String: Any] = [:]
}
Copy the code
- Put publicly provided
host
Taken out - No longer provide
LGRequest
Network request capability - Serialization is delivered to the concrete model, providing a serialization capability
LGDecodable
protocol ClientProtocol {
var host: String { get }
func send<T: LGRequest>(_ r: T, handler: @escaping (T.Response?) -> Void)
}
class LGClient: ClientProtocol{
static let manager = LGClient()
let host: String = "http://127.0.0.1:5000"
func send<T>(_ r: T, handler: @escaping (T.Response?) -> Void) where T : LGRequest {
let url = URL(string: host.appending(r.path))!
var request = URLRequest(url: url)
request.httpMethod = r.method.rawValue
let task = URLSession.shared.dataTask(with: request) {
data, response, error in
if let data = data, let res = T.Response.parse(data: data) {
DispatchQueue.main.async { handler(res) }
} else {
DispatchQueue.main.async { handler(nil) }
}
}
task.resume()
}
}
Copy the code
- Provides a network management class
LGClient
- Manage network request capabilities and common provisioning parameters
2: network capability provider
class LGLoginClient: LGClient {
override func send<T>(_ r: T, handler: @escaping (T.Response?) -> Void) where T : LGRequest {
switch r.path {
case let string where string.contains("/pythonJson/getTeacherInfo") :print("123456")
handler(nil)
default:
let url = URL(string: host.appending(r.path))!
var request = URLRequest(url: url)
request.httpMethod = r.method.rawValue
let task = URLSession.shared.dataTask(with: request) {
data, response, error in
if let data = data, let res = T.Response.parse(data: data) {
DispatchQueue.main.async { handler(res) }
} else {
DispatchQueue.main.async { handler(nil) }
}
}
task.resume()
}
}
}
Copy the code
- Module network capability layer
LGLoginClient
Rewrite, according to the different interface block processing - The serialization layer is handed over to the generic model (
T.Response
) processing - Of course, you can also continue to sink the network capacity, to the specific network comprehensive requestor to deal with
3: Serialization capability provision layer
extension LGPerson: LGDecodable {
static func parse(data: Data) -> LGPerson? {
return LGPerson(data: data)
}
}
Copy the code
- Serialization is simply expressed here, and you can call some optimized tripartite framework
6 οΈ β£ : summary
- POP network, so that the application layer and network layer completely separated!
- Protocol oriented programming to provide the ability to greatly expand the reuse, while the coupling degree can also be handled!
- At the same time, this model (application layer -> information supply layer -> network layer) programming thinking is easier to understand, operation is easier to get started!
- In addition, such programming habits are also in line with the development process (generally, it is the background developers who make corresponding interfaces before we do network debugging).
- Later maintenance is simple, later changes, we only need to provide information layer to deal with the response configuration, there is no need to move the application layer or network layer
- Of course, this is also the mainstream development thinking, as a mid-to-senior iOS developer does not move
POP
Network programming then I guess you need to study hard! πͺ πͺ πͺ
Recently I got some PDF documents of summary of iOS interview questions from my friends! Because the platform can not send files, friends in need can add QQ group: 679884541, there are iOS developers in the group, any problems and complaints we can communicate together!