1

Id welcome any help unarchiving an NSArray of UIBezierPaths from NSData. I want to use the NSArray container to hold some UIBezierPaths which I can persist to Core Data as an NSData property in my entity (rather than persist them individually, which Ive done elsewhere in this project).

  1. I am able to archive and unarchive a single UIBezierPath without putting it in an array (example 1 below)
  2. Im also able to archive and unarchive an array of NSStrings in the NSArray (example 2 below) (just to illustrate that I can archive and unarchive using an array container)

However,

  1. When I put a UIBezierPath in an NSArray, Im getting UNARCHIVED Object = (null) CLASS: (null) in the console. (example 3 below) Ive put some of the console output from this example at the bottom of this question.

I feel I should be using [NSKeyedUnarchiver unarchivedObjectOfClass:fromData:error:] (rather than the deprecated methods) and Ive searched all the posts I can find on [NSKeyedUnarchiver unarchivedObjectOfClass:] but I haven't been able to work it out.

Im pretty stuck on this and I feel Im missing something basic, so any steer is welcome

Many thanks

    //1. WORKS ===================
    UIBezierPath* p = [_pathManager.Paths objectAtIndex:1];
    NSLog(@"Path: %@", p);

    NSError* error = nil;
    NSData *obj = [NSKeyedArchiver archivedDataWithRootObject:p requiringSecureCoding:YES error:&error];
    NSLog(@"    NS DATA: %@", obj);

    NSError *error1;
    UIBezierPath* arr = [NSKeyedUnarchiver unarchivedObjectOfClass:[UIBezierPath class] fromData:obj error:&error1];
    NSLog(@"    UNARCHIVED Object = %@ CLASS: %@", arr, [arr  class] );



    //2. ALSO WORKS - archiving and unarchiving NSStrings in an NSArray
    NSError* error = nil;
    NSArray* arr1 = [[NSArray alloc]initWithObjects:@"Test1",@"Test2",nil];
    NSLog(@"    ARRAY: %@", arr1);

    NSData *obj = [NSKeyedArchiver archivedDataWithRootObject:arr1 requiringSecureCoding:YES error:&error];
    NSLog(@"    NS DATA: %@", obj);

    NSError *error1;
    NSArray* arr = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSArray class] fromData:obj error:&error1];
    NSLog(@"    UNARCHIVED Object = %@ CLASS: %@", arr, [arr  class] );




    //3. DOESNT WORK - console returns UNARCHIVED Object = (null) CLASS: (null)

    UIBezierPath* p = [_pathManager.Paths objectAtIndex:1];
    NSLog(@"Path: %@", p);


    NSError* error = nil;
    NSArray* arr1 = [[NSArray alloc]initWithObjects: p , nil];
    NSLog(@"    ARRAY: %@", arr1);

    NSData *obj = [NSKeyedArchiver archivedDataWithRootObject:arr1 requiringSecureCoding:YES error:&error];
    NSLog(@"    NS DATA: %@", obj);

    NSError *error1;
    NSArray* arr = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSArray class] fromData:obj error:&error1];
    NSLog(@"    UNARCHIVED Object = %@ CLASS: %@", arr, [arr  class] );

Sample Console output below:

2020-06-13 12:27:29.236477+0100 PROJ[24718:931062] Path: <UIBezierPath: 0x60000560de60; <MoveTo {6321, 4648}>,
 <MoveTo {6334.5377384528101, 4651.0555672716337}>,
 <CurveTo {6338.0387705020785, 4653.1006231477277} {6335.121243794355, 4651.3964099176492} {6336.862553352169, 4652.4247805556097}>,
 <CurveTo {6341.5950413522669, 4655.1106228243434} {6339.2149876519879, 4653.7764657398457} {6340.4053789767258, 4654.4454254015836}>,
..... etc....
<CurveTo {6427.7455441302509, 4702.2045296954602} {6425.1616837301008, 4701.18468119315} {6427.1089369371202, 4701.9410553993894}>,
 <LineTo {6446.3401401523624, 4712.478597704282}>
