π¬π File and Components Naming
The focus of this document is to provide clear and actionable rules for naming within Swift and SwiftUI projects, while excluding folder organization and architecture-specific patterns such as MVVM or VIPER. For these aspects, refer to complementary documentation on project organization and architecture guidelines.
General Naming Guidelinesβ
Consistency and Clarityβ
Consistency and clarity are the cornerstones of effective naming conventions. Names should clearly convey the purpose and functionality of the element they represent. Consistent naming patterns across the codebase make it easier to understand and maintain, especially as the project scales.
- Use Descriptive Names: Choose names that accurately describe the role of the variable, function, or type. Avoid single-letter names or overly short names except for loop indices or very common abbreviations (e.g.,
i
,x
,y
). - Avoid Ambiguity: Names should be specific enough to avoid confusion. For example, use
userProfile
instead ofprofile
if the context involves multiple types of profiles.
Use of Descriptive Namesβ
Descriptive names help developers quickly understand what a piece of code does. This is particularly important in collaborative environments where multiple developers work on the same codebase.
- Methods and Functions: Use action-oriented names for functions and methods, starting with a verb that describes what the function does (e.g.,
fetchUserData()
,updateProfile()
). - Classes and Structs: Use nouns that represent the entity or concept the type models (e.g.,
UserManager
,Order
). - Variables: Choose variable names that represent the data they hold. For example, use
userName
instead of justname
to specify that itβs a userβs name.
Capitalization Rulesβ
Adhere to Swiftβs capitalization rules to maintain a consistent style across your codebase.
- PascalCase for Types and File Names: Use
PascalCase
(e.g.,UserProfileView
,LoginManager
) for classes, structs, enums, protocols, and file names. Each word in the name should start with a capital letter. - camelCase for Variables and Functions: Use
camelCase
(e.g.,userName
,fetchUserData()
) for variable names, properties, methods, and functions. The first word should be in lowercase, and each subsequent word should start with a capital letter. - SCREAMING_SNAKE_CASE for Global Constants: Use
SCREAMING_SNAKE_CASE
(e.g.,MAX_LOGIN_ATTEMPTS
) for global constants and static values within enums.
Avoid Redundancyβ
Avoid including redundant or unnecessary information in names, as it can make code harder to read and maintain.
- Avoid Repeating Information: Donβt repeat the type in the name. For example,
userArray
is redundant if the type is[User]
. Instead, useusers
. - Avoid Generic Names: Generic names like
manager
,data
, orinfo
provide little context. Be specific, likeauthManager
oruserData
. - Avoid Long Names: Keep names concise yet descriptive. While itβs important to be specific, excessively long names can be cumbersome. Use 2-3 words that convey the componentβs role.
Abbreviations and Acronymsβ
Use abbreviations and acronyms sparingly and only when they are widely understood.
- Common Abbreviations: Use common abbreviations like
URL
,ID
, orJSON
where appropriate. Avoid using non-standard abbreviations, as they can confuse other developers. - Avoid Shortened Words: Avoid creating your own abbreviations for commonly understood words (e.g., use
button
, notbtn
).
Prefixes and Suffixesβ
Use prefixes and suffixes to add context to names, but only when necessary.
- Boolean Variables: Use prefixes like
is
,has
, orcan
for Boolean properties to indicate their purpose (e.g.,isLoggedIn
,hasAccess
,canSubmit
). - Delegates and Data Sources: Add
Delegate
orDataSource
suffixes to indicate the role of the object (e.g.,tableViewDelegate
,collectionViewDataSource
). - Protocols: Avoid using
I
prefixes (common in other languages like C#). Instead, use descriptive names that reflect the protocolβs role (e.g.,Configurable
,Validatable
).
Use of Contextual Namesβ
Names should provide enough context to understand their use without being verbose.
- Single Responsibility Names: Each name should reflect a single purpose or responsibility. For example,
userManager
is responsible for user-related actions, whileauthService
handles authentication. - Include Context in Nested Scopes: When variables are used within closures or nested scopes, include context in the name to avoid ambiguity (e.g.,
currentUser
instead ofuser
in a nested loop or closure).
Temporary Variablesβ
Temporary variables should be used sparingly and named appropriately.
- Loop Variables: Use single-letter names like
i
,j
,k
for loop indices, but provide descriptive names in more complex loops (e.g.,userIndex
). - Short-Lived Variables: For short-lived variables in small scopes, use concise names that indicate their role (e.g.,
tempData
for temporary data storage).
Filesβ
Proper file naming is crucial for organizing code and ensuring that developers can easily locate and understand the purpose of each file. Following consistent file naming conventions helps maintain a clean and navigable project structure.
- Use
PascalCase
for File Names: All Swift file names should usePascalCase
, where each word begins with an uppercase letter (e.g.,UserProfileView.swift
,LoginManager.swift
). - Match File Name with Primary Type: The file name should match the name of the primary type it contains. If a file contains a class named
UserProfileView
, the file should be namedUserProfileView.swift
. - Avoid Special Characters and Spaces: Do not use special characters (e.g.,
@
,#
,&
) or spaces in file names. Use only alphanumeric characters and avoid underscores (_
) and hyphens (-
) to ensure compatibility and consistency. - Be Descriptive but Concise: File names should be descriptive enough to convey the purpose of the file but not overly long. Aim for clarity while keeping names manageable.
Specific Typesβ
Different types of Swift constructs, such as classes, structs, protocols, and extensions, have specific naming patterns to follow.
Classes and Structsβ
- File Names Should Match the Type Name: The file name should exactly match the name of the class or struct it contains. For example:
User.swift
for aUser
struct or class.AuthManager.swift
for anAuthManager
class.
- Avoid Redundant Suffixes: Do not add unnecessary suffixes like
Class
orStruct
in the file name (e.g., useUser.swift
instead ofUserClass.swift
).
Protocolsβ
- File Names Should Match the Protocol Name: The file name should match the protocol name exactly. For example:
Configurable.swift
for aConfigurable
protocol.DataSourceProvider.swift
for aDataSourceProvider
protocol.
- Extensions to Protocols: Use a suffix to indicate the functionality of the extension, such as
ProtocolName+Functionality.swift
(e.g.,Configurable+Defaults.swift
for default implementations of theConfigurable
protocol).
Enumsβ
- File Names Should Match the Enum Name: The file name should be the same as the enum name. For example:
UserRole.swift
for aUserRole
enum defining different user roles.OrderStatus.swift
for anOrderStatus
enum representing various order states.
Extensionsβ
- Use the Format
TypeName+Functionality.swift
: When creating extensions, name the file using the type name and a short description of the functionality provided by the extension. For example:String+Validation.swift
for validation-related extensions to theString
type.UIView+Animations.swift
for custom animation methods added toUIView
.
- Avoid Overloading Extension Files: Keep related extensions grouped together, but avoid overloading a single file with too many unrelated extensions. Split extensions into multiple files if necessary, using descriptive names.
Multi-Type Filesβ
- Use Descriptive Names for Multi-Type Files: If a file contains multiple related types (e.g., models or utility functions), choose a name that reflects its contents. For example:
UserProfileModels.swift
for a file containing multiple models related to user profiles.NetworkHelpers.swift
for a file containing utility functions related to networking.
Utility Filesβ
Utility files often contain helper functions, constants, or other shared resources. Use clear and specific names to indicate their purpose.
Helpers and Utilitiesβ
- Use Descriptive Names Reflecting the Utilityβs Purpose: File names should describe the function or role of the utilities within. For example:
NetworkHelper.swift
for networking-related utility functions.DateFormatterUtility.swift
for utilities related to date formatting.
Constants and Configurationsβ
- Use Specific Names for Constants Files: Use names that indicate the scope of the constants, such as
AppConstants.swift
for application-wide constants orAPIConstants.swift
for constants related to API configurations. - Avoid Overloading Constants Files: Avoid creating a single, large constants file for all constants. Instead, split constants into logical groups based on their use.
Extensions and Categoriesβ
- Use
TypeName+Functionality.swift
for Extensions: As mentioned above, categorize extension files based on the type and the specific functionality being added. This approach makes it easier to find and manage extensions. - Keep Extensions Focused: Each extension file should focus on a specific area of functionality (e.g.,
UIView+Layout.swift
for layout-related methods).
iOS-Specific Componentsβ
iOS projects often include specific types of files that require unique naming conventions.
View Controllersβ
- Use the
ViewController
Suffix: All view controllers should have a name that reflects their purpose followed byViewController
. For example:LoginViewController.swift
for a login screen.UserProfileViewController.swift
for a user profile screen.
- Navigation and Tab Controllers: For custom navigation or tab bar controllers, use names like
CustomNavigationController.swift
orMainTabBarController.swift
.
Storyboard and XIB Filesβ
- Match the File Name to the Corresponding View Controller or Component: Storyboard and XIB file names should match the name of the corresponding view controller or UI component (e.g.,
LoginViewController.storyboard
,UserProfileCell.xib
). - Use Descriptive Names for Reusable Components: For reusable UI components, use names that reflect their role (e.g.,
CustomButton.xib
,UserProfileHeaderView.xib
).
Typesβ
Classes and Structsβ
Classes and structs are fundamental building blocks in Swift. Proper naming helps distinguish their purpose and makes the code more intuitive.
- Use
PascalCase
: UsePascalCase
for all class and struct names, capitalizing the first letter of each word (e.g.,UserProfile
,LoginManager
). - Use Nouns: Name classes and structs using nouns that describe the object or entity they represent (e.g.,
Order
,ProductCatalog
). Avoid using verbs or adjectives. - Avoid Redundant Suffixes: Do not include unnecessary suffixes like
Class
orStruct
in the name. For example, useUser
instead ofUserClass
orUserStruct
. - Indicate Responsibility Clearly: Choose names that clearly convey the class or structβs role in the codebase (e.g.,
AuthenticationService
for handling authentication,UserSettings
for user-specific preferences).
Name | Purpose | Example |
---|---|---|
UserProfile | Represents an individual user's profile. | class UserProfile {} |
OrderManager | Manages operations related to orders. | struct OrderManager {} |
AuthService | Handles authentication logic. | class AuthService {} |
ProductCatalog | Represents a collection of products. | struct ProductCatalog {} |
Protocolsβ
Protocols define a blueprint of methods and properties for conforming types. They should be named to reflect their purpose clearly.
- Use
PascalCase
: UsePascalCase
for all protocol names, with the first letter of each word capitalized (e.g.,Configurable
,DataSourceProvider
). - Use Descriptive Adjectives or Nouns: Use adjectives (e.g.,
Configurable
,Validatable
) or nouns (e.g.,DataSource
,Delegate
) that describe the protocolβs purpose. - Avoid Using the "I" Prefix: Unlike languages like C# where interfaces use the
I
prefix, Swift protocols should not use this convention (e.g.,UserProtocol
is incorrect; useUserDelegate
instead).
Name | Purpose | Example |
---|---|---|
Configurable | Represents something that can be configured. | protocol Configurable {} |
DataSourceProvider | Provides data to a UI component. | protocol DataSourceProvider {} |
Validatable | Represents an object that can be validated. | protocol Validatable {} |
Networking | Defines networking operations for an object. | protocol Networking {} |
Enumsβ
Enums are used to define a common type for a group of related values. Naming should be intuitive and reflect the purpose of the values.
- Use
PascalCase
: UsePascalCase
for the enum name and for its cases (e.g.,OrderStatus
,UserRole
). - Use Singular Nouns: The enum name should typically be a singular noun that represents the group of values (e.g.,
PaymentMethod
). - Use Verb Phrases for Actions: If the enum represents actions or state transitions, use verb phrases (e.g.,
LoadingState
with cases likeloading
,success
,failure
). - Avoid Adding "Enum" Suffix: Do not add "Enum" to the name; it is redundant (e.g.,
UserRoleEnum
is incorrect; useUserRole
).
Name | Purpose | Example |
---|---|---|
OrderStatus | Represents the status of an order. | enum OrderStatus { case pending, shipped, delivered } |
UserRole | Defines the roles a user can have within the application. | enum UserRole { case admin, user, guest } |
PaymentMethod | Lists different payment methods available. | enum PaymentMethod { case creditCard, paypal, applePay } |
LoadingState | Represents the state of a loading process. | enum LoadingState { case loading, success, failure } |
Extensionsβ
Extensions allow you to add functionality to existing types. Proper naming helps organize the additional functionality and clarifies its purpose.
- Use the Format
TypeName+Functionality
: Use the formatTypeName+Functionality
to name extension files (e.g.,String+Validation.swift
). - Group Related Functions: Group related methods in a single extension to improve code organization (e.g.,
UIView+Layout
for layout-related methods). - Avoid Adding Unrelated Functions: Do not add unrelated methods in the same extension, as it reduces clarity and organization.
Name | Purpose | Example |
---|---|---|
String+Validation | Adds validation-related methods to the String type. | extension String { func isValidEmail() -> Bool {} } |
UIView+Animations | Adds custom animations to UIView . | extension UIView { func shake() {} } |
Date+Formatting | Adds date formatting functions to Date . | extension Date { func formatted() -> String {} } |
Array+SafeAccess | Adds safe access methods to arrays. | extension Array { func safeElement(at index: Int) -> Element? {} } |
Type Aliases and Associated Typesβ
Type aliases and associated types provide a way to create more readable code by giving a type a new name. They are often used in protocols and generics.
- Use Descriptive Names: Choose names that clearly describe the role of the type alias or associated type (e.g.,
JSONDictionary
for[String: Any]
). - Avoid Generic Names: Avoid using generic names like
T
orElement
unless in generic contexts where their role is obvious. - Use
camelCase
for Aliases within Methods: For method-local aliases, usecamelCase
to distinguish them from top-level type aliases.
Name | Purpose | Example |
---|---|---|
JSONDictionary | Represents a dictionary used for JSON parsing. | typealias JSONDictionary = [String: Any] |
Element | Represents an element in a generic context, such as a collection. | associatedtype Element |
CompletionHandler | A closure that is called when an operation completes. | typealias CompletionHandler = (Result<Data, Error>) -> Void |
Functions and Methodsβ
Functions and Methodsβ
Functions and methods should have clear, descriptive names that reflect their purpose and behavior. They are the actions in your code, so naming them appropriately is crucial for readability and maintainability.
- Use Verb Phrases: Start function names with a verb to indicate the action being performed (e.g.,
fetchUserData()
,updateProfile()
). - Be Descriptive Yet Concise: Use names that are specific enough to convey the functionβs purpose but not overly long. Avoid vague names like
doSomething()
orhandle()
. - Include Context When Necessary: If a function is performing an action related to a specific entity or context, include that in the name (e.g.,
saveUserSettings()
instead of justsave()
). - Avoid Redundant Words: Do not include redundant terms like
function
ormethod
in the name (e.g., usegetData()
instead ofgetDataMethod()
).
Name | Purpose | Example |
---|---|---|
fetchUserData() | Retrieves user data from a remote server. | func fetchUserData() {} |
updateProfile(with:) | Updates the user profile with the provided data. | func updateProfile(with data: UserProfile) {} |
saveSettings() | Saves user settings locally or remotely. | func saveSettings() {} |
deleteAccount() | Deletes the userβs account from the system. | func deleteAccount() {} |
Boolean Methods and Propertiesβ
Boolean methods and properties should be named to clearly indicate a true/false condition. This convention helps in understanding the state or behavior of an object.
- Use Prefixes Like
is
,has
, orcan
: These prefixes clarify that the method or property returns a Boolean value.is
: Indicates a state (e.g.,isLoggedIn
).has
: Indicates possession or availability (e.g.,hasAccess
).can
: Indicates a capability (e.g.,canSubmit
).
- Avoid Negatively Named Booleans: Instead of naming a property
isNotLoggedIn
, use!isLoggedIn
in the code for clarity.
Name | Purpose | Example |
---|---|---|
isLoggedIn | Indicates whether the user is currently logged in. | var isLoggedIn: Bool = false |
hasPremiumAccess | Indicates if the user has access to premium features. | var hasPremiumAccess: Bool = true |
canSubmitForm() | Checks if the form meets all requirements for submission. | func canSubmitForm() -> Bool {} |
isFormValid | Returns true if the form data is valid. | var isFormValid: Bool = false |
Delegate and Data Source Methodsβ
Delegate and data source methods should be named to reflect the events or actions they handle. They often use a pattern of describing the component, the event, and the response.
- Use Descriptive Method Names: Include the name of the object that triggers the event, the action that occurs, and any relevant context (e.g.,
tableView(_:didSelectRowAt:)
). - Follow the
subjectVerbObject
Pattern: This pattern helps in making delegate methods more readable (e.g.,buttonDidTap(_:)
). - Use Optional Parameters When Possible: For delegate methods that may not require all parameters in every implementation, consider using optional parameters to keep the method signature concise.
Name | Purpose | Example |
---|---|---|
tableView(_:didSelectRowAt:) | Called when a user selects a row in a table view. | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {} |
textFieldDidBeginEditing(_:) | Notifies that a text field has started editing. | func textFieldDidBeginEditing(_ textField: UITextField) {} |
buttonDidTap(_:) | Handles tap events on a custom button. | func buttonDidTap(_ button: UIButton) {} |
collectionView(_:cellForItemAt:) | Provides the cell for a specific item in a collection view. | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {} |
Closures and Callbacksβ
Closures and callbacks are often used for asynchronous operations or event handling. Proper naming helps clarify their role and expected behavior.
- Use
completion
orhandler
Suffix: Usecompletion
orhandler
as a suffix to indicate that the closure is a callback (e.g.,fetchDataCompletion
). - Describe the Purpose of the Closure: If the closure has a specific role, include that in the name (e.g.,
loginCompletionHandler
). - Use Descriptive Parameter Names: When defining closures, use descriptive names for the parameters to clarify what each value represents.
Name | Purpose | Example |
---|---|---|
completionHandler | Indicates a closure that will be called upon completion of an operation. | func fetchData(completionHandler: @escaping (Result<Data, Error>) -> Void) {} |
loginCompletion | A closure called after a login attempt, passing a Boolean indicating success. | func performLogin(completion: @escaping (Bool) -> Void) {} |
fetchDataCompletion | Called after data is fetched, passing a result object. | func fetchData(completion: @escaping (Result<User, Error>) -> Void) {} |
Parametersβ
Parameter names in functions and methods should be clear and descriptive, reflecting the purpose of the argument.
- Use External and Internal Parameter Names: Use external parameter names to describe the role of the parameter in the function, and internal names to use within the function body (e.g.,
func updateProfile(for userID: String, with data: UserProfile)
). - Avoid Using
and
in Parameter Names: Combining multiple responsibilities in one parameter name can be confusing. Use separate parameters instead of names likesaveUserAndNotify
. - Use Default Parameter Values: For optional behaviors, provide default values for parameters (e.g.,
func displayAlert(message: String, title: String = "Alert")
).
Name | Purpose | Example |
---|---|---|
for userID | External parameter name for provides context, while userID is used internally. | func updateProfile(for userID: String, with data: UserProfile) {} |
with data | with indicates the relationship of the parameter data to the function. | func saveProfile(with data: UserProfile) {} |
message: String, title: String = "Alert" | Sets a default value for the title parameter while requiring the message parameter. | func displayAlert(message: String, title: String = "Alert") {} |
completion: @escaping (Bool) -> Void | Describes a completion handler that expects a Boolean result. | func submitForm(completion: @escaping (Bool) -> Void) {} |
Variables and Constantsβ
Variables and Propertiesβ
Variables and properties should have descriptive names that clearly indicate their purpose and content. This makes the code more readable and maintainable.
- Use
camelCase
: UsecamelCase
for all variable and property names, starting with a lowercase letter and capitalizing each subsequent word (e.g.,userName
,isLoggedIn
). - Be Descriptive: Choose names that reflect the role or purpose of the variable. Avoid generic names like
data
ortemp
. - Use Context-Specific Names: If a variable is scoped within a function or a class, use names that provide context (e.g.,
currentUser
instead of justuser
). - Avoid Redundant Prefixes: Avoid prefixes like
m_
orself.
for properties unless necessary to differentiate from method parameters.
Name | Purpose | Example |
---|---|---|
userFullName | Stores the full name of the user. | var userFullName: String = "John Doe" |
isUserAuthenticated | Indicates whether the user has successfully logged in. | var isUserAuthenticated: Bool = false |
currentTemperature | Represents the current temperature value in a weather app. | var currentTemperature: Double = 72.5 |
remainingItems | Number of items left in stock. | var remainingItems: Int = 10 |
sessionToken | Stores the user session token for authentication. | var sessionToken: String? |
shouldShowAlert | Controls whether an alert should be displayed. | var shouldShowAlert: Bool = true |
totalAmount | Represents the total amount in a shopping cart. | var totalAmount: Decimal = 99.99 |
selectedCategory | Holds the selected category in a filter view. | var selectedCategory: Category? |
Instances of Classes and Structsβ
Instances of classes and structs should have names that describe their role within the context of the application.
- Use Descriptive Names: Choose names that reflect the instance's purpose or role, such as
userManager
for an instance ofUserManager
. - Avoid Generic Names: Avoid using generic names like
manager
orcontroller
. Instead, specify the context (e.g.,authManager
,networkController
). - Singleton Instances: Use
shared
ordefault
as a prefix for singleton instances (e.g.,sharedSession
).
Name | Purpose | Example |
---|---|---|
userManager | Manages user-related operations like login and profile updates. | let userManager = UserManager() |
authService | Handles authentication processes, such as login and logout. | let authService = AuthService() |
databaseController | Manages interactions with the database. | let databaseController = DatabaseController() |
paymentGateway | Facilitates payment processing. | let paymentGateway = PaymentGateway() |
analyticsTracker | Tracks user interactions and events for analytics purposes. | let analyticsTracker = AnalyticsTracker() |
fileDownloader | Downloads files from the internet. | let fileDownloader = FileDownloader() |
networkManager | Handles network requests and connectivity status. | let networkManager = NetworkManager() |
locationProvider | Provides the current location of the user. | let locationProvider = LocationProvider() |
Collections of Instancesβ
Collections should have names that clearly indicate the type and purpose of the items they contain.
- Use Plural Nouns: Use plural forms to indicate that the variable is a collection (e.g.,
users
,products
). - Include Context: Include context about what the collection represents (e.g.,
activeUsers
instead of justusers
). - Avoid Suffixes Like
List
orArray
: Do not use redundant suffixes likelist
orarray
in the name (e.g., useitems
instead ofitemList
).
Name | Purpose | Example |
---|---|---|
registeredUsers | A collection of users who have registered in the app. | var registeredUsers: [User] |
downloadedFiles | An array of files downloaded by the user. | var downloadedFiles: [File] |
availableProducts | List of products available for purchase. | var availableProducts: [Product] |
activeSessions | Tracks active user sessions in the app. | var activeSessions: [Session] |
completedOrders | Contains orders that have been processed and completed. | var completedOrders: [Order] |
favoriteArticles | Collection of articles marked as favorite by the user. | var favoriteArticles: [Article] |
pendingInvitations | List of invitations waiting for user action. | var pendingInvitations: [Invitation] |
recentSearches | Stores recent search queries made by the user. | var recentSearches: [String] |
Constantsβ
Constants should have clear, descriptive names and use consistent formatting to indicate that their values do not change.
- Use
PascalCase
for Global Constants: UsePascalCase
for global constants and constants defined at the top level of a class or struct (e.g.,MaxLoginAttempts
). - Use
SCREAMING_SNAKE_CASE
for Enumerations: UseSCREAMING_SNAKE_CASE
for constants defined within enums (e.g.,API_BASE_URL
). - Group Related Constants: Group related constants into structs or enums to keep them organized (e.g.,
struct API { static let baseURL = "https://api.example.com" }
).
Name | Purpose | Example |
---|---|---|
MaxRetryAttempts | Maximum number of retry attempts for a network request. | let MaxRetryAttempts = 3 |
DefaultUserAvatarURL | Default URL for a user's avatar image if none is provided. | let DefaultUserAvatarURL = "https://example.com/default-avatar.png" |
DefaultTimeoutInterval | Default timeout for network requests in seconds. | let DefaultTimeoutInterval: TimeInterval = 30.0 |
API.baseURL | Base URL for the API endpoints. | struct API { static let baseURL = "https://api.example.com" } |
NotificationKeys.UserDidLogin | Notification key for user login events. | struct NotificationKeys { static let UserDidLogin = "UserDidLoginNotification" } |
ErrorMessages.invalidEmail | Error message displayed for invalid email input. | struct ErrorMessages { static let invalidEmail = "Please enter a valid email address." } |
ThemeColors.primaryColor | Primary color used throughout the app's UI. | struct ThemeColors { static let primaryColor = UIColor.blue } |
AnimationDurations.default | Default duration for animations. | struct AnimationDurations { static let default = 0.3 } |
Enumerations for Constantsβ
Name | Purpose | Example |
---|---|---|
APIEndpoints.getUser | Defines the endpoint for fetching user data. | enum APIEndpoints { static let getUser = "/user" } |
Theme.Fonts.title | Defines the font used for title labels. | struct Theme { struct Fonts { static let title = UIFont.systemFont(ofSize: 18) } } |
UserRoles.admin | Represents the admin role for a user in the app. | enum UserRoles { case admin, user, guest } |
ErrorCodes.networkError | Error code for network-related issues. | enum ErrorCodes { static let networkError = 1001 } |
UserDefaultsKeys.hasSeenIntro | Key for tracking whether the user has seen the introduction screen. | enum UserDefaultsKeys { static let hasSeenIntro = "HasSeenIntro" } |
iOS-Specific Componentsβ
View Controllersβ
View controllers are a core component of UIKit, managing the views and coordinating interactions between the model and view layers. Proper naming helps clarify their role and purpose.
- Use the
ViewController
Suffix: Always use theViewController
suffix for classes that inherit fromUIViewController
(e.g.,LoginViewController
,SettingsViewController
). - Descriptive Prefixes: Use prefixes that describe the view controllerβs purpose or the feature it manages (e.g.,
UserProfileViewController
for managing user profile screens). - Navigation and Tab Controllers: For custom navigation or tab bar controllers, use names like
CustomNavigationController
orMainTabBarController
to indicate their specialized role.
Name | Purpose | Example |
---|---|---|
LoginViewController | Manages user login interactions. | class LoginViewController: UIViewController {} |
UserProfileViewController | Displays and edits the user profile. | class UserProfileViewController: UIViewController {} |
SettingsViewController | Handles app settings and preferences. | class SettingsViewController: UIViewController {} |
MainNavigationController | Custom navigation controller for handling main app flow. | class MainNavigationController: UINavigationController {} |
CustomTabBarController | Manages the custom tab bar interface and interactions. | class CustomTabBarController: UITabBarController {} |
SwiftUI Componentsβ
SwiftUI introduces a new paradigm for building user interfaces. Naming conventions for SwiftUI components should reflect their role and reusability.
- Use Descriptive Names: Use names that reflect the component's role and content (e.g.,
UserProfileView
,LoginButton
). - Use the
View
Suffix: Add theView
suffix for standard SwiftUI views to differentiate them from other types (e.g.,SettingsView
). - Reusable Components: Name reusable components with a clear purpose and context (e.g.,
PrimaryButton
,CustomTextField
).
Name | Purpose | Example |
---|---|---|
UserProfileView | Displays detailed information about the user profile. | struct UserProfileView: View {} |
SettingsView | Manages and displays app settings. | struct SettingsView: View {} |
LoginButton | Custom button used for login actions. | struct LoginButton: View {} |
CustomTextField | Customized text field with specific styling. | struct CustomTextField: View {} |
ContentView | Main entry point for the appβs user interface. | struct ContentView: View {} |
UIKit Componentsβ
Custom UIKit components such as buttons, cells, and controls should have names that reflect their function and customization.
- Use Descriptive Names: Name components based on their specific role (e.g.,
PrimaryButton
for a main action button). - Include Context: Use names that provide context, such as
UserProfileCell
for a table view cell that displays user profiles. - Custom Views: For custom views, use names that describe the content and layout, like
UserProfileHeaderView
.
Name | Purpose | Example |
---|---|---|
PrimaryButton | Custom button styled for primary actions. | class PrimaryButton: UIButton {} |
SecondaryButton | Custom button for secondary actions. | class SecondaryButton: UIButton {} |
UserProfileCell | Custom table view cell for displaying user profiles. | class UserProfileCell: UITableViewCell {} |
CustomSwitch | Custom toggle switch with additional features. | class CustomSwitch: UISwitch {} |
RoundedImageView | Image view with rounded corners. | class RoundedImageView: UIImageView {} |
Combine Frameworkβ
The Combine framework is used for handling asynchronous events. Naming conventions for publishers and subscribers should reflect their role and data flow.
- Descriptive Names: Use descriptive names that indicate what data the publisher or subscriber deals with (e.g.,
userUpdatesPublisher
). - Use
Publisher
andSubscriber
Suffixes: Add suffixes likePublisher
andSubscriber
to indicate the type's role in data flow.
Name | Purpose | Example |
---|---|---|
userUpdatesPublisher | Publishes updates to user data. | var userUpdatesPublisher: AnyPublisher<User, Error> |
dataSubscriber | Subscribes to receive updates from a data publisher. | var dataSubscriber: AnyCancellable |
networkStatusPublisher | Publishes changes in network connectivity status. | var networkStatusPublisher: AnyPublisher<Bool, Never> |
authStateSubscriber | Subscribes to authentication state changes. | var authStateSubscriber: AnyCancellable |
searchResultsPublisher | Publishes search results based on user queries. | var searchResultsPublisher: AnyPublisher<[SearchResult], Never> |
CoreDataβ
CoreData entities and attributes should have clear, descriptive names that reflect their role in the data model.
- Entity Names: Use
PascalCase
for entity names that describe the model (e.g.,User
,Order
). - Attribute Names: Use
camelCase
for attribute names that describe the data stored (e.g.,firstName
,orderDate
). - Avoid Redundancy: Do not include the entity name in attribute names (e.g., use
name
instead ofuserName
for aUser
entity).
Name | Purpose | Example |
---|---|---|
User | Represents a user entity in the CoreData model. | class User: NSManagedObject {} |
Order | Represents an order placed by a user. | class Order: NSManagedObject {} |
firstName | Stores the first name of a user. | @NSManaged public var firstName: String? |
orderDate | Date when the order was placed. | @NSManaged public var orderDate: Date? |
totalAmount | Total amount of an order. | @NSManaged public var totalAmount: Double |
Resources and Assetsβ
Image Assetsβ
Image assets are an integral part of any iOS application. Proper naming helps maintain consistency and makes it easier to find and update assets.
- Use
snake_case
for Asset Names: Use lowercase letters with underscores to separate words (e.g.,icon_user_profile
,bg_home_screen
). - Use Descriptive Prefixes: Prefix the asset name with its type or usage (e.g.,
icon_
,bg_
for background images,btn_
for button images). - Include Size and State Modifiers: If the asset has different sizes or states, include them in the name (e.g.,
icon_user_profile@2x
,btn_submit_disabled
).
Name | Purpose | Example |
---|---|---|
icon_user_profile | Icon representing a user's profile. | icon_user_profile.png |
bg_home_screen | Background image for the home screen. | bg_home_screen.jpg |
btn_submit_disabled | Image for the disabled state of a submit button. | btn_submit_disabled.png |
icon_notification | Icon used for notifications. | icon_notification.png |
bg_login_screen@2x | Retina version of the login screen background image. | bg_login_screen@2x.png |
Colorsβ
Color assets should have clear, descriptive names that indicate their usage or context. This makes it easy to update themes or adapt for different design systems.
- Use Descriptive Names Reflecting Usage: Use names that reflect the purpose or context, such as
primaryColor
,backgroundColor
,textColor
. - Themed Colors: If your app supports themes (e.g., light and dark modes), use prefixes like
lightModePrimary
,darkModeAccent
. - Avoid Generic Names: Avoid names like
blueColor
orredColor
. Instead, use names likeerrorColor
orsuccessColor
to reflect their use.
Name | Purpose | Example |
---|---|---|
primaryColor | Primary color used throughout the app for buttons and links. | primaryColor |
secondaryTextColor | Color used for secondary text elements. | secondaryTextColor |
errorColor | Color used for error messages and icons. | errorColor |
backgroundColor | Default background color for views and screens. | backgroundColor |
lightModePrimary | Primary color used in light mode. | lightModePrimary |
Fonts and Stylesβ
Fonts and text styles should be named according to their usage in the app, making it easy to apply consistent typography across different screens.
- Use the Font Family and Style: Include the font family and style in the name (e.g.,
Roboto-Bold
,OpenSans-Italic
). - Use Descriptive Names for Text Styles: For reusable text styles, use names that describe the role, like
titleFont
,bodyFont
. - Avoid Ambiguous Names: Avoid using generic names like
customFont
. Be specific about the style and weight.
Name | Purpose | Example |
---|---|---|
titleFont | Font used for titles and headings. | static let titleFont = "Helvetica-Bold" |
bodyFont | Font used for main body text. | static let bodyFont = "OpenSans-Regular" |
buttonFont | Font used for buttons. | static let buttonFont = "Roboto-Bold" |
captionFont | Font used for small captions and notes. | static let captionFont = "OpenSans-LightItalic" |
subtitleFont | Font used for subtitles and secondary headings. | static let subtitleFont = "Helvetica-Italic" |
Localized Strings and Pluralsβ
Localized strings should have meaningful keys that make it easy to identify their usage. Plurals should be handled using appropriate key naming conventions to ensure clarity.
- Use
camelCase
for Keys: UsecamelCase
for string keys (e.g.,loginButtonTitle
,errorMessage
). - Group Keys by Feature: Organize keys by feature or screen to make localization files easier to manage (e.g.,
login_username_placeholder
). - Use Contextual Names for Plurals: Use names that reflect the context of the plural, like
numberOfItems
ordaysRemaining
.
Name | Purpose | Example |
---|---|---|
loginButtonTitle | Title for the login button. | "loginButtonTitle" = "Log In"; |
welcomeMessage | Message displayed on the welcome screen. | "welcomeMessage" = "Welcome to the App!"; |
errorMessage | General error message for user input errors. | "errorMessage" = "An error has occurred."; |
numberOfItems | Plural string indicating the number of items. | "numberOfItems" = "%d items"; |
daysRemaining | Plural string for the number of days remaining. | "daysRemaining" = "%d days remaining"; |
Soundsβ
Sound assets should be named to clearly indicate their purpose and context of use, such as alerts or notifications.
- Use Descriptive Names: Name sounds based on their function, such as
notification_alert
orbutton_click
. - Organize by Category: Group related sounds by category, using a prefix like
alert_
,button_
,background_
. - Include File Format: Ensure the file format (e.g.,
.mp3
,.wav
) is appropriate for the platform and file type.
Name | Purpose | Example |
---|---|---|
notification_alert | Sound played for notifications. | notification_alert.mp3 |
button_click | Sound for button click feedback. | button_click.wav |
background_music | Background music loop for the main menu. | background_music.mp3 |
success_chime | Sound played on successful completion of an action. | success_chime.wav |
error_buzz | Error sound played when an invalid action occurs. | error_buzz.mp3 |
Asset Catalog Organizationβ
Organizing assets within the catalog ensures that they are easy to find and manage.
- Use Asset Folders: Group related assets into folders within the asset catalog (e.g.,
Icons
,Backgrounds
,Buttons
). - Use Asset Sets for Variants: Use asset sets to manage different resolutions and states (e.g.,
icon_user_profile
with1x
,2x
,3x
variants). - Naming Convention Consistency: Maintain a consistent naming convention across all assets to avoid confusion.
Name | Purpose | Example |
---|---|---|
Icons | Folder containing all application icons. | icon_user_profile , icon_settings |
Backgrounds | Folder for background images. | bg_login_screen , bg_home_screen |
Buttons | Folder for button images, including active and disabled states. | btn_submit_active , btn_submit_disabled |
Sounds | Folder for all sound assets. | button_click.wav , alert_tone.mp3 |
Storyboard and XIB Elementsβ
Storyboard Identifiersβ
Storyboard identifiers are used to reference view controllers and segues within a storyboard. Proper naming makes it easier to manage navigation and transitions between scenes.
- Use Descriptive Identifiers: Use identifiers that clearly describe the purpose or role of the view controller or segue (e.g.,
LoginViewControllerID
,showUserProfileSegue
). - Match with View Controller Names: The storyboard identifier should generally match the name of the view controller class (e.g.,
UserProfileViewControllerID
for aUserProfileViewController
). - Use CamelCase: Use
camelCase
orPascalCase
for storyboard identifiers, avoiding spaces or special characters.
Name | Purpose | Example |
---|---|---|
LoginViewControllerID | Identifier for the login view controller. | LoginViewControllerID |
showUserProfileSegue | Segue identifier for transitioning to the user profile view. | showUserProfileSegue |
SettingsViewControllerID | Identifier for the settings view controller. | SettingsViewControllerID |
unwindToHomeSegue | Identifier for an unwind segue back to the home screen. | unwindToHomeSegue |
MainTabBarControllerID | Identifier for the main tab bar controller. | MainTabBarControllerID |
XIB Files and Outletsβ
XIB files and their elements, such as buttons and labels, should have names that reflect their role and usage within the interface.
XIB Fileβ
- Match with Contained Class: The XIB file name should match the name of the view or view controller class it is associated with (e.g.,
CustomButton.xib
for aCustomButton
class). - Use PascalCase: Use
PascalCase
for XIB file names, avoiding underscores or spaces.
Name | Purpose | Example |
---|---|---|
CustomButton.xib | XIB file for a reusable custom button. | CustomButton.xib |
UserProfileHeaderView.xib | XIB file for a custom header view in user profile. | UserProfileHeaderView.xib |
LoginFormView.xib | XIB file for a custom login form. | LoginFormView.xib |
SettingsTableViewCell.xib | XIB file for a custom settings table view cell. | SettingsTableViewCell.xib |
RoundedImageView.xib | XIB file for a custom image view with rounded corners. | RoundedImageView.xib |
Outletβ
Outlets should be named to reflect the role and type of the UI element they reference. This makes it easy to understand their purpose in the code.
- Use
camelCase
: UsecamelCase
for outlet names, starting with a lowercase letter and using capital letters to separate words. - Include Element Type: Include the type of the element in the name (e.g.,
submitButton
for a button,titleLabel
for a label). - Avoid Prefixes like
lbl
orbtn
: Do not use abbreviations likelbl
orbtn
in outlet names. Instead, use full descriptive names.
Name | Purpose | Example |
---|---|---|
userProfileImageView | Outlet for a UIImageView displaying the user profile picture. | @IBOutlet weak var userProfileImageView: UIImageView! |
submitButton | Outlet for a UIButton used to submit a form. | @IBOutlet weak var submitButton: UIButton! |
titleLabel | Outlet for a UILabel displaying the screen title. | @IBOutlet weak var titleLabel: UILabel! |
emailTextField | Outlet for a UITextField used for email input. | @IBOutlet weak var emailTextField: UITextField! |
loginActivityIndicator | Outlet for a UIActivityIndicatorView showing login progress. | @IBOutlet weak var loginActivityIndicator: UIActivityIndicatorView! |
Actionβ
Actions triggered by user interactions should be named to indicate the type of event and the element that triggers it.
- Use Verb Phrases: Start action names with a verb that describes the interaction (e.g.,
submitButtonTapped
,textFieldEditingChanged
). - Include Element Name: Include the name of the UI element in the action method (e.g.,
loginButtonTapped
). - Use
camelCase
: UsecamelCase
for action names, starting with a lowercase letter.
Name | Purpose | Example |
---|---|---|
submitButtonTapped | Action triggered when the submit button is tapped. | @IBAction func submitButtonTapped(_ sender: UIButton) {} |
loginButtonTapped | Action triggered when the login button is pressed. | @IBAction func loginButtonTapped(_ sender: UIButton) {} |
textFieldEditingChanged | Action called when the text field content changes. | @IBAction func textFieldEditingChanged(_ sender: UITextField) {} |
sliderValueChanged | Action triggered when the slider value is adjusted. | @IBAction func sliderValueChanged(_ sender: UISlider) {} |
switchToggled | Action triggered when the switch is toggled. | @IBAction func switchToggled(_ sender: UISwitch) {} |
Segue Identifiersβ
Segue identifiers are used to manage transitions between view controllers. Proper naming makes it easy to identify and manage these transitions.
- Use Verb Phrases: Use names that describe the transition, such as
showDetailSegue
orpresentSettingsSegue
. - Include Source and Destination: If necessary, include the source and destination view controllers in the name for clarity (e.g.,
mainToSettingsSegue
). - Use
camelCase
: UsecamelCase
for segue identifiers, starting with a lowercase letter.
Name | Purpose | Example |
---|---|---|
showUserProfileSegue | Segue to show the user profile view. | showUserProfileSegue |
presentSettingsSegue | Segue to present the settings view modally. | presentSettingsSegue |
mainToDetailSegue | Segue from the main view to the detail view. | mainToDetailSegue |
loginToHomeSegue | Segue to navigate from login to the home screen. | loginToHomeSegue |
showOrderHistorySegue | Segue to display the order history view. | showOrderHistorySegue |
Error Handlingβ
Error Types and Enumsβ
Error types and enums represent different error conditions in your app. Proper naming helps developers quickly understand the context and type of error being handled.
- Use Descriptive Names Ending with
Error
: Name error types and enums with a descriptive name followed byError
to indicate that they represent an error type (e.g.,NetworkError
,DatabaseError
). - Use PascalCase for Enum Cases: Use
PascalCase
for enum cases to maintain consistency with Swift naming conventions (e.g.,invalidURL
,noDataAvailable
). - Group Related Errors in a Single Enum: Group errors that belong to the same domain or context in a single enum (e.g.,
AuthenticationError
for all authentication-related errors).
enum NetworkError: Error {
case invalidURL
case noDataAvailable
case requestFailed
}
enum DatabaseError: Error {
case dataNotFound
case readFailure
case writeFailure
}
enum AuthenticationError: Error {
case invalidCredentials
case userNotFound
case accountLocked
}
Name | Purpose | Example |
---|---|---|
NetworkError | Represents errors related to network requests. | enum NetworkError: Error {} |
DatabaseError | Defines errors that occur when accessing the database. | enum DatabaseError: Error {} |
AuthenticationError | Handles errors related to user authentication. | enum AuthenticationError: Error {} |
invalidCredentials | Indicates that the provided user credentials are invalid. | case invalidCredentials |
dataNotFound | Error case for missing data in the database. | case dataNotFound |
Error Constants and Messagesβ
Error constants and messages should be named to clearly indicate the type of error and provide meaningful information to the developer and user.
- Use Descriptive Names: Error constants should have descriptive names that convey the issue, such as
invalidEmailError
ornetworkTimeoutError
. - Group Related Messages: Organize related error messages in structs or enums to maintain a clean and structured codebase.
- Use PascalCase for Constants: Use
PascalCase
for error constant names, avoiding underscores or abbreviations.
struct ErrorMessages {
static let invalidEmail = "The email address entered is invalid."
static let passwordTooShort = "The password must be at least 8 characters long."
static let networkTimeout = "The network request timed out. Please try again later."
}
struct ValidationError {
static let missingRequiredFields = "Please fill out all required fields."
static let passwordsDoNotMatch = "The passwords entered do not match."
}
struct NetworkErrorMessages {
static let noInternetConnection = "No internet connection available. Please check your connection and try again."
static let serverUnavailable = "The server is currently unavailable. Please try again later."
}
Name | Purpose | Example |
---|---|---|
invalidEmailError | Indicates an error when the email format is invalid. | static let invalidEmail = "The email address entered is invalid." |
networkTimeoutError | Describes an error when a network request times out. | static let networkTimeout = "The network request timed out. Please try again later." |
missingRequiredFields | Error message for missing form fields. | static let missingRequiredFields = "Please fill out all required fields." |
passwordsDoNotMatch | Error message when password confirmation fails. | static let passwordsDoNotMatch = "The passwords entered do not match." |
noInternetConnection | Error message for no internet connectivity. | static let noInternetConnection = "No internet connection available. Please check your connection and try again." |
Error Handling Methodsβ
Methods for error handling should have names that clearly indicate their purpose and the type of error they handle.
- Use Verb Phrases: Start method names with verbs to describe the action being taken, such as
handle
,show
, orlog
. - Include Error Context: Include the context of the error in the method name (e.g.,
handleNetworkError
,logDatabaseError
). - Use Specific Method Names: Avoid generic names like
processError
ordisplayError
. Be specific about the type of error being handled.
func handleNetworkError(_ error: NetworkError) {
switch error {
case .invalidURL:
print("The URL provided is invalid.")
case .noDataAvailable:
print("No data is available for the requested resource.")
case .requestFailed:
print("The network request failed. Please try again.")
}
}
func showAuthenticationError(_ error: AuthenticationError) {
switch error {
case .invalidCredentials:
showAlert(with: "Invalid login credentials. Please try again.")
case .userNotFound:
showAlert(with: "No user found with the provided information.")
case .accountLocked:
showAlert(with: "Your account is locked. Please contact support.")
}
}
func logDatabaseError(_ error: DatabaseError) {
switch error {
case .dataNotFound:
print("Data not found in the database.")
case .readFailure:
print("Failed to read data from the database.")
case .writeFailure:
print("Failed to write data to the database.")
}
}
Name | Purpose | Example |
---|---|---|
handleNetworkError | Handles errors related to network issues. | func handleNetworkError(_ error: NetworkError) {} |
showAuthenticationError | Displays errors related to authentication failures. | func showAuthenticationError(_ error: AuthenticationError) {} |
logDatabaseError | Logs errors encountered when interacting with the database. | func logDatabaseError(_ error: DatabaseError) {} |
showAlert(with:) | Displays an alert with a specific error message. | func showAlert(with message: String) {} |
logErrorToAnalytics(_:) | Logs the error details to an analytics service. | func logErrorToAnalytics(_ error: Error) {} |
Testsβ
Unit Test Classes and Methodsβ
Unit tests verify the functionality of individual components in isolation. Naming test classes and methods correctly helps in understanding the scope and purpose of each test.
Test Class Namingβ
- Use the
Tests
Suffix: AppendTests
to the name of the class being tested (e.g.,UserViewModelTests
,LoginManagerTests
). - Include the Class Name: The test class name should include the class or module it is testing (e.g.,
UserViewModelTests
for theUserViewModel
class). - Group by Feature or Module: If a single class has many test cases, consider grouping them by feature or module (e.g.,
LoginFeatureTests
).
Name | Purpose | Example |
---|---|---|
UserViewModelTests | Contains unit tests for the UserViewModel class. | class UserViewModelTests: XCTestCase {} |
LoginManagerTests | Tests functionality of the LoginManager class. | class LoginManagerTests: XCTestCase {} |
NetworkServiceTests | Tests for network-related methods in NetworkService . | class NetworkServiceTests: XCTestCase {} |
SettingsViewModelTests | Tests for user settings management in SettingsViewModel . | class SettingsViewModelTests: XCTestCase {} |
OrderHistoryFeatureTests | Group of tests related to order history functionality. | class OrderHistoryFeatureTests: XCTestCase {} |
Test Method Namingβ
- Use
test
Prefix: Start each test method name withtest
to indicate that it is a test case (e.g.,testUserLogin
,testFetchUserData
). - Describe the Expected Outcome: Include the specific condition or outcome being tested (e.g.,
testLoginSuccess
,testFetchUserDataFailure
). - Use
camelCase
: UsecamelCase
for method names, starting with lowercase and capitalizing each subsequent word.
Name | Purpose | Example |
---|---|---|
testUserLogin | Tests the user login functionality. | func testUserLogin() {} |
testFetchUserDataSuccess | Verifies that user data is fetched successfully. | func testFetchUserDataSuccess() {} |
testInvalidCredentialsError | Checks for an error when invalid login credentials are provided. | func testInvalidCredentialsError() {} |
testSettingsSaveFailure | Tests failure case for saving user settings. | func testSettingsSaveFailure() {} |
testOrderHistoryDisplay | Verifies correct display of order history information. | func testOrderHistoryDisplay() {} |
UI Testsβ
UI tests validate the user interface and user interactions within the app. Proper naming helps identify what part of the UI is being tested and the expected behavior.
UI Test Class Namingβ
- Use the
UITests
Suffix: AppendUITests
to the name of the view or feature being tested (e.g.,LoginUITests
,HomeScreenUITests
). - Describe the View or Feature: Include the view or feature name in the class name (e.g.,
UserProfileUITests
for testing the user profile screen). - Group by Feature or Screen: Group tests that interact with the same screen or feature (e.g.,
SettingsScreenUITests
).
Name | Purpose | Example |
---|---|---|
LoginUITests | Contains UI tests for the login screen. | class LoginUITests: XCTestCase {} |
UserProfileUITests | UI tests for the user profile view. | class UserProfileUITests: XCTestCase {} |
HomeScreenUITests | Tests the main home screen UI and interactions. | class HomeScreenUITests: XCTestCase {} |
SettingsScreenUITests | UI tests for the settings screen. | class SettingsScreenUITests: XCTestCase {} |
OrderHistoryUITests | Verifies the UI for displaying order history. | class OrderHistoryUITests: XCTestCase {} |
UI Test Method Namingβ
- Use
test
Prefix: Begin each method name withtest
followed by the action or state being tested (e.g.,testLoginButtonTap
,testProfileUpdate
). - Describe the UI Interaction: Include the specific user action or UI component being tested (e.g.,
testLoginButtonTap
ortestProfileImageChange
). - Use
camelCase
: UsecamelCase
for method names, starting with lowercase and capitalizing each subsequent word.
Name | Purpose | Example |
---|---|---|
testLoginButtonTap | Tests that tapping the login button triggers the login process. | func testLoginButtonTap() {} |
testProfileImageChange | Verifies that changing the profile image works correctly. | func testProfileImageChange() {} |
testSettingsToggleSwitch | Tests that the settings toggle switch updates preferences correctly. | func testSettingsToggleSwitch() {} |
testOrderHistoryScroll | Checks that the order history list scrolls smoothly. | func testOrderHistoryScroll() {} |
testSearchFunctionality | Tests the search functionality in the home screen. | func testSearchFunctionality() {} |
Test Data and Mocksβ
Test data and mock objects are often used in tests to simulate real-world scenarios. Proper naming helps differentiate them from real objects and clarifies their purpose.
Test Data Namingβ
- Use
Mock
orTest
Prefix: Prefix test data or mock objects withMock
orTest
to indicate their role (e.g.,MockUser
,TestOrder
). - Describe the Data Type: Include the type of data in the name, such as
User
,Order
, orResponse
(e.g.,MockUser
,TestLoginResponse
). - Use Specific Names for Scenarios: Use specific names for data objects that represent particular test scenarios (e.g.,
MockUserInvalidEmail
,TestOrderWithoutItems
).
Name | Purpose | Example |
---|---|---|
MockUser | Represents a generic mock user object for testing. | let mockUser = User(id: 1, name: "John Doe") |
TestLoginResponse | Simulates a login response from the server. | let testLoginResponse = LoginResponse(success: true) |
MockUserInvalidEmail | Represents a user object with an invalid email for testing error handling. | let mockUserInvalidEmail = User(email: "invalid-email") |
TestOrderWithoutItems | Test order object without items to test validation. | let testOrderWithoutItems = Order(items: []) |
MockNetworkService | Mock object for simulating network requests. | let mockNetworkService = MockNetworkService() |
Mock Object Namingβ
- Use
Mock
Prefix: Use theMock
prefix for mock classes or structs that simulate the behavior of real objects (e.g.,MockAPIClient
,MockUserService
). - Include the Original Objectβs Name: The mock class name should include the name of the real object it is simulating (e.g.,
MockUserManager
for theUserManager
class). - Use Descriptive Method Names: Mock methods should have names that clearly indicate the simulated behavior (e.g.,
simulateNetworkError()
).
Name | Purpose | Example |
---|---|---|
MockAPIClient | Simulates the behavior of a real API client. | class MockAPIClient: APIClient {} |
MockUserService | Mocks the user service for testing user-related functionality. | class MockUserService: UserService {} |
MockDatabaseManager | Simulates database operations for testing. | class MockDatabaseManager: DatabaseManager {} |
MockAuthManager | Mocks the authentication manager to simulate login/logout scenarios. | class MockAuthManager: AuthManager {} |
MockOrderService | Mocks order service operations such as placing and canceling orders. | class MockOrderService: OrderService {} |
Swift Packages and Modulesβ
Swift Package Namesβ
Swift packages are reusable libraries or frameworks that can be imported into various projects. Proper naming helps developers identify the purpose and scope of the package.
- Use
PascalCase
: UsePascalCase
for package names, capitalizing the first letter of each word (e.g.,NetworkingKit
,UserAuthentication
). - Be Descriptive Yet Concise: Choose names that clearly describe the package's functionality without being overly verbose (e.g.,
ImageProcessing
, notImageProcessingAndFiltering
). - Avoid Generic Names: Avoid overly generic names like
Utilities
orHelpers
. Instead, use names that reflect the package's specific purpose (e.g.,DateUtilities
).
Name | Purpose | Example |
---|---|---|
NetworkingKit | Provides networking utilities and API client implementations. | import NetworkingKit |
UserAuthentication | Handles user login, registration, and authentication processes. | import UserAuthentication |
ImageProcessing | Offers image manipulation and filtering functionalities. | import ImageProcessing |
CoreDataHelper | Simplifies CoreData operations like saving and fetching data. | import CoreDataHelper |
PushNotificationManager | Manages push notifications and permissions. | import PushNotificationManager |
Module Namesβ
Modules represent the scope of a package, encapsulating its types and functionalities. Proper naming ensures that modules are easy to understand and use.
- Match the Package Name: The module name should generally match the package name to avoid confusion (e.g.,
NetworkingKit
for a package namedNetworkingKit
). - Use Descriptive Names for Submodules: If the package is divided into submodules, use names that clearly describe their functionality (e.g.,
NetworkingKit.Authentication
).
Name | Purpose | Example |
---|---|---|
NetworkingKit | Core module of the NetworkingKit package. | import NetworkingKit |
NetworkingKit.Authentication | Submodule for handling authentication-related networking operations. | import NetworkingKit.Authentication |
ImageProcessing.Filters | Submodule for applying filters to images. | import ImageProcessing.Filters |
CoreDataHelper.Utilities | Submodule for utility functions related to CoreData. | import CoreDataHelper.Utilities |
UserAuthentication.OAuth | Submodule for handling OAuth authentication. | import UserAuthentication.OAuth |
Components within Packagesβ
Within a Swift package, various components like classes, structs, enums, and protocols need clear and consistent naming to facilitate use and collaboration.
Classes and Structsβ
- Use
PascalCase
: UsePascalCase
for class and struct names, similar to how you would name them in a regular Swift file (e.g.,APIClient
,UserManager
). - Include the Module Prefix: If a class or struct is tightly coupled with its module, consider including the module prefix in the name (e.g.,
NetworkingAPIClient
).
Name | Purpose | Example |
---|---|---|
APIClient | Represents a generic API client for making network requests. | class APIClient {} |
UserManager | Manages user-related operations like login and registration. | struct UserManager {} |
ImageFilter | Applies filters to images in the ImageProcessing package. | struct ImageFilter {} |
OAuthHandler | Manages OAuth authentication flows in UserAuthentication . | class OAuthHandler {} |
PushNotificationService | Handles push notification setup and delivery. | class PushNotificationService {} |
Protocolsβ
- Use Adjective or Noun Descriptions: Protocols should be named to describe a capability or role (e.g.,
Configurable
,Authenticatable
). - Avoid Prefixes like
I
: Unlike some other languages, Swift protocols should not use theI
prefix (e.g.,IConfigurable
is incorrect; useConfigurable
).
Name | Purpose | Example |
---|---|---|
Configurable | Protocol for objects that can be configured. | protocol Configurable {} |
Authenticatable | Protocol for types that support authentication operations. | protocol Authenticatable {} |
NetworkRequestable | Protocol defining methods for making network requests. | protocol NetworkRequestable {} |
ImageFilterable | Protocol for applying filters to images. | protocol ImageFilterable {} |
Persistable | Protocol for objects that can be saved to persistent storage. | protocol Persistable {} |
Enumsβ
- Use
PascalCase
for Enum Names andcamelCase
for Cases: UsePascalCase
for the enum name andcamelCase
for its cases (e.g.,NetworkError
,networkTimeout
). - Group Related Constants: Use enums to group related constants or states, especially in complex modules.
Name | Purpose | Example |
---|---|---|
NetworkError | Defines different types of network errors. | enum NetworkError { case networkTimeout } |
AuthenticationState | Represents different states of user authentication. | enum AuthenticationState { case loggedIn, loggedOut } |
ImageFilterType | Specifies different types of image filters. | enum ImageFilterType { case sepia, monochrome } |
DatabaseOperation | Enumerates various database operations like read and write. | enum DatabaseOperation { case read, write } |
PushNotificationType | Defines different types of push notifications. | enum PushNotificationType { case alert, badge, sound } |
Resource and Asset in Packagesβ
Resources and assets like images, colors, and localizations should be named to reflect their purpose and usage within the package.
Images and Iconsβ
- Use Descriptive Names with Context: Include the purpose or context in the name (e.g.,
icon_add
,background_login
). - Use
snake_case
: Use lowercase letters and underscores to separate words (e.g.,icon_user_profile
).
Name | Purpose | Example |
---|---|---|
icon_add | Icon for the "Add" action. | icon_add.png |
background_login | Background image for the login screen. | background_login.jpg |
button_primary | Image for the primary button state. | button_primary.png |
icon_notification | Icon used for notifications. | icon_notification.png |
bg_home_screen | Background image for the home screen. | bg_home_screen.jpg |
Colorsβ
- Use Contextual Names: Name colors based on their usage (e.g.,
primaryColor
,errorColor
). - Support for Themes: Include theme prefixes if the package supports multiple themes (e.g.,
lightModePrimary
).
Name | Purpose | Example |
---|---|---|
primaryColor | Primary color used throughout the app. | primaryColor |
secondaryTextColor | Color used for secondary text elements. | secondaryTextColor |
errorColor | Color used for error messages and icons. | errorColor |
backgroundColor | Default background color for views and screens. | backgroundColor |
lightModePrimary | Primary color used in light mode. | lightModePrimary |
Build Configurations and Schemesβ
Build Configurationsβ
Build configurations define how your app is built and deployed. Proper naming ensures that configurations are easily identifiable and manageable across different environments.
- Use Environment and Purpose in the Name: Include both the environment (e.g.,
Debug
,Release
,Staging
) and the purpose of the build (e.g.,DebugTesting
,ReleaseProduction
). - Follow a Consistent Format: Use a consistent naming pattern like
EnvironmentPurpose
(e.g.,DebugTesting
,ReleaseProduction
). - Use PascalCase: Use
PascalCase
for build configuration names to maintain clarity and consistency.
Name | Purpose | Example |
---|---|---|
DebugTesting | Used for debugging and testing features during development. | DebugTesting |
ReleaseProduction | Production build for release to the App Store. | ReleaseProduction |
StagingInternal | Build configuration for internal testing on a staging environment. | StagingInternal |
DebugLocal | Build configuration for local development and testing. | DebugLocal |
ReleaseBeta | Release configuration for beta testing with external users. | ReleaseBeta |
Schemesβ
Schemes define the build configuration, target, and settings for running, testing, and profiling your app. Proper naming helps in distinguishing between different purposes, such as testing, deployment, and debugging.
- Include the Target and Configuration: Use the target name followed by the build configuration to clarify the schemeβs purpose (e.g.,
AppName-ReleaseProduction
). - Use PascalCase with Hyphen: Use
PascalCase
for names and separate the target and configuration with a hyphen (e.g.,AppName-ReleaseBeta
). - Describe the Environment or Role: Include a description of the environment or the scheme's role, such as
AppName-Testing
orAppName-Deployment
.
Name | Purpose | Example |
---|---|---|
MyApp-ReleaseProduction | Scheme for releasing the production build of MyApp . | MyApp-ReleaseProduction |
MyApp-DebugTesting | Scheme for debugging and testing MyApp . | MyApp-DebugTesting |
MyApp-StagingInternal | Internal staging scheme for testing MyApp . | MyApp-StagingInternal |
MyApp-ReleaseBeta | Scheme for beta testing MyApp with external users. | MyApp-ReleaseBeta |
MyApp-DebugLocal | Local development scheme for MyApp testing and debugging. | MyApp-DebugLocal |
Build Settings and Info.plist Keysβ
Build settings and Info.plist
keys control various aspects of your appβs configuration, such as versioning, bundle identifiers, and environment-specific settings.
Build Settings Namingβ
- Use Descriptive Names: Use names that clearly describe the settingβs purpose, such as
BASE_URL
,API_KEY
, orENABLE_LOGGING
. - Use Uppercase with Underscores: Use uppercase letters with underscores to separate words for environment variables (e.g.,
API_BASE_URL
,ENABLE_CRASH_REPORTING
).
Name | Purpose | Example |
---|---|---|
API_BASE_URL | Base URL for the API in the current environment. | API_BASE_URL |
ENABLE_LOGGING | Enables or disables logging based on the build configuration. | ENABLE_LOGGING |
APP_VERSION | Represents the current version of the app. | APP_VERSION |
API_KEY | API key used for authentication with the backend services. | API_KEY |
FEATURE_FLAG_NEW_UI | Toggles the new UI feature in the app. | FEATURE_FLAG_NEW_UI |
Info.plist Keys Namingβ
- Use CamelCase: Use
camelCase
for customInfo.plist
keys to match Appleβs conventions (e.g.,isFeatureEnabled
). - Include Feature Context: Include the feature or purpose in the key name to make it clear what the key controls (e.g.,
enableFeatureX
,isBetaVersion
).
Name | Purpose | Example |
---|---|---|
isFeatureEnabled | Controls whether a specific feature is enabled in the app. | isFeatureEnabled |
enableBetaFeatures | Toggles access to beta features in the app. | enableBetaFeatures |
apiBaseURL | Defines the base URL for API requests. | apiBaseURL |
supportEmailAddress | Specifies the support email address for user queries. | supportEmailAddress |
isBetaVersion | Indicates whether the app is a beta version. | isBetaVersion |
Configuration Filesβ
Configuration files, such as .xcconfig
files, store build settings and environment-specific configurations. Proper naming makes these files easier to manage and identify.
- Use the Configuration and Environment: Name configuration files based on the build configuration and environment (e.g.,
Debug.xcconfig
,ReleaseProduction.xcconfig
). - Include the Target Name: If the configuration file is specific to a target, include the target name in the file name (e.g.,
AppName-Debug.xcconfig
). - Use Descriptive File Names: Use names that reflect the fileβs role, such as
EnvironmentVariables.xcconfig
orFeatureFlags.xcconfig
.
Name | Purpose | Example |
---|---|---|
Debug.xcconfig | Configuration file for the debug build. | Debug.xcconfig |
ReleaseProduction.xcconfig | Configuration file for the release production build. | ReleaseProduction.xcconfig |
AppName-Debug.xcconfig | Debug configuration file specific to the AppName target. | AppName-Debug.xcconfig |
EnvironmentVariables.xcconfig | Stores environment-specific variables like API keys and URLs. | EnvironmentVariables.xcconfig |
FeatureFlags.xcconfig | Configuration file for managing feature flags in different environments. | FeatureFlags.xcconfig |
Scheme Actions Namingβ
Scheme actions define the pre- and post-build scripts, environment variables, and settings for running and testing your app. Proper naming helps keep these actions organized.
- Use Verb Phrases: Use verb phrases to describe the action being performed (e.g.,
RunTests
,UploadBuild
,GenerateMocks
). - Include Context: Include the context or target of the action, such as
RunUnitTests
orBuildDocumentation
. - Use PascalCase: Use
PascalCase
for naming actions to keep the naming consistent and clear.
Name | Purpose | Example |
---|---|---|
RunUnitTests | Action to run unit tests before the build. | RunUnitTests |
UploadBuild | Action to upload the build to the distribution platform. | UploadBuild |
GenerateMocks | Action to generate mock files for testing. | GenerateMocks |
BuildDocumentation | Action to build project documentation using a specified tool. | BuildDocumentation |
DeployToStaging | Action to deploy the current build to the staging environment. | DeployToStaging |