Я пытаюсь сохранить std :: vector в NSData и обратно напрямую. В своей первой попытке я преобразовал каждую точку в NSValue и сохранил их с помощью NSKeyedUnarchiver, который кажется ужасно неэффективным. Моему тестовому набору данных потребовалось 64 МБ читаемого человеком текста (с NSKeyedUnarchiver), в отличие от преобразования каждого std: vector в NSData, получаемые в результате хранимые файлы — гораздо более разумные 896 КБ. Я делаю следующее для хранения данных:
typedef std::vector<CGPoint> CGContour;
typedef std::vector<std::vector<CGPoint>> CGContours;
static CGContours contoursVector;
contoursVector = CGContours(1024); //Populated with CGContours that are populated with CGPoints datatypes above
//doing the following in a for loop, just showing record 0 for brevity
NSData *contourData([[NSData alloc]
initWithBytesNoCopy: contoursVector[0].data()
length: contoursVector[0].size()
freeWhenDone:false]);
Я могу получить буфер:
const void *buffer = [contourData bytes];
size_t len = [contourData length];
Однако я не могу понять, как заполнить std :: vector указателем буфера const void. Я попытался использовать каждую возможную комбинацию указателя и разыменования, о которой только мог подумать — единственное, что я могу получить для компиляции, это:
contoursVector[0] = *(CGContour *)[contourData bytes];
Если я проверяю вектор CGPoints, они равны 0,0, поэтому ясно, что что-то не так.
РЕДАКТИРОВАТЬ: после реализации предложенного ответа, иногда это работает, в других случаях я получаю EXC_BAD_ACCESS. Вот соответствующий обратный след:
* thread #17: tid = 0x11bf7d4, 0x0000000111607551 libsystem_platform.dylib`_platform_memmove$VARIANT$Ivybridge + 49, queue = 'NSOperationQueue 0x7fa298f51000 :: NSOperation 0x7fa29f3251f0 (QOS: UTILITY)', stop reason = EXC_BAD_ACCESS (code=1, address=0x126e27000)
frame #0: 0x0000000111607551 libsystem_platform.dylib`_platform_memmove$VARIANT$Ivybridge + 49
frame #1: 0x000000010d01890f Foundation`NSCopyMemoryPages + 57
frame #2: 0x000000010cf9b737 Foundation`_NSDataCreateVMDispatchData + 103
frame #3: 0x000000010cf99cf2 Foundation`-[_NSPlaceholderData initWithBytes:length:copy:deallocator:] + 230
frame #4: 0x000000010cfa5902 Foundation`-[NSData(NSData) initWithBytes:length:] + 37
* frame #5: 0x000000010cfeabfb Foundation`+[NSData(NSData) dataWithBytes:length:] + 54
frame #6: 0x000000010c5c998a TDTPhotoLib`storePointData() + 682 at TDTContourImage.mm:562
Странно, но и контуры, и контур, преобразуемый в данные, выглядят корректными в отладчике, и проблема кажется неустойчивой (иногда это работает в других случаях, но не может, но не может сказать, что, если что-то может отличаться)
РЕДАКТИРОВАТЬ 2:
Я могу перебирать каждую точку, но она падает в строке NSData.
NSMutableArray<NSData *> *groupedPointsArrayMain = [NSMutableArray new];
for(const CGContour &contour : contoursVector)
{
if (contour.size() > 0) {
// I am able to iterate over every point and store them this way
NSMutableArray *contourPoints = [NSMutableArray arrayWithCapacity:contour.size()];
for(const CGPoint &point : contour)
{
[contourPoints addObject:[NSValue valueWithCGPoint:point]];
}
//When it crashes, it will crash on this line
//despite it successfully walking over each point
//in the code directly above
NSData *data = [NSData dataWithBytes: contour.data()
length: (contour.size() * cgContourSize)];
[groupedPointsArrayMain addObject:data];
}
}
Нечто подобное должно сработать. Обратите внимание, что я не пытался скомпилировать этот код, так как я нахожусь в Linux atm.
typedef std::vector<CGPoint> CGContour;
typedef std::vector<CGContour> CGContours;
const size_t contourSize = sizeof(CGContour);
NSMutableArray<NSData *> *datas = [NSMutableArray new];
{ // store
CGContours contours(1024);
for(const CGContour &contour : contours)
{
NSData *data = [NSData dataWithBytes: contour.data()
length: contour.size() * contourSize];
[datas addObject:data]
}
}
{ // restore
CGContours contours;
for(NSData *data in datas)
{
const size_t count = [data length] / contourSize;
CGPoint *first = (CGPoint *)[data bytes];
CGPoint *last = first + count;
contours.emplace_back(first, last);
}
}
Других решений пока нет …