11个资源强大的网站_快速的10个强大属性

11个资源强大的网站

@转义(@escaping)

It’s normally used as an escaping closure passed as a function argument. It exists in the memory when the function ends and then gets executed.

通常用作作为函数参数传递的escaping闭包。 当函数结束然后执行时,它存在于内存中。

When defining an optional closure as a property, it’s already escaping by default.

在将可选闭包定义为属性时,默认情况下已经在转义。

class Service {
    var closure: @escaping (() -> Void)? //error: closure is already escaping in optional type argument
}

The escaping closure can be stored for later use:

可以将转义的闭包存储起来以备后用:

class Service {


    var closure: (() -> Void)?


    func storageExample(with completion: @escaping (() -> Void)) {
        closure = completion // Stored for later use
    }
}

Or it can be executed after the function ends:

或者可以在函数结束后执行:

class Service {
    func asyncExample(with completion: @escaping  (() -> Void)) {
        DispatchQueue.global().async { // Excute escaping closure ayncally
            completion()
        }
    }
}

@未知(@unknown)

@unknown was introduced with @frozen and @nonfrozen enumerations. A non-frozen enum may gain new enumeration cases in the future. For instance, the UILayoutConstraintAxis contains two axes at the moment: AxisHorizontal and AxisVertical:

@unknown是由@frozen@nonfrozen枚举引入的。 非冻结枚举将来可能会获得新的枚举案例。 例如, UILayoutConstraintAxis包含两个轴: AxisHorizontalAxisVertical

enum UILayoutConstraintAxis: Int { 
  case UILayoutConstraintAxisHorizontal = 0
  case UILayoutConstraintAxisVertical = 1 
}

It may gain another case axisZ later:

以后可能会获得另一个case axisZ

enum UILayoutConstraintAxis: Int { 
  case UILayoutConstraintAxisHorizontal = 0 
  case UILayoutConstraintAxisVertical = 1
  case UILayoutConstraintAxisZ = 2
}

To safely avoid the compile error:

为了安全地避免编译错误:

error: switch must be exhaustive

We implement the switch with @unknown attributes:

我们使用@unknown属性实现开关:

switch axis {
case .UILayoutConstraintAxisHorizontal:
    print("")
case .UILayoutConstraintAxisVertical:
    print("")
@unknown default:
    print("")
}

@propertyWrapper(@propertyWrapper)

When applying a property wrapper to the property of a class, structure, or enumeration, it wraps access to the property through an instance of the wrapper type.

将属性包装器应用于类,结构或枚举的属性时,它将通过包装器类型的实例包装对属性的访问。

The wrapper must define a wrappedValue, which is the getter and setter for the property exposed. The following example trims whitespaces and newlines from incoming string values:

包装器必须定义wrappedValue ,它是暴露的属性的获取器和设置器。 下面的示例从传入的字符串值中修剪空格和换行符:

@propertyWrapper
struct WhitespaceTrimmable {
    private(set) var value: String = ""


    var wrappedValue: String {
        get { value }
        set { value = newValue.trimmingCharacters(in: .whitespacesAndNewlines) }
    }


    init(wrappedValue: String) {
        self.wrappedValue = wrappedValue
    }
}

To use it:

要使用它:

struct Service {
    @WhitespaceTrimmable var title: String
}


let service = Service(title: "Title    ")
print(service.title) // Title

The property wrapper can accept arguments as default values too:

属性包装器也可以接受参数作为默认值:

struct Service {
    @WhitespaceTrimmable(wrappedValue: "Default title") var title: String
}


var service = Service()
print(service.title) // Default title

To access the wrapped property directly, we use _ as a prefix name:

要直接访问包装的属性,我们使用_作为前缀名称:

struct Service {
    @WhitespaceTrimmable(wrappedValue: "Default title") var title: String


    func accessTitle() {
        print("title: \(_title)") //Default title
    }
}

@可用(@available)

It indicates that the declaration is only available in specific Swift language versions or OS system versions.

它表明该声明仅在特定的Swift语言版本或OS系统版本中可用。

For instance, to use the compositional UICollectionView that is only available in iOS 13+:

例如,要使用仅在iOS 13+中可用的合成UICollectionView ,请执行以下操作:

public struct CollectionViewCellProvider {
    @available(iOS 13, *)
    public static func compositionalCell() {
        // compositional collection view cell
    }


    public static func collectionCell() {
        // collection view cell
    }
}

@discardableResult(@discardableResult)

It indicates that the result of the function can be ignored without the compiler warning.

它指示函数的结果可以忽略而无需编译器警告。

Before we apply the @discardableResult to the function, the compiler complains Result of call to '' is unused when the function is called without using its result:

在将@discardableResult应用于函数之前,编译器会抱怨在不使用函数Result of call to '' is unused的结果未使用:

class ParentViewController: UIViewController {
    override func viewDidLoad() {
        presentViewController() // Result of call to 'presentViewController' is unused
    }


    func presentViewController() -> UIViewController {
        return UIViewController()
    }
}

