<!--
{
  "availability" : [
    "iOS: 17.0.0 -",
    "iPadOS: 17.0.0 -",
    "macCatalyst: 17.0.0 -",
    "tvOS: 17.0.0 -",
    "visionOS: 1.0.0 -",
    "watchOS: -"
  ],
  "documentType" : "symbol",
  "framework" : "UIKit",
  "identifier" : "/documentation/UIKit/UITraitDefinition-3572h",
  "metadataVersion" : "0.1.0",
  "role" : "Protocol",
  "symbol" : {
    "kind" : "Protocol",
    "modules" : [
      "UIKit"
    ],
    "preciseIdentifier" : "c:objc(pl)UITraitDefinition"
  },
  "title" : "UITraitDefinition"
}
-->

# UITraitDefinition

A type representing a trait in a trait collection.

```
@protocol UITraitDefinition
```

## Overview

All traits contained in a [`UITraitCollection`](/documentation/UIKit/UITraitCollection) conform to this protocol. Three protocols refine `UITraitDefinition`: [`UINSIntegerTraitDefinition`](/documentation/UIKit/UINSIntegerTraitDefinition), [`UICGFloatTraitDefinition`](/documentation/UIKit/UICGFloatTraitDefinition), or [`UIObjectTraitDefinition`](/documentation/UIKit/UIObjectTraitDefinition). You can create custom traits by defining your own object conforming one of these three protocols, as appropriate for your trait value.

The example below defines a new trait that holds an <doc://com.apple.documentation/documentation/ObjectiveC/NSInteger> value:

```objc
typedef NS_ENUM(NSInteger, Theme) {
    ThemeStandard,
    ThemeMonochrome
};

@interface MyThemeTrait : NSObject<UINSIntegerTraitDefinition>
@end

@implementation MyThemeTrait
+ (NSInteger)defaultValue { return ThemeStandard; }
@end
```

Defining [`defaultValue`](/documentation/UIKit/UITraitDefinition-64c15/defaultValue) is the minimum requirement to conform to this protocol. The [`defaultValue`](/documentation/UIKit/UITraitDefinition-64c15/defaultValue) must be constant.

The best candidates for trait values are simple scalars: <doc://com.apple.documentation/documentation/ObjectiveC/NSInteger> and <doc://com.apple.documentation/documentation/CoreFoundation/CGFloat-swift.struct>. You can also use lightweight objects as trait values, but these are less efficient than simple scalars. Examples of lightweight objects include <doc://com.apple.documentation/documentation/Foundation/NSString>, <doc://com.apple.documentation/documentation/Foundation/NSDate>, or a composite of similarly lightweight objects. Make sure the default value never changes, preferably by making the object immutable. The system frequently checks trait values for equality, so classes need an efficient implementation of <doc://com.apple.documentation/documentation/ObjectiveC/NSObjectProtocol/isEqual(_:)>.

If you use your custom trait to implement custom dynamic colors, implement [`affectsColorAppearance`](/documentation/UIKit/UITraitDefinition-64c15/affectsColorAppearance) and return `YES`. Returning `YES` tells the system to update and redraw views automatically when the trait changes. The system responds to changes to your trait similar to changes in system traits contained in [`systemTraitsAffectingColorAppearance`](/documentation/UIKit/UITraitCollection/systemTraitsAffectingColorAppearance-64z7q). Changes to traits that affect color appearance are more expensive, so opt in to this behavior only when necessary, and change such traits infrequently.

A trait type serves as a unique key, identifying a trait within a trait collection. Methods such as [`valueForNSIntegerTrait:`](/documentation/UIKit/UITraitCollection/valueForNSIntegerTrait:) and [`registerForTraitChanges:withHandler:`](/documentation/UIKit/UITraitChangeObservable-7qoet/registerForTraitChanges:withHandler:) take a trait type to identify the trait in a collection.

### Traits in both Swift and Objective-C

If you need to access traits from both Swift and Objective-C code, create a type conforming to [`UITraitDefinition`](/documentation/UIKit/UITraitDefinition-64c15) in both languages. To define a trait that’s accessible from both Swift and Objective-C, follow these guidelines :

- In Swift, define a structure that conforms to [`UITraitDefinition`](/documentation/UIKit/UITraitDefinition-64c15).
- In Objective-C, define an <doc://com.apple.documentation/documentation/ObjectiveC/NSObject-swift.class> subclass that conforms to [`UINSIntegerTraitDefinition`](/documentation/UIKit/UINSIntegerTraitDefinition), [`UICGFloatTraitDefinition`](/documentation/UIKit/UICGFloatTraitDefinition), or [`UIObjectTraitDefinition`](/documentation/UIKit/UIObjectTraitDefinition).
- Implement [`defaultValue`](/documentation/UIKit/UITraitDefinition-64c15/defaultValue), [`name`](/documentation/UIKit/UITraitDefinition-64c15/name), and [`identifier`](/documentation/UIKit/UITraitDefinition-64c15/identifier), and make the values the same in Objective-C and Swift.
- If your trait holds an object value, make the class visible to both Swift and Objective-C.
- If your trait holds a fundamental value type, make your Objective-C types correspond to Swift types, as in the following table:

