What is an attribute in Swift?


Throughout this article, you will learn what an attribute in Swift is and how to use it with code examples.

Swift Attributes

Swift makes it possible to provide some additional info about the declaration or type. We have two types of attributes that can be used in Swift language.

  • Declaration Attributes

  • Type Attributes

Syntax

You can apply an attribute by using the symbol @ followed by the attribute name, as shown below −

@attribute name
@attribute name(attribute arguments)

Explanation

We can provide arguments in declaration attributes to define the declaration. These arguments can be provided in parentheses and the format.

Declaration Attributes

You can apply a declaration attribute to declarations only.

Below are some declaration attributes −

@available

Available is a declaration attribute that can be used to specify the Swift language version, platform, or iOS version to which the declaration belongs. In other words, it helps you make your code available or unavailable as per platform or version.

Throughout Swift's history, there have been many additions to APIs introduced which is available in releases and future versions. There is a possibility that some of the code will not run on all platforms (macOS, watchOS, etc.).

This attribute can be specified with two or more arguments separated by a comma. The argument list begins with one of the following platform names or languages −

  • iOS, iOSApplicationExtension

  • macOS, macOSApplicationExtension

  • watchOS, watchOSApplicationExtension

  • tvOS, tvOSApplicationExtension

  • Swift

Example

if #available(iOS 15, *) {
   print("This code will run on iOS 15 and upper versions.")
} else {
   print("This code will only runs on iOS 14 and lower versions.")
}

Output

This code will run on iOS 15 and upper versions.

You can use the available attribute inside a guard statement as well −

guard #available(iOS 15, *) else {
   print("This code will only runs on iOS 14 and lower versions.")
   return
}
print("This code will run on iOS 15 and upper versions.")

This is helpful for cases in which you’d like to execute specific code only for a specific iOS version.

@UIApplicationMain

It is applied to a class to indicate the application delegate declaration. While we use this attribute, we inform the compiler about the delegate class.

@PropertyWrapper

This attribute might be useful to override the value of a property. You can specify custom specifications using this attribute in classes or structs.

Example

Remember that you cannot apply this attribute to local and global properties. Let's see an example of how to use this attribute in the Swift language like below −

import Foundation
@propertyWrapper struct UserName {
   var wrappedValue: String {
      didSet { wrappedValue = wrappedValue.lowercased() }
   }
   init(wrappedValue: String) {
      self.wrappedValue = wrappedValue.lowercased()
   }
}
struct InstagramUser {
   @UserName var firstName: String
   @UserName var lastName: String
    
   var fullUserName: String {
      "\(firstName).\(lastName)"
   }
}
let user = InstagramUser(firstName: "Alex", lastName: "Muphy")
print(user.fullUserName)

Output

alex.muphy

Explanation

In the above example, we created a property wrapper for UserName using the @propertyWrapper attribute. In here, we are wrapping the given value in lowercased as username should be in lowercased.

In the InstagramUser struct, we declare some properties like first and last name along with the UserName property wrapper. Further, we don’t need to worry about a valid case value as this is done by the property wrapper.

@Objc

This attribute is used to represent Objective-C properties and methods in Swift code. We can apply this attribute to classes to tell the compiler that a declaration is available to use in Objective-C code.

import Foundation
class UserValidator {
   @objc func authenticateUser() {
	   // statements to validate user details
   }
}

@discardableResult

Example

When the result of a method or function that returns a value is unused, the Swift compiler often throws a warning.

func appendLastName(_ lastName: String) -> String {
   var fullName = "Penny"
   fullName += " \(lastName)"
   print("Full name is: \(fullName)")
   return fullName
}
appendLastName("Black")

Output

Full name is: Penny Black

You will get a warning here −

Result of call to 'appendLastName' is unused

Example

Below is the way to use @discardableResult in order to suppress the warning generated by the unused value returned by the method returning the value

@discardableResult
func appendLastName(_ lastName: String) -> String {
   var fullName = "Penny"
   fullName += " \(lastName)"
   print("Full name is: \(fullName)")
   return fullName
}
appendLastName("Black")

Output: (no warning this time)

Full name is: Penny Black

Declaration Attributes Used by Interface Builder

Swift provides us with some attributes to help us declare user interface components using IBAction, IBDesignable, IBInspectable, and IBOutlet.

Method declarations can make use of interface builder attributes such as IBAction and IBSegueAction. The IBOutlet and IBInspectable attributes can be applied to the properties of a class.

Example

import UIKit
class LoginController: UIViewController {
   @IBOutlet var sendButton: UIButton!
   @IBAction func handleSendButtonTapped(_ sender: UIButton) {
      // perform send action here
   }
}

Type Attributes

You can apply type attributes to types only.

autoclosure

Example

As the name implies, this attribute automatically creates a closure from the function arguments. Basically, we apply this attribute to a function or method declaration. The autoclosure attribute does not take any parameters and usually returns a value.

func greetingMessage(_ name: @autoclosure () -> String) {
   print("Good morning, \(name())")
}
greetingMessage("Rahul")

Output

Good morning, Rahul

Explanation

In this example, the greetingMessage(_:) function takes a closure that returns a String value. The @autoclosure attribute indicates that a closure should be automatically created to wrap the name argument.

escaping

Example

We can apply the escaping attribute in a function or method declaration. It is used to tell the compiler to store the parameter to use to it later. It means, we can store the argument passed in a function.

import UIKit
class NetworkManager {
   private func sendRequest(url: URL, completion: @escaping (Data?) -> ()) {
      let task = URLSession.shared.dataTask(with: url) { data, response, error in
         completion(data)
      }
      task.resume()
   }
   func fetchSampleData(_ completion: @escaping (Data?) -> ()) {
      guard let url = URL(string: "https://jsonplaceholder.typicode.com/todos/1") else {
         completion(nil)
         return
      }
      sendRequest(url: url, completion: completion)
   }
}
let networkManager = NetworkManager()
networkManager.fetchSampleData { data in
   print("fetched data: \(data)")
}

Output

fetched data: Optional(83 bytes)

Explanation

In this example, fetchSampleData() takes a closure as an argument and uses it to return the fetched data to the caller. The closure is marked with the @escaping keyword because it is called after the fetchSampleData() function has returned. The example function uses sendRequest() to fetch some data from the URL and then processes the data in the closure it passes to fetchSampleData().

Conclusion

In the code, you can apply different attributes to classes, structures, properties, etc. Using attributes, your code will look more concise and safe. As a result, you can write code according to the iOS version or platform.

Having these attributes makes your coding easy and clean. These often save a lot of development time.

Updated on: 21-Dec-2022

773 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements