IOS is a powerful generic and can also be extended to UIButton

Source: Internet
Author: User
Tags hashable

The article revolves around these five points:

1. What is a generic type?

2. Why use generics

3. How to use generics

4. Generics step-by-step

5. Extended use of generics

What is generics (generics)?

Refer to the description of generics in Apple:

Generic code enables you to write flexible, reusable functions and types the can work with any type, subject to Requireme NTS that define. You can write code that avoids duplication and expresses it intent in a clear, abstracted manner.

Generics was one of the most powerful features of Swift, and much of the Swift standard library was built with generic code . In fact, you ' ve been using generics throughout the Language guide, even if you didn ' t realize it. For example, Swift's Array and Dictionary types are both generic collections. You can create an array of holds Int values, or an array of that holds String values, or indeed an array for any other type That can is created in Swift. Similarly, you can create a dictionary to store values of any specified type, and there is no limitations on what that Ty PE can be.

To the effect of saying:

Generics allow you to use defined types to write flexible, reusable functions and types that avoid duplication and express their intentions in a clear, abstract way. In terms of employing words, generics give us more abstract encapsulation functions or classes of ability, not rigorous, the more abstract use of a language more convenient. Both the array and the dictionary in Swift are based on the generic type of collection, which is fine if you don't understand it, and here are a few examples to understand.

1. Generics in Objective-c

Apple launched the SWIFT 2.0 release on WWDC in 2015, in an effort to make it easier for developers to transition to Swift from Objective-c, which also brought generics generic support to Objective-c

Generics. Specify type information for collection classes like Nsarray, Nsset, and Nsdictionary. The type information improves Swift access when you are in the bridge from Objective-c and simplifies the code you has to write.

So we often see the generics in OC such as:

Instantiate an array with an element type of ' NSString '

Nsarray <nsstring *> *array = [Nsarray new];

or a dictionary.

Nsdictionary <nsstring *, nsnumber *> *dict = @{@ "Manoboo": @1}

Or:

-(void) Touchesbegan: (Nsset<uitouch *> *) touches withevent: (Uievent *) Event {

}

Let's take a look at what generics in OC probably did:

Open NSArray.h we can see:

@interface nsarray<__covariant objecttype>: NSObject <nscopying, nsmutablecopying, nssecurecoding, Nsfastenumeration>

@property (readonly) Nsuinteger count;

-(ObjectType) Objectatindex: (Nsuinteger) index;

-(instancetype) init ns_designated_initializer;

-(Instancetype) Initwithobjects: (const ObjectType _nonnull [_nullable]) objects count: (Nsuinteger) CNT ns_designated_ INITIALIZER;

-(Nullable Instancetype) Initwithcoder: (Nscoder *) Adecoder Ns_designated_initializer;

@end

The format for declaring a generics is as follows:

@interface class name < placeholder type name >

@end

Type restrictions can also be added after a placeholder type, such as:

@interface mbcollection <t:nsstring *>

@end

If you do not include a type limit, you accept that the ID is any type. Let's look at a simple example of using generics:

@interface mbcollection<__covariant t>: nsobject

@property (nonatomic, readonly) Nsmutablearray <T> *elements;

-(void) AddObject: (T) object;

-(BOOL) InsertObject: (T) object Atindex: (Nsuinteger) index;

@end

where T is our pre-declared placeholder type name, customizable (such as ObjectType, etc.), note that the scope of the T is limited to @interface mbcollection to @end, and the modifiers before the generic placeholder name can be divided into two types: __ Covariant ( covariant ) and __contravariant ( contravariance )

The difference between the two is as follows:

__covariant means covariant , meaning that a subclass can be forced to convert to (superclass) the parent class , followed by the L, the Richter substitution principle in solid, presumably can be described as: The object in the program should be replaced by its subclass without changing the correctness of the program [1]

__contravariant means inversion , meaning that the parent class can be coerced into subclasses.

Explain it with our custom generics above:

Mbcollection *collection;

Mbcollection <nsstring *> *string_collection;

Mbcollection <nsmutablestring *> *mstring_collection;

collection = String_collection;

String_collection = collection;

collection = Mstring_collection;

Generics of different types can be converted to each other without specifying a generic type by default.

At this point, you can add the modifier __covariant or __contravariant to control the conversion relationship before the placeholder generic name, like Nsarray using the __covariant modifier.

Extended:

In the above example, when declaring a property, you can also add a __kindof keyword before the generic, indicating that the type is the type or its subclasses, such as:

@property (nonatomic, readonly) Nsmutablearray <__kindof t> *elements;

After that, you can call the

Mbcollection <nsstring *> *string_collection;

nsmutablestring *str = String_collection.elements.lastObject;

There's no such type of warning.

Use __kindof to dismiss type warnings. png

2. Generics in Swift

Starting with the example of the Swift programming language