2020-06-13 12:27:29.247213+0100 PROJ[24718:931062]     ARRAY: (
    "<UIBezierPath: 0x60000560de60; <MoveTo {6321, 4648}>,\n <MoveTo {6334.5377384528101, 4651.0555672716337}>,\n <CurveTo {6338.0387705020785, 4653.1006231477277} {6335.121243794355, 4651.3964099176492} {6336.862553352169, 4652.4247805556097}>,\n <CurveTo {6341.5950413522669, 4655.1106228243434} {6339.2149876519879, 4653.7764657398457} {6340.4053789767258, 4654.4454254015836}>,\n 
..... etc....
<CurveTo {6427.7455441302509, 4702.2045296954602} {6425.1616837301008, 4701.18468119315} {6427.1089369371202, 4701.9410553993894}>,\n <LineTo {6446.3401401523624, 4712.478597704282}>"
)
2020-06-13 12:27:29.247942+0100 PROJ[24718:931062]     NS DATA: {length = 1614, bytes = 0x62706c69 73743030 d4010203 04050607 ... 00000000 000005c0 }
2020-06-13 12:27:29.248213+0100 PROJ[24718:931062]     UNARCHIVED Object = (null) CLASS: (null)

MiltsInit
  • 153
  • 7
  • 1
    what do you get in error1? – chunkyguy Jun 13 '20 at 23:50
  • Hi - logging the error for scenario 3 using NSLog(@"Error1: %@ %@", error1, [error userInfo]); gives: 2020-06-14 11:34:51.045186+0100 PROJ[27555:1192633] Error1: Error Domain=NSCocoaErrorDomain Code=4864 "value for key 'NS.objects' was of unexpected class 'UIBezierPath'. Allowed classes are '{( NSArray )}'." UserInfo={NSDebugDescription=value for key 'NS.objects' was of unexpected class 'UIBezierPath'. Allowed classes are '{( NSArray )}'.} (null) – MiltsInit Jun 14 '20 at 10:37
  • 1
    And did you try using the older way, without secure coding. Just trying to rule out if secure coding is not correctly set. In my experience, secure coding is more strict than the older way. – chunkyguy Jun 14 '20 at 12:40
  • yes - if i use NSArray* arr = [NSKeyedUnarchiver unarchiveObjectWithData:obj]; to unarchive the NSData object I get UNARCHIVED Object = ( ",\n .... etc.....{,\n " ) CLASS: __NSSingleObjectArrayI 2020-06-14 17:27:17.084979+0100 VIE2020[29004:1299025] Error1: (null) (null) .....which clearly works (even though its deprecated) – MiltsInit Jun 14 '20 at 16:30
  • ...I also tried setting the archiver (in [NSKeyedArchiver archivedDataWithRootObject:arr1 requiringSecureCoding:YES error:&error];) to requiringSecureCoding:NO, but that didnt work either. – MiltsInit Jun 14 '20 at 16:32
  • 1
    Hi firstly thank you for making to time to look at this problem. Id also posted it to Reddit and have just received an answer that appears to work: NSSet *allowedClasses = [NSSet setWithObjects:[NSArray class],[UIBezierPath class], nil]; [NSKeyedUnarchiver unarchivedObjectOfClasses:allowedClasses fromData:archiveData error:&unArchiveError]; – MiltsInit Jun 14 '20 at 19:57
  • 1
    Hi firstly chunkyguy thank you for making to time to look at this problem - I very much appreciate your help. Id also posted to Reddit and have just received an answer that appears to work, namely - declare an NSSet of the expected types: NSSet *allowedClasses = [NSSet setWithObjects:[NSArray class],[UIBezierPath class], nil]; then use a different unarchiving function: [NSKeyedUnarchiver unarchivedObjectOfClasses:allowedClasses fromData:archiveData error:&error1]; Using this approach, the console shows the expected unarchived array and the error messaging is Error1: (null) (null) – MiltsInit Jun 14 '20 at 20:06

0 Answers0