To silence the warning, we use @discardableResult:

为了使警告@discardableResult ,我们使用@discardableResult

class ParentViewController: UIViewController {
    override func viewDidLoad() {
        presentViewController() // No Xcode complains!
    }


    @discardableResult
    func presentViewController() -> UIViewController {
        return UIViewController()
    }
}

@dynamicCallable(@dynamicCallable)

@dynamicCallable takes @dynamicMemberLookup a step further. It’s syntactic sugar rather than any sort of compiler magic. It applies to a class, structure, enumeration, or protocol to treat instances of the type as callable functions.

@dynamicCallable使@dynamicMemberLookup更进一步。 它是语法糖,而不是任何形式的编译器魔术。 它适用于类,结构,枚举或协议,将类型的实例视为可调用函数。

To use it, we need to add @dynamicCallable attributes and implement one or both of the following methods:

要使用它,我们需要添加@dynamicCallable属性并实现以下一种或两种方法:

func dynamicallyCall(withArguments args: ExpressibleByArrayLiteral) -> Double


func dynamicallyCall(withKeywordArguments args: ExpressibleByDictionaryLiteral) -> Double
@dynamicCallable
struct RandomProvider {
    func dynamicallyCall(withArguments args: [Int]) -> Double {
        let numberOfZeroes = Double(args[0])
        let maximum = pow(10, numberOfZeroes)
        return Double.random(in: 0...maximum)
    }


    func dynamicallyCall(withKeywordArguments args: KeyValuePairs<String, Int>) -> Double {
        let numberOfZeroes = Double(args.first?.value ?? 0)
        let maximum = pow(10, numberOfZeroes)
        return Double.random(in: 0...maximum)
    }
}


let random = RandomProvider()
print(random(1)) // 8.15946134247
print(random(a:1)) // 5.14551692644

@dynamicMemberLookup(@dynamicMemberLookup)

It was introduced at the Swift Evolution proposal SE-0195. It instructs Swift to call a subscript method when accessing properties. We need to add the subscript method when using it:

它是在Swift Evolution提案SE-0195中引入的。 它指示Swift在访问属性时调用subscript方法。 使用它时,我们需要添加subscript方法:

subscript(dynamicMember:)

For the following instance, we implement the User struct with members firstname and lastname. The properties do not exist as properties but are all looked up at runtime. The dynamicMember looks up the property member firstname and lastname in a dictionary and returns its value.

对于以下实例,我们使用成员firstnamelastname实现User结构。 这些属性不作为属性存在,而是在运行时进行查找。 dynamicMember在字典中查找属性成员的firstnamelastname ,并返回其值。

@dynamicMemberLookup
struct User {
    subscript(dynamicMember member: String) -> String {
        let properties = ["firstname": "Bob", "lastname": "Dylan"]
        return properties[member, default: ""]
    }
}
let user = User()
print(user.firstname) // Bob
print(user.lastname) // Dylan

@主要(@main)

It becomes more practical with the @Argument attribute in Swift 5.3, especially when creating a Swift CLI tool. It applies to a class, struct, or enum declaration to indicate it contains the top-level entry point. The main() function must be provided.

使用Swift 5.3中的@Argument属性,它变得更加实用,尤其是在创建Swift CLI工具时。 它适用于类,结构或枚举声明,以指示它包含顶级入口点。 必须提供main()函数。

@main 
struct Repeat: ParsableCommand {
    @Argument(help: "The phrase to repeat.")
    var phrase: String


    mutating func run() throws {
        for _ in 1...5 {
            print(phrase)
        }
    }
}

@UIApplicationMain(@UIApplicationMain)

It’s probably the best-known attribute, as it sits in the AppDelegate.swift file to indicate the main entry point of the iOS app.

它可能是最著名的属性,因为它位于AppDelegate.swift文件中,用于指示iOS应用程序的主要入口点。

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
}

@NSApplicationMain(@NSApplicationMain)

When we create an OS X project, Xcode generates a main.swift file. This attribute applies to the app delegate class in order to generate an implicit main for the app. It plays the same role as @UIApplicationMain for iOS apps.

当我们创建OS X项目时,Xcode会生成一个main.swift文件。 此属性适用于应用程序委托类,以便为应用程序生成隐式的主体。 对于iOS应用,它的作用与@UIApplicationMain相同。

import Cocoa


NSApplicationMain(Process.argc, Process.unsafeArgv)

结论(Conclusion)

Swift keeps adding @ attributes in different versions. Understanding and using them correctly and efficiently can bring us clean code and better app performance.

Swift不断在不同版本中添加@属性。 正确有效地理解和使用它们可以为我们带来干净的代码和更好的应用程序性能。

Thank you for reading. Leave any questions you might have in the comments.

感谢您的阅读。 留下您可能在评论中有任何疑问。

All code mentioned above can be found in this GitHub repo.

上面提到的所有代码都可以在此GitHub存储库中找到。

翻译自: https://medium.com/better-programming/10-powerful-attributes-in-swift-d4e4153a0001

11个资源强大的网站

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值