|Swift                                                                            |Objective-C                                                                      |
|---------------------------------------------------------------------------------|---------------------------------------------------------------------------------|
|<doc://com.apple.documentation/documentation/Swift/Bool>                         |<doc://com.apple.documentation/documentation/ObjectiveC/NSInteger>               |
|<doc://com.apple.documentation/documentation/Swift/Int>                          |<doc://com.apple.documentation/documentation/ObjectiveC/NSInteger>               |
|<doc://com.apple.documentation/documentation/Swift/Double>                       |<doc://com.apple.documentation/documentation/CoreFoundation/CGFloat-swift.struct>|
|<doc://com.apple.documentation/documentation/CoreFoundation/CGFloat-swift.struct>|<doc://com.apple.documentation/documentation/CoreFoundation/CGFloat-swift.struct>|

For Swift <doc://com.apple.documentation/documentation/Swift/Bool> values, Objective-C uses 0 for `false` and 1 for `true`.

If your Swift trait uses an optional type for the [`defaultValue`](/documentation/UIKit/UITraitDefinition-64c15/defaultValue), Objective-C represents a Swift `nil` value with a special Objective-C constant. The table below lists the Objective-C values that correspond to a Swift `nil` value.

|Swift optional type|Swift value|Objective-C type                                                                 |Objective-C value                                                        |
|-------------------|-----------|---------------------------------------------------------------------------------|-------------------------------------------------------------------------|
|`Int?`             |`nil`      |<doc://com.apple.documentation/documentation/ObjectiveC/NSInteger>               |<doc://com.apple.documentation/documentation/Foundation/NSNotFound-4qp9h>|
|`Double?`          |`nil`      |<doc://com.apple.documentation/documentation/CoreFoundation/CGFloat-swift.struct>|<doc://com.apple.documentation/documentation/CoreFoundation/CGFLOAT_MAX> |
|`CGFloat?`         |`nil`      |<doc://com.apple.documentation/documentation/CoreFoundation/CGFloat-swift.struct>|<doc://com.apple.documentation/documentation/CoreFoundation/CGFLOAT_MAX> |

In Objective-C, your trait value may require an <doc://com.apple.documentation/documentation/ObjectiveC/NSObject-swift.class> subclass if your data model exceeds the simple scalars of <doc://com.apple.documentation/documentation/ObjectiveC/NSInteger> and <doc://com.apple.documentation/documentation/CoreFoundation/CGFloat-swift.struct>. To use this value in Swift, import your Objective-C class into Swift, and use it for the value of your custom trait in both languages. Other than bridging with Objective-C, avoid using reference types for Swift trait values.

You can prevent Swift from importing your Objective-C class name by applying the `NS_REFINED_FOR_SWIFT` macro to your Objective-C interface. This macro allows you to name your Swift trait structure with the same name as your Objective-C trait class.

The example below defines a trait in Objective-C, with a custom `Theme` type for a trait value.

```objc
typedef NS_ENUM(NSInteger, Theme) {
    ThemeStandard,
    ThemeMonochrome
};

NS_REFINED_FOR_SWIFT @interface ThemeTrait : NSObject<UINSIntegerTraitDefinition>
@end

@implementation ThemeTrait
+ (NSInteger)defaultValue { return ThemeStandard; }
+ (NSString *)name { return @"Theme"; }
+ (NSString *)identifier { return @"com.example.themetrait"; }
@end
```

The following code example shows the definition of a Swift trait so that UIKit recognizes it as the same trait as defined above in Objective-C:

```swift
// The NS_REFINED_FOR_SWIFT macro allows this struct to have 
// the same name as the Objective-C trait class.
struct ThemeTrait: UITraitDefinition {
    static let defaultValue = Theme.standard
    static let name = "Theme"
    static let identifier = "com.example.themetrait"
}
```

The `NS_REFINED_FOR_SWIFT` macro makes your Objective-C class available in Swift by prepending double underscores to the class name. You can use this to make your Swift implementation call your Objective-C class properties. For more details, refer to <doc://com.apple.documentation/documentation/Swift/improving-objective-c-api-declarations-for-swift>.

## Topics

### Type Properties

[`@property (class, nonatomic, readonly) BOOL affectsColorAppearance;`](/documentation/UIKit/UITraitDefinition-3572h/affectsColorAppearance)

Whether the trait is used to resolve dynamic colors (or images), and changes to the trait should
automatically trigger views using dynamic colors/images to update their appearance. Default is NO.

[`@property (class, nonatomic, readonly) NSString * identifier;`](/documentation/UIKit/UITraitDefinition-3572h/identifier)

A unique identifier string for the trait (reverse-DNS format recommended).
Allows the trait to be encoded/decoded, and to map both a Swift and Objective-C trait to the same data.

[`@property (class, nonatomic, readonly) NSString * name;`](/documentation/UIKit/UITraitDefinition-3572h/name)

A short human-readable name for the trait, e.g. for printing and debugging output.
By default, the trait’s class name is used when not implemented.

## Relationships

### Inherited By

[`UINSIntegerTraitDefinition`](/documentation/UIKit/UINSIntegerTraitDefinition)

[`UICGFloatTraitDefinition`](/documentation/UIKit/UICGFloatTraitDefinition)

[`UIObjectTraitDefinition`](/documentation/UIKit/UIObjectTraitDefinition)

---

Copyright &copy; 2026 Apple Inc. All rights reserved. | [Terms of Use](https://www.apple.com/legal/internet-services/terms/site.html) | [Privacy Policy](https://www.apple.com/privacy/privacy-policy)