Константы в Objective-C

Для примитивных типов (включая байты) используйте System.Buffer.BlockCopy вместо System.Array.Copy. Это быстрее.

Я назначил каждый из предложенных методов в цикле, выполненном 1 миллион раз, используя 3 массива по 10 байт каждый. Вот результаты:

  1. Новый байт-массив с использованием System.Array.Copy - 0.2187556 секунд
  2. Новый байт-массив с использованием System.Buffer.BlockCopy - 0.1406286 секунд
  3. IEnumerable & lt ; byte> с использованием оператора C # yield - 0.0781270 секунд
  4. IEnumerable & lt; byte> с использованием Concact & lt;> - 0.0781270 секунд LINQ

Я увеличил размер каждого массива до 100 элементов и повторно запустить тест:

  1. Новый массив байтов с использованием System.Array.Copy - 0.2812554 секунд
  2. Новый байт-массив с использованием System.Buffer.BlockCopy - 0.2500048 секунд
  3. IEnumerable & lt; byte> с использованием оператора C # yield - 0.0625012 секунд
  4. IEnumerable & lt; byte> с использованием Concact & lt;> - 0.0781265 секунд LINQ

Я увеличил размер каждого массива до 1000 элементов и повторного запуска теста:

  1. Новый массив байтов с использованием System.Array.Copy - 1.0781457 секунд
  2. Новый массив байтов с использованием System.Buffer.BlockCopy - 1.0156445 секунд
  3. IEnumerable & lt; byte> с использованием оператора C # yield - 0.0625012 секунд
  4. IEnumerable & lt; byte> с использованием Concact & lt;> - 0.07812 LINQ 65 секунд

Наконец, я увеличил размер каждого массива до 1 миллиона элементов и перезапустил тест, выполнив каждый цикл только 4000 раз:

  1. Новый байт-массив с использованием System.Array.Copy - 13.4533833 секунд
  2. Новый массив байтов с использованием System.Buffer.BlockCopy - 13.1096267 секунд
  3. IEnumerable & lt; byte> с использованием оператора C # yield - 0 секунд
  4. IEnumerable & lt; byte> используя Concact & lt;> - 0 секунд LINQ

Итак, если вам нужен новый массив байтов, используйте

byte[] rv = new byte[a1.Length + a2.Length + a3.Length];
System.Buffer.BlockCopy(a1, 0, rv, 0, a1.Length);
System.Buffer.BlockCopy(a2, 0, rv, a1.Length, a2.Length);
System.Buffer.BlockCopy(a3, 0, rv, a1.Length + a2.Length, a3.Length);

Но, если вы может использовать IEnumerable<byte>, DEFINITELY предпочитает метод Concat & lt;> LINQ. Это немного медленнее, чем оператор C # yield, но является более кратким и более элегантным.

IEnumerable<byte> rv = a1.Concat(a2).Concat(a3);

Если у вас есть произвольное количество массивов и вы используете .NET 3.5, вы можете сделать System.Buffer.BlockCopy Решение более общее:

private byte[] Combine(params byte[][] arrays)
{
    byte[] rv = new byte[arrays.Sum(a => a.Length)];
    int offset = 0;
    foreach (byte[] array in arrays) {
        System.Buffer.BlockCopy(array, 0, rv, offset, array.Length);
        offset += array.Length;
    }
    return rv;
}

* Примечание. В приведенном выше блоке вы должны добавить следующее пространство имен вверху, чтобы оно работало.

using System.Linq;

К Jon Skeet's (байтовый массив против IEnumerable & lt; byte>), я повторно запустил последний тест времени (1 миллион элементов, 4000 итераций), добавив цикл, который выполняет итерацию по всему массиву с каждым проходом:

  1. Массив нового байта с использованием System.Array.Copy - 78.20550510 секунд
  2. Новый байт-массив с использованием System.Buffer.BlockCopy - 77.89261900 секунд
  3. IEnumerable & lt; byte> с использованием C # yield оператор - 551.7150161 секунд
  4. IEnumerable & lt; byte> с использованием Concact & lt;> - 448.1804799 секунд LINQ

