text
We usually useswift
When writing third-party extensions (categorized in OC), you may write methods directly into the extension, which is simple and convenient. However, when we look at some of the three parties that often use you (for example:Kingfisher、SnapKit
) and so on will be derived with a simple parameter (for example:kf
、snp
), let’s explore how to use it, and then summarize its advantages and disadvantages
A brief thought on SnapKit expansion method
bySnapKit
As an example, using the following, it was found that thesnp
var iv = UIImageView(); { make in }
Intermediate variablessnp
As shown below,ConstraintView
It is a rename (alias) for unifying different platforms
public extension ConstraintView { var snp: ConstraintViewDSL { return ConstraintViewDSL(view: self) } }
Its previous version also directlyleft
Prefixes, etc.snp_
, call it directly, and I think everyone can see the purpose at a glance. That's right, avoiding the duplication of other extensions. Now it has been changed to the introductionsnp
Indirectly calling, the actual logic is passedsnp
Come to call, my personal guess is also based on mainstream applications to update. When calling, at least the classification API is tidy
Pros and cons:
- 1. Introduce intermediate variables
snp
After that, the first thing I feel is that when we call our classification, there are obviously not so many messy methods (this method OC can actually be used as a reference) - 2. Cancel it
Prefix
, reduces the amount of code, and when there is a duplicate name with other classes, you only need to replace itsnp
The variable name is just not required to be replacedall
Method, reduce naming obstacles - 3. By introducing this parameter between different parties, our calling module identification is more obvious, the functional module is clearer, and the maintenance is stronger.
A brief thought on Kingfisher extension method
byKingfisher
As an example, using the following, it was found that thekf
var iv = UIImageView(); (with: URL(string: ""))
In addition, during use, it is fully utilizedswift
Features,SnapKit
More elegant and efficient in use
//Declare a basic protocol, which must be of AnyObject type, which can be used to subsequently add protocols to the basic class.public protocol KingfisherCompatible: AnyObject { } //Extend to implement this basic protocol so that our components can directly call the methods inside through .kf//This kf is similar to snap, except that it adds a generic to extend the limit between different classesextension KingfisherCompatible { public var kf: KingfisherWrapper<Self> { get { return KingfisherWrapper(self) } set { } } } //By the generic top one basic class one by one, through which the basic class we are extended can obtain the components we are extended//And through the generics of this basic class, different extension methods can be added to different types separatelypublic struct KingfisherWrapper<Base> { public let base: Base public init(_ base: Base) { = base } } // When the class following the protocol is UIImage, extend the methodextension KingfisherWrapper where Base: KFCrossPlatformImage { ... } // When the class following the protocol is KFCrossPlatformImageView, extend the method for itextension KingfisherWrapper where Base: KFCrossPlatformImageView { ... } ... //The above only defines a protocol that can be used after extension, and has not been applied to our basic components// Therefore, you only need to add extensions to the basic components and follow our protocolextension KFCrossPlatformImageView: KingfisherCompatible { }
The View without a name is an alias for the unified name of different platforms, as shown below (only for dispelling doubts)
#if os(iOS) || os(tvOS) public typealias ConstraintView = UIView #else public typealias ConstraintView = NSView #endif
Pros and cons:
- 1. Introduce intermediate variables
kf
After that, the first thing I feel is that when we call our classification, there are obviously not so many messy methods (this method OC can actually be used as a reference) - 2. In addition, the prefix can be cancelled to reduce the amount of code. When there is a duplicate name with other classes, you only need to replace it.
kf
The variable name is just for you, and you don't need to replace all methods, reducing naming obstacles - 3. By introducing this parameter between different parties, our calling module identification is more obvious, the functional module is clearer, and the maintenance is stronger.
- 4. Introduce protocols and generics, introduce the same intermediate variable through protocols, extend different methods to different categories through generics, reduce invalid methods and code, etc., and make the structure clearer. From a certain perspective, it is an advanced version of the extension method.
Try imitating yourself
public protocol MarshalTest: AnyObject {} struct Wrapper<T> { public let base: T init(_ base: T) { = base } } extension MarshalTest { var ml: Wrapper<Self> { get { Wrapper(self) } set { } } } extension UIImageView : MarshalTest {} extension Wrapper where T: UIImageView { func setImg() { } } extension Wrapper where T: UIView { func setBkg() { } } class ViewController: UIViewController { override func viewDidLoad() { var iv2 = UIImageView() () } }
This test is successful. When we imitate, we can refer to this writing
at last
When we extend content for the default component ourselves, if we only extend only one class and function, we cansnp
Likewise, you can directly introduce the intermediate variable extension. If our extensions are multiple categories and belong to a module, then we can imitate it.Kingfisher
, make our functions clearer
The above is the detailed content of Swift SnapKit imitates Kingfisher's third-party extension optimization example. For more information about SnapKit's third-party extension, please follow my other related articles!