Unexplained numeric literal

ID

objectivec.maintainability.magic_number

Severity

info

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Numeric Literal

Language

Objective-C

Description

Reports a decimal integer literal of three or more digits compared against inside an if or while condition, or used as the initialiser of a mutable variable. Declarations marked const are the fix rather than the defect and are not reported, and neither are #define directives, hexadecimal literals - which are masks and flags rather than quantities - or the round scale factors 100, 1000, 10000, 100000, 1000000 and 1024.

Rationale

A bare number carries no unit and no reason. A reader meeting 86400 has to work out that it is a day in seconds, and cannot tell whether the 86400 in another file is the same quantity or a coincidence - so when the value has to change, some occurrences get updated and others do not. In a condition the problem is sharper still, because the literal is the threshold that decides the behaviour and there is nothing to grep for when someone asks where that threshold is set.

The following code illustrates the pattern detected by this rule:

@implementation Session

- (BOOL)refreshWithRetries:(NSInteger)retries elapsed:(NSInteger)elapsed {
    // FLAGGED: Unexplained numeric literal
    if (retries > 300) {
        return NO;
    }
    // FLAGGED: Unexplained numeric literal
    while (elapsed < 5000) {
        elapsed++;
    }
    // FLAGGED: Unexplained numeric literal
    NSInteger timeout = 86400;
    // FLAGGED: Unexplained numeric literal
    static NSInteger cachedWindow = 3600;

    if (retries > 3) {
        return NO;
    }
    if (elapsed == 0) {
        return NO;
    }
    // A named constant is the fix, not the defect.
    static const NSInteger kSecondsPerDay = 86400;
    const NSInteger maxWindow = 500;
    NSInteger budget = kMaxItems;
    // Round scale factors carry their own meaning.
    NSInteger millis = 1000;
    NSInteger page = 1024;
    // Hexadecimal literals are masks and flags, not quantities.
    NSUInteger mask = 0xFF00;

    // NSInteger timeout = 86400;
    NSLog(@"NSInteger timeout = 86400;");

    NSLog(@"%ld %ld %ld %ld %ld %ld %lu", (long)timeout, (long)cachedWindow, (long)kSecondsPerDay,
          (long)maxWindow, (long)budget, (long)millis + (long)page, (unsigned long)mask);
    return YES;
}

@end

Remediation

Give the value a name once and use the name everywhere - static const NSTimeInterval kSessionLifetime = 86400;, or a FOUNDATION_EXPORT constant when it has to be shared across files. Where the quantity is a duration, prefer a type that carries the unit, such as NSTimeInterval with a named constant built from 60 * 60 * 24, so the derivation is visible rather than folded into a single opaque number.

Configuration

This detector does not need any configuration.

© 2026 Xygeni. All rights reserved