Класс ObjC/Cocoa для преобразования размера к человекочитаемой строке?

Мой комментарий к вашему вопросу объясняет, почему он не работает. Этот ответ показывает способ выполнить то, что вы просили, основываясь на вашем разъяснении, что MyChild не должен распространяться MyParent.

Это пример взлома, который заставляет его работать, используя тот факт, что php не если вы вызываете защищенные методы в других случаях, чем вы, если вы разделяете предок защищенного метода.

Мне пришлось изменить код, чтобы сделать его действительным php. __constructor не является именем конструктора php.

hacky.php

<?php

class Observer
{
    protected function callme()
    {
        echo 'I was called from ' . get_called_class(), PHP_EOL;
    }
}

class MyParent extends Observer
{
    public function createMyChild()
    {
        $this->callme(); // this is OK
        return new MyChild ($this);
    }
}

class MyChild extends Observer // hackey extends
{
    private $myMyParent;
    public function __construct($myMyParent)
    {
        $this->myMyParent = $myMyParent;
        $this->myMyParent->callme();
    }
}

$p = new MyParent;
$c = $p->createMyChild();

Результат:

$ php hacky.php
I was called from MyParent
I was called from MyParent
28
задан dbr 21 February 2009 в 08:11
поделиться

2 ответа

Вот мой собственный взгляд на проблему:

enum {
    kUnitStringBinaryUnits     = 1 << 0,
    kUnitStringOSNativeUnits   = 1 << 1,
    kUnitStringLocalizedFormat = 1 << 2
};

NSString* unitStringFromBytes(double bytes, uint8_t flags){

    static const char units[] = { '\0', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' };
    static int maxUnits = sizeof units - 1;

    int multiplier = (flags & kUnitStringOSNativeUnits && !leopardOrGreater() || flags & kUnitStringBinaryUnits) ? 1024 : 1000;
    int exponent = 0;

    while (bytes >= multiplier && exponent < maxUnits) {
        bytes /= multiplier;
        exponent++;
    }
    NSNumberFormatter* formatter = [[[NSNumberFormatter alloc] init] autorelease];
    [formatter setMaximumFractionDigits:2];
    if (flags & kUnitStringLocalizedFormat) {
        [formatter setNumberStyle: NSNumberFormatterDecimalStyle];
    }
    // Beware of reusing this format string. -[NSString stringWithFormat] ignores \0, *printf does not.
    return [NSString stringWithFormat:@"%@ %cB", [formatter stringFromNumber: [NSNumber numberWithDouble: bytes]], units[exponent]];
}

По умолчанию (если 0 передано для флагов ), выводятся единицы СИ (базовая десятка). Вы можете установить kUnitStringBinaryUnits , чтобы выбрать двоичные (базовые два) блоки, подходящие для памяти, или kUnitStringOSNativeUnits , чтобы тип блока выбирался автоматически в зависимости от версии ОС (до Leopard получает два, после -Леопард получает десятку). Параметр kUnitStringLocalizedFormat форматирует строку на основе текущего языкового стандарта пользователя. Например:

unitStringFromBytes(1073741824, 0); // → "1.07 GB"
unitStringFromBytes(1073741824, kUnitStringBinaryUnits); // → "1 GB"
unitStringFromBytes(1073741824, kUnitStringOSNativeUnits | kUnitStringLocalizedFormat); // → "1.07 GB" (In Mac OS 10.6)
unitStringFromBytes(12345678901234567890123456789, kUnitStringOSNativeUnits | kUnitStringLocalizedFormat); // → "12,345.68 YB" (In Mac OS 10.6, in the US)
unitStringFromBytes(12345678901234567890123456789, kUnitStringOSNativeUnits | kUnitStringLocalizedFormat); // → "12.345,68 YB" (In Mac OS 10.6, in Spain)

Вот вспомогательная функция, необходимая для модулей ОС:

BOOL leopardOrGreater(){
    static BOOL alreadyComputedOS = NO;
    static BOOL leopardOrGreater = NO;
    if (!alreadyComputedOS) {
        SInt32 majorVersion, minorVersion;
        Gestalt(gestaltSystemVersionMajor, &majorVersion);
        Gestalt(gestaltSystemVersionMinor, &minorVersion);
        leopardOrGreater = ((majorVersion == 10 && minorVersion >= 5) || majorVersion > 10);
        alreadyComputedOS = YES;
    }
    return leopardOrGreater;
}
18
ответ дан 28 November 2019 в 02:14
поделиться
NSString *stringFromFileSize(NSInteger theSize)
{
    /*
     From http://snippets.dzone.com/posts/show/3038 with slight modification
     */
    float floatSize = theSize;
    if (theSize<1023)
        return([NSString stringWithFormat:@"%i bytes",theSize]);
    floatSize = floatSize / 1024;
    if (floatSize<1023)
        return([NSString stringWithFormat:@"%1.1f KB",floatSize]);
    floatSize = floatSize / 1024;
    if (floatSize<1023)
        return([NSString stringWithFormat:@"%1.1f MB",floatSize]);
    floatSize = floatSize / 1024;

    return([NSString stringWithFormat:@"%1.1f GB",floatSize]);
}
6
ответ дан dbr 14 October 2019 в 09:18
поделиться