Func swaptwoints (_ A:inout int, _ b:inout int) {

Let Temporarya = a

A = b

b = Temporarya

}

This function is to exchange two int integer values, but imagine that this code can only exchange integer values, then we would like to exchange two string types or other more types? Might write Swaptwostrings, swaptwodoubles, how to change the exchange of two int values to exchange two values of the same type? How to encapsulate allows a function to be more abstract to support more types, so the generics are born, and you can see that using generics can broaden the scope of the method better and more abstractly

Func swaptwovalues<t> (_ A:inout T, _ B:inout t) {

Let Temporarya = a

A = b

b = Temporarya

}

1. Class/struct/enum + generics

Still using an example in the Swift programming language, how to implement a stack with generics, which makes it easy to implement pop and push with generics, eliminating the type conversion in Swift.

struct Stack<t> {

Private var collection = Array<t>.init ()

private var colection = [T] () equals above

var maxlength:int = 10

var topelement:t? {

Return collection.isempty? Nil:collection.last

}

Declaration can ignore return results

@discardableResult

Mutating Func Push (_ Object:t), Bool {

If Collection.count < maxLength {

Collection.append (object)

return True

}else {

return False

}

}

@discardableResult

Mutating func pop (), T {

Return Collection.removelast ()

}

}

Call

var stack = Stack<string>.init ()

Stack.push ("Mano")

Stack.push ("Boo")

Stack.push ("Welcome")

Stack.pop ()

If let Topelement = stack.topelement {

Print ("The top element is \ (topelement)")

}

We use generics to define a stack stack with an element type of T, a stack with a capacity of ten elements, a simple stack-up and a stack-out function, and a generic class or protocol, such as a struct stack, that can be qualified after the T-generics. <T:NSString>, struct stack<t:hashable>, struct stack<t:equatable>

Generics are widely used in swift, and common arrays, dictionary, etc. support generics, using the following:

var dict:dictionary<string, any>

var dict: [String:any]//Like the above function, just a shorthand for grammatical sugars

var arr: [String]

var arr:array<string>

Give another example [2]

Imitate Dictionary to customize a generic dictionary

struct genericsdictionary<key:hashable, value> {

private var data: [Key:value]

Init (Data:[key:value]) {

Self.data = Data

}

Subscript (Key:key), Value? {

return Data[key]

}

}

Use:

Let genericsdict = Genericsdictionary.init (data:["name": "Manoboo", "Age": 24])

Let name = genericsdict["Name"]

Let age = genericsdict["Age"]

What is the type of age at this time?

The subscript method has been introduced with generic support in Swift 4.0, so we can write:

Subscript<t> (Key:key), T? {

Return Data[key] as? T

}

Use:

Let name:string? = genericsdict["Name"]

Let Age:int? = genericsdict["Age"]

2. Protocol + generics

The generic usage scenarios that are common in Swift are described in the following section to see how to use protocol to encapsulate a small picture Request Extension Library template

In OC, our common third-party libraries are basically using category extensions to the original class, such as an example of sdwebimage:

Uiimageview *imageview = [[Uiimageview alloc] init];

[ImageView sd_setimagewithurl:[nsurl urlwithstring:@ "Http://www.domain.com/path/to/image.jpg"]

Placeholderimage:[uiimage imagenamed:@ "Placeholder.png"];

However, in many cases, we may repeat the naming, we may not know which library the method belongs to, thanks to the excellent expansion capability of extension in swift, we can avoid this problem very well, the code is as follows:

Public final class Ciimagekit<base> {

Public Let Base:base

Public init (_ Base:base) {

Self.base = Base

}

}

protocol need to use Associatedtype to preset a type

Public protocol Ciimagedownloaderprotocol {

Associatedtype type

var ci:type {Get}

}

Public extension Ciimagedownloaderprotocol {

public var ci:ciimagekit<self> {

get {

return Ciimagekit (self)

}

}

}

We declare a CIIMAGEDOWNLOADERPROTOCOL protocol, and for classes that comply with the protocol, there is an object of type Ciimagekit, and below we extend the Uiimageview

Extension Uiimageview:ciimagedownloaderprotocol {}

Extension Ciimagekit where Base:uiimageview {

Func setimage (Url:url, placeholder:uiimage?) {

The logic for downloading and caching and displaying pictures

}

}

This is a basic third-party library package template, how to invoke it?

Let image = Uiimageview ()

Image.ci.setImage (Url:URL.init (string: "https://www.manoboo.com")!, Placeholder:nil)

We classify the method into the Ciimage class through the middle layer of protocol, and we can also extend the UIButton

Extension Uibutton:ciimagedownloaderprotocol {}

Extension Ciimagekit where Base:uibutton {

Func setimage (Url:url, placeholder:uiimage?) {

The logic for downloading and caching and displaying pictures

}

}

IOS is a powerful generic and can also be extended to UIButton

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.