следующий код работал для меня
@interface TopAlignedCollectionViewFlowLayout : UICollectionViewFlowLayout
- (void)alignToTopForSameLineElements:(NSArray *)sameLineElements;
@end
@implementation TopAlignedCollectionViewFlowLayout
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect;
{
NSArray *attrs = [super layoutAttributesForElementsInRect:rect];
CGFloat baseline = -2;
NSMutableArray *sameLineElements = [NSMutableArray array];
for (UICollectionViewLayoutAttributes *element in attrs) {
if (element.representedElementCategory == UICollectionElementCategoryCell) {
CGRect frame = element.frame;
CGFloat centerY = CGRectGetMidY(frame);
if (ABS(centerY - baseline) > 1) {
baseline = centerY;
[self alignToTopForSameLineElements:sameLineElements];
[sameLineElements removeAllObjects];
}
[sameLineElements addObject:element];
}
}
[self alignToTopForSameLineElements:sameLineElements];//align one more time for the last line
return attrs;
}
- (void)alignToTopForSameLineElements:(NSArray *)sameLineElements
{
if (sameLineElements.count == 0) {
return;
}
NSArray *sorted = [sameLineElements sortedArrayUsingComparator:^NSComparisonResult(UICollectionViewLayoutAttributes *obj1, UICollectionViewLayoutAttributes *obj2) {
CGFloat height1 = obj1.frame.size.height;
CGFloat height2 = obj2.frame.size.height;
CGFloat delta = height1 - height2;
return delta == 0. ? NSOrderedSame : ABS(delta)/delta;
}];
UICollectionViewLayoutAttributes *tallest = [sorted lastObject];
[sameLineElements enumerateObjectsUsingBlock:^(UICollectionViewLayoutAttributes *obj, NSUInteger idx, BOOL *stop) {
obj.frame = CGRectOffset(obj.frame, 0, tallest.frame.origin.y - obj.frame.origin.y);
}];
}
@end
C99 имеет отличную инициализацию структуры любого порядка. Конечно, вы не можете применить его к шаблону C ++. Вы также не можете применить его к методам класса (потому что метод класса должен знать, для какого объекта он был вызван, а связь в стиле C не имеет никакого способа передать эту информацию функции).
Это возможно применить extern «C»
к функциям, которые существуют в пространстве имен, но информация о пространстве имен просто исчезнет при использовании через C.
Если у вас уже есть класс (мы будем использовать класс POD для простоты), и вы хотите, чтобы его можно было использовать из C, вам нужно применить extern «C»
к функции, вызываемой в C К сожалению, это становится некрасивым даже в простых случаях:
// in the header file
#ifdef __cplusplus
namespace X {
#endif
struct A
{
int x;
#ifdef __cplusplus
A() : x(5) { }
int foo()
{
return x += 5;
}
#endif
};
#ifdef __cplusplus
extern "C" {
#endif
int A_foo(struct A a);
struct A A_create();
#ifdef __cplusplus
}
}
#endif
// in the .cc file
#include "try.h"
namespace X {
extern "C" {
int A_foo(A* a)
{
return a.foo();
}
A A_create()
{
return A();
}
}
}
// in the .c file
#include <stdio.h>
#include "try.h"
int main()
{
struct A a = A_create();
printf("%d", A_foo(a));
}
Используя gcc, вы бы скомпилировали это следующим образом:
g ++ try.cc -c -o try.o
Чтобы вызвать деструктор явно:
extern "C" void A_destroy(struct A a)
{
a.~A();
}
extern "c" использует связывание в стиле c; то есть необработанное имя функции - это то, что отображается из библиотеки. Поскольку это просто необработанное имя функции, ни одна из функций C ++ не будет работать с ней, включая методы или внешние данные-члены в пространствах имен, классах, структурах или объединениях.
Уточнение : Структуры и объединения находятся в C , но не имеют функций-членов, поэтому их функции-члены в C ++ нельзя экспортировать в стиле c (а определения структуры и объединения не нужно экспортировать, поскольку они уже находятся в заголовке)
Боюсь, что нет. Но если вы хотите передать объект C ++ в функции C, вы можете обратиться к этой ссылке: http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html# faq-32.8
Ммм ... extern "C"
принудительно устанавливает связь в стиле C. Его нельзя использовать с классами AFAIK.
Вы можете вроде как применить extern "C"
к функции-члену с помощью очень запутанного (но полностью легального) хака:
extern "C" typedef int bar_t(int x);
struct foo {
bar_t bar; // yes, this declares a nonstatic member function!
};
int foo::bar(int x) { return x; } // definition
Это возможно согласно ISO C++03 9.3[class.mfct]/9:
функция-член может быть объявлена (но не определена) с помощью typedef для типа функции. Результирующая функция-член имеет точно такой же тип, как если бы декларатор функции был представлен явно, см. 8.3.5.
Однако на самом деле это ничего не дает, так как в ISO C++03 7.5[dcl.link]/4:
Синхронизация языка Си игнорируется для имен членов класса и функции-члена тип функций члена класса.