Я должен сравнить перечисление в целом с одной строкой, таким образом, целое содержание перечисления проверяется.
Требуемый что-то как:
NSString *colString = [[NSString aloc] initWithString:@"threeSilver"];
typedef enum {
oneGreen,
twoBlue,
threeSilver
}numbersAndColours;
if (colString == numbersAndColours) {
//Do cool stuff
}
Но очевидно я не могу сделать этого, возможно, структура... извините, я плохо знаком с C, помогите?
BTW: Я знаю, что NSString не является C, но полагал, что этим вопросом было больше C, чем Obj-C.
Спасибо
Хорошая идея, если
скорость имеет значение
Вас не волнует доступность (программы чтения с экрана, считывающие текст ALT изображения и т.д., все, что пропало при использовании спрайтов)
Вас не волнует, что миниатюры не будут напечатаны по умолчанию в любом браузере
Вы можете сделать это, не став кошмаром обслуживания (Какое изображение снова было на позиции 461?)
Что касается вашего второго вопроса, вероятно, целесообразно поместить все спрайты в одно или очень мало изображений контейнера, чтобы минимизировать время загрузки.
-121--4716585-C, ObjC и C++ не поддерживают это напрямую, необходимо создать явное сопоставление.
Пример использования простого подхода C:
typedef struct {
numbersAndColours num;
const char* const str;
} entry;
#define ENTRY(x) { x, #x }
numberAndColours toNum(const char* const s) {
static entry map[] = {
ENTRY(oneGreen),
ENTRY(twoBlue),
ENTRY(threeSilver)
};
static const unsigned size = sizeof(map) / sizeof(map[0]);
for(unsigned i=0; i<size; ++i) {
if(strcmp(map[i].str, s) == 0)
return map[i].num;
}
return -1; // or some other value thats not in the enumeration
}
#undef ENTRY
// usage:
assert(toNum("oneGreen") == oneGreen);
assert(toNum("fooBar") == -1);
Basic Objective-C:
#define ENTRY(x) [NSNumber numberWithInt:x], @#x
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
ENTRY(oneGreen),
ENTRY(twoBlue),
ENTRY(threeSilver),
nil];
#undef ENTRY
if([dict objectForKey:@"oneGreen"]) {
// ... do stuff
}
-121--4950858- В C для этого необходимо записать функцию. По существу, это будет оператор switch
.
char* colour_of(enum numbersAndColours c)
{
switch( c ) {
case oneGreen:
return "oneGreen";
break;
case twoBlue:
return "twoBlue";
break;
/* ... */
default:
return "donno";
}
}
Функцию можно использовать следующим образом:
{
char* nac;
nac = colour_of(numbersAndColours);
if( strncmp(colString, nac, colStringLen) == 0 )
/* ... */
}
Если colString
не соответствует ни одному из элементов перечисления, она не будет соответствовать numbersAndColours
. Нет необходимости сравнивать его со всеми элементами.
C, OBJC и C ++ не поддерживают это напрямую, вы должны создать явное отображение.
Пример, использующий простые C:
typedef struct {
numbersAndColours num;
const char* const str;
} entry;
#define ENTRY(x) { x, #x }
numberAndColours toNum(const char* const s) {
static entry map[] = {
ENTRY(oneGreen),
ENTRY(twoBlue),
ENTRY(threeSilver)
};
static const unsigned size = sizeof(map) / sizeof(map[0]);
for(unsigned i=0; i<size; ++i) {
if(strcmp(map[i].str, s) == 0)
return map[i].num;
}
return -1; // or some other value thats not in the enumeration
}
#undef ENTRY
// usage:
assert(toNum("oneGreen") == oneGreen);
assert(toNum("fooBar") == -1);
Основной объективный подход:
#define ENTRY(x) [NSNumber numberWithInt:x], @#x
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
ENTRY(oneGreen),
ENTRY(twoBlue),
ENTRY(threeSilver),
nil];
#undef ENTRY
if([dict objectForKey:@"oneGreen"]) {
// ... do stuff
}
Опыт работы с чрезвычайно ограниченной средой встроенной памяти:
Я не видел такого эффекта - я, конечно, никогда не сталкивался с этим как с узким местом.
Вот очень грубый и готовый тест, который показывает (на моей коробке в любом случае) делегаты на самом деле быть быстрее , чем интерфейсы:
using System;
using System.Diagnostics;
interface IFoo
{
int Foo(int x);
}
class Program : IFoo
{
const int Iterations = 1000000000;
public int Foo(int x)
{
return x * 3;
}
static void Main(string[] args)
{
int x = 3;
IFoo ifoo = new Program();
Func<int, int> del = ifoo.Foo;
// Make sure everything's JITted:
ifoo.Foo(3);
del(3);
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
x = ifoo.Foo(x);
}
sw.Stop();
Console.WriteLine("Interface: {0}", sw.ElapsedMilliseconds);
x = 3;
sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
x = del(x);
}
sw.Stop();
Console.WriteLine("Delegate: {0}", sw.ElapsedMilliseconds);
}
}
Результаты (.NET 3,5; .NET 4 .0b2 примерно то же самое):
Interface: 5068
Delegate: 4404
Теперь у меня нет особой веры в то, что это означает, что делегаты действительно быстрее, чем интерфейсы... но это убеждает меня, что они не на порядок медленнее. Кроме того, это практически ничего не делает в рамках метода делегата/интерфейса. Очевидно, что стоимость вызова будет все меньше и меньше различаться, так как вы делаете все больше и больше работы на вызов.
Необходимо быть осторожным в том, что вы не создаете нового делегата несколько раз, где вы бы использовали только один экземпляр интерфейса. Это может вызвать проблему, поскольку это спровоцирует сбор мусора и т.д. Если метод экземпляра используется в качестве делегата в цикле, будет более эффективным объявление переменной делегата вне цикла, создание отдельного делегата и его повторное использование. Например:
Func<int, int> del = myInstance.MyMethod;
for (int i = 0; i < 100000; i++)
{
MethodTakingFunc(del);
}
эффективнее, чем:
for (int i = 0; i < 100000; i++)
{
MethodTakingFunc(myInstance.MyMethod);
}
Могла ли это быть проблема, которую вы видели?
-121--960468- Я не уверен, что понимаю, чего вы пытаетесь достичь, но, возможно, вам захочется взглянуть на NSSet
. Если значение colString
является определенным, кажется, что вы хотите, чтобы ваша программа делала крутые вещи.
NSSet *numbersAndColors = [NSSet setWithObjects:@"oneGreen", @"twoBlue", @"threeSilver", nil];
NSString *colString = [[NSString alloc] initWithString:@"threeSilver"];
if ([numbersAndColors containsObject:colString])
{
// do cool stuff
}
NSSet
быстрее NSSray
, когда нужно знать, существует ли конкретный объект, но один важный аспект NSSet
заключается в том, что он не поддерживает порядок объектов. Как правило, он используется, когда вы не заботитесь о порядке и хотите просто проверить, существует ли объект в наборе.