Хотя C "близок" к управлению низкого уровня 8-разрядными, 16-разрядными, 32-разрядными, 64-разрядными данными, существует несколько математических операций, не поддерживаемых C, который может часто выполняться изящно в определенных наборах инструкции по сборке:
умножение Фиксированной точки: продуктом двух 16-разрядных чисел является 32-разрядное число. Но в правилах в C говорится, что продуктом двух 16-разрядных чисел является 16-разрядное число, и продуктом двух 32-разрядных чисел является 32-разрядное число - нижняя половина в обоих случаях. Если Вы хотите вершина , половина 16x16 умножается, или 32x32 умножаются, необходимо играть в игры с компилятором. Общий метод состоит в том, чтобы бросить к большей-,-чем-необходимый разрядной ширине, умножиться, сдвиг вниз, и вспомнить:
int16_t x, y;
// int16_t is a typedef for "short"
// set x and y to something
int16_t prod = (int16_t)(((int32_t)x*y)>>16);`
В этом случае компилятор может быть достаточно умным, чтобы знать, что Вы действительно просто пытаетесь добраться, верхняя половина 16x16 умножают и делают правильную вещь с собственным компонентом машины 16x16multiply. Или это может быть глупо и потребовать, чтобы вызов библиотеки, чтобы сделать 32x32 умножился, это - путь излишество, потому что Вам только нужны 16 битов продукта - но стандарт C не дает Вам способа выразиться.
Certain bitshifting операции (вращение/нести):
// 256-bit array shifted right in its entirety:
uint8_t x[32];
for (int i = 32; --i > 0; )
{
x[i] = (x[i] >> 1) | (x[i-1] << 7);
}
x[0] >>= 1;
Это не слишком неэлегантно в C, но снова, если компилятор не достаточно умен для понимания то, что Вы делаете, он собирается сделать большую "ненужную" работу. Много наборов инструкции по сборке позволяют Вам вращаться или смещаться слева/справа с результатом в регистре переноса, таким образом, Вы могли выполнить вышеупомянутое в 34 инструкциях: загрузите указатель на начало массива, очистите перенос и выполните 32 8-разрядных сдвига вправо, с помощью автоинкремента на указателе.
Для другого примера, существуют линейные сдвиговые регистры обратной связи (LFSR), которые изящно выполняются в блоке: Возьмите блок битов N (8, 16, 32, 64, 128, и т.д.), сместите все это прямо на 1 (см. выше алгоритма), затем если получающийся перенос равняется 1 затем Вы XOR в небольшом шаблоне, который представляет многочлен.
Однако я не обратился бы к этим методам, если у меня не было серьезных ограничений производительности. Как другие сказали, блок намного более трудно зарегистрировать/отладить/тестировать/поддержать, чем код C: увеличение производительности идет с некоторыми серьезными затратами.
редактирование: 3. Водосливное обнаружение возможно в блоке (не может действительно сделать этого в C), это делает некоторые алгоритмы намного легче.
Из этого туториала Вы узнаете все современное решение iOS 5, от процесса создания файлов xib и классов ячейки до самого конца:
Лично я думаю, что оба предложенных урока имеют большой недостаток, когда дело доходит до reuseIdentifier
. Если вы забыли назначить его в конструкторе интерфейсов или неправильно написали его, вы будете загружать перо каждый раз, когда вызывается cellForRowAtIndexPath
.
Джефф Ламарш пишет об этом и как это исправить в этом сообщении в блоге . Помимо reuseIdentifier
он использует тот же подход, что и в документации Apple по Загрузка пользовательских ячеек табличного представления из файлов пера .
После прочтения всех этих статей я придумал следующий код:
Редактировать: если вы ориентируетесь на iOS 5.0 и выше, вам нужно придерживаться Duane Fields 'answer
@interface CustomCellWithXib : UITableViewCell
+ (NSString *)reuseIdentifier;
- (id)initWithOwner:(id)owner;
@end
@implementation CustomCellWithXib
+ (UINib*)nib
{
// singleton implementation to get a UINib object
static dispatch_once_t pred = 0;
__strong static UINib* _sharedNibObject = nil;
dispatch_once(&pred, ^{
_sharedNibObject = [UINib nibWithNibName:NSStringFromClass([self class]) bundle:nil];
});
return _sharedNibObject;
}
- (NSString *)reuseIdentifier
{
return [[self class] reuseIdentifier];
}
+ (NSString *)reuseIdentifier
{
// return any identifier you like, in this case the class name
return NSStringFromClass([self class]);
}
- (id)initWithOwner:(id)owner
{
return [[[[self class] nib] instantiateWithOwner:owner options:nil] objectAtIndex:0];
}
@end
UINib (доступный в iOS 4.0 и более поздних версиях) используется здесь как одиночный, потому что, хотя используется reuseIdentifier
, ячейка все еще повторно инициализируется о 10 раз или около того. Теперь cellForRowAtIndexPath
выглядит так:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCellWithXib *cell = [tableView dequeueReusableCellWithIdentifier:[CustomCellWithXib reuseIdentifier]];
if (cell == nil) {
cell = [[CustomCellWithXib alloc] initWithOwner:self];
}
// do additional cell configuration
return cell;
}
Вы можете создать класс CustomCell с XIB, который унаследован от UITableViewCell. Мы просто добавим категорию в .m файл класса tableview следующим образом. Я думаю, что это самый простой метод, который можно применять для создания пользовательских ячеек.
@interface UITableViewCell(NIB) @property(nonatomic,readwrite,copy) NSString *reuseIdentifier; @end - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 30; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *identifier=@"cell"; CustomCell *cell=[tableView dequeueReusableCellWithIdentifier:identifier]; if(cell==nil) { NSLog(@"New Cell"); NSArray *nib=[[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil]; cell=[nib objectAtIndex:0]; cell.reuseIdentifier=identifier; }else{ NSLog(@"Reuse Cell"); } cell.lbltitle.text=[NSString stringWithFormat:@"Level %d",indexPath.row]; id num=[_arrslidervalues objectAtIndex:indexPath.row]; cell.slider.value=[num floatValue]; return cell; } @end