Суть в том, что ОЧЕНЬ важно, чтобы понять эффективность как креацио n и использование результирующей структуры данных. Простое сосредоточение на эффективности создания может не учитывать неэффективность, связанную с использованием. Кудос, Джон.

994
задан Peter Mortensen 13 March 2015 в 20:32
поделиться

6 ответов

Необходимо создать заголовочный файл как

// Constants.h
FOUNDATION_EXPORT NSString *const MyFirstConstant;
FOUNDATION_EXPORT NSString *const MySecondConstant;
//etc.

(можно использовать extern вместо FOUNDATION_EXPORT, если код не будет использоваться в смешанных средах C/C++ или на других платформах)

, можно включать этот файл в каждый файл, который использует константы или в предварительно скомпилированный заголовок для проекта.

Вы определяете эти константы в.m файле как [1 110]

// Constants.m
NSString *const MyFirstConstant = @"FirstConstant";
NSString *const MySecondConstant = @"SecondConstant";

, Constants.m должен быть добавлен к Вашей цели приложения/платформы так, чтобы это было связано в с конечным продуктом.

преимущество использования строковых констант вместо #define 'd константы состоит в том, что можно протестировать на равенство с помощью сравнения указателя (stringInstance == MyFirstConstant), который намного быстрее, чем сравнение строк ([stringInstance isEqualToString:MyFirstConstant]) (и легче читать, IMO).

1280
ответ дан Barry Wark 14 March 2015 в 06:32
поделиться
  • 1
    Полностью не знаю об этом, я имею 5 + приложения на Appstore, они все используют Достижимость, я использовал достижимость, как я описал выше в ответе, таким образом, я не знаю о том, что должно быть реализовано, я обычно реализую то, в чем я нуждаюсь – Omar Abdelhafith 24 June 2012 в 23:40

Если Вы хотите что-то как глобальные константы; быстрое грязный путь должно поместить объявления константы в pch файл.

11
ответ дан Forge 14 March 2015 в 06:32
поделиться
  • 1
    Да, это - одно возможное решение. Вы зарегистрируете своего делегата приложения как получатель тех уведомлений и обновите переменную (переменные), когда одно из уведомлений будет получено. Тогда в Ваших контроллерах представления Вы могли сделать это MyAppDelegate* myAppDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate] для доступа к переменным. – Andreas 24 June 2012 в 23:46

Как сказанный Abizer, Вы могли выразиться в файл PCH. Иначе это не настолько грязно, должен заставить включать файл для всех Ваших ключей и затем или включать это в файл, Вы используете ключи, или, включаете его в PCH. С ними в их собственном включают файл, который, по крайней мере, дает Вам одно место, чтобы искать и определить все эти константы.

12
ответ дан Grant Limberg 14 March 2015 в 06:32
поделиться

Существует также одна вещь упомянуть. При необходимости в не глобальной константе необходимо использовать static ключевое слово.

Пример

// In your *.m file
static NSString * const kNSStringConst = @"const value";

из-за static ключевое слово, эта константа не видима за пределами файла.

<час>

Незначительное исправление @QuinnTaylor: статические переменные видимы в единица компиляции . Обычно, это - единственный.m файл (как в этом примере), но он может укусить Вас, если Вы объявляете это в заголовке, который включен в другом месте, так как Вы получите ошибки компоновщика после компиляции

189
ответ дан Community 14 March 2015 в 06:32
поделиться

Самый легкий путь:

// Prefs.h
#define PREFS_MY_CONSTANT @"prefs_my_constant"

Лучший путь:

// Prefs.h
extern NSString * const PREFS_MY_CONSTANT;

// Prefs.m
NSString * const PREFS_MY_CONSTANT = @"prefs_my_constant";

Одно преимущество второго - то, что изменение значения константы не вызывает восстанавливание Вашей всей программы.

277
ответ дан Andrew Grant 14 March 2015 в 06:32
поделиться

Попробуйте использовать метод класса:

+(NSString*)theMainTitle
{
    return @"Hello World";
}

Я иногда использую его.

8
ответ дан 19 December 2019 в 20:20
поделиться