将NSMutableArray转换为字符串并返回

时间:2010-03-30 02:11:25

标签: iphone nsmutablearray nsarray

在我目前的项目中,我遇到了以下问题:

应用程序需要与我的服务器交换数据,这些数据存储在iPhone上的NSMutableArray中。该数组包含NSString,NSData和CGPoint值。 现在,我认为最简单的方法是将数组转换为格式正确的字符串,将其发送到我的服务器并将其存储在一些mySQL数据库中。此时我想从我的服务器请求表示我的数组内容的字符串,然后实际将其转换回NSMutablArray。

到目前为止,我尝试过这样的事情:

NSString *myArrayString = [myArray description];

现在我将此字符串发送到我的服务器并将其存储在mySQL数据库中。那部分效果很好。

但是,当我从服务器收到字符串时,我无法将其转换回NSMutableArray。

是否有方法可以轻松地将数组描述转换回数组?不幸的是到目前为止我找不到任何东西。 也许我从一开始就“序列化”数组的方式是错误的,并且有一种更聪明的方法可以做到这一点。

任何帮助表示赞赏。提前谢谢。

2 个答案:

答案 0 :(得分:4)

不要使用description,因为这是为了让它变成人类可读的“漂亮”格式。你想要的是对象的数据转储。

您可能想要做的是利用NSArray执行NSCoding以从中获取原始字节数组的事实 - NSData。 (这是您提到的序列化。)然后,您可以将原始字节传输到服务器,使用zip压缩,或者对base-64中的字节进行编码,以通过HTTP发送查询字符串。要恢复数组,您只需撤消该过程。

Stack Overflow上有很多现有的问题和答案可以帮助您解决这个问题。这是一对夫妇:

How to convert NSArray to NSData?

Converting NSData to base64

答案 1 :(得分:0)

好吧,我想我离得更近了。但是,我还没到那里,因为在将数据转换回新数组时遇到了一些“EXC_BAD_ACCESS”。

让我与您分享一些代码。以下是应该将数组转换为NSData,将NSData转换为base64,反之亦然。

@interface NSArray (dataConversion)
    + (NSArray*) arrayWithData:(NSData*) data;
    - (NSData*) convertToData;
@end

@implementation NSArray (dataConversion)


- (NSData*) convertToData {
    unsigned n= [self count]; 
NSMutableData* data = [NSMutableData dataWithLength: sizeof(unsigned)+
                       sizeof(id) *n];
unsigned* p = [data mutableBytes];
*p++= n;
[self getObjects:(void*)p];
return data;
}

+ (NSArray*) arrayWithData:(NSData*) data {
unsigned* p = (unsigned*)[data bytes];
unsigned n = *p++;
return [NSArray arrayWithObjects:(id*)p count:n];
}

@end

@interface NSData (MBBase64)

+ (id)dataWithBase64EncodedString:(NSString *)string;     //  Padding '=' characters are     optional. Whitespace is ignored.
- (NSString *)base64Encoding;
@end


static const char encodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";


@implementation NSData (MBBase64)

+ (id)dataWithBase64EncodedString:(NSString *)string;
{
if (string == nil)
    [NSException raise:NSInvalidArgumentException format:nil];
if ([string length] == 0)
    return [NSData data];

static char *decodingTable = NULL;
if (decodingTable == NULL)
{
    decodingTable = malloc(256);
    if (decodingTable == NULL)
        return nil;
    memset(decodingTable, CHAR_MAX, 256);
    NSUInteger i;
    for (i = 0; i < 64; i++)
        decodingTable[(short)encodingTable[i]] = i;
}

const char *characters = [string cStringUsingEncoding:NSASCIIStringEncoding];
if (characters == NULL)     //  Not an ASCII string!
    return nil;
char *bytes = malloc((([string length] + 3) / 4) * 3);
if (bytes == NULL)
    return nil;
NSUInteger length = 0;

NSUInteger i = 0;
while (YES)
{
    char buffer[4];
    short bufferLength;
    for (bufferLength = 0; bufferLength < 4; i++)
    {
        if (characters[i] == '\0')
            break;
        if (isspace(characters[i]) || characters[i] == '=')
            continue;
        buffer[bufferLength] = decodingTable[(short)characters[i]];
        if (buffer[bufferLength++] == CHAR_MAX)      //  Illegal character!
        {
            free(bytes);
            return nil;
        }
    }

    if (bufferLength == 0)
        break;
    if (bufferLength == 1)      //  At least two characters are needed to produce one byte!
    {
        free(bytes);
        return nil;
    }

    //  Decode the characters in the buffer to bytes.
    bytes[length++] = (buffer[0] << 2) | (buffer[1] >> 4);
    if (bufferLength > 2)
        bytes[length++] = (buffer[1] << 4) | (buffer[2] >> 2);
    if (bufferLength > 3)
        bytes[length++] = (buffer[2] << 6) | buffer[3];
}

realloc(bytes, length);
return [NSData dataWithBytesNoCopy:bytes length:length];
}

- (NSString *)base64Encoding;
{
if ([self length] == 0)
    return @"";

char *characters = malloc((([self length] + 2) / 3) * 4);
if (characters == NULL)
    return nil;
NSUInteger length = 0;

NSUInteger i = 0;
while (i < [self length])
{
    char buffer[3] = {0,0,0};
    short bufferLength = 0;
    while (bufferLength < 3 && i < [self length])
        buffer[bufferLength++] = ((char *)[self bytes])[i++];

    //  Encode the bytes in the buffer to four characters, including padding "=" characters if necessary.
    characters[length++] = encodingTable[(buffer[0] & 0xFC) >> 2];
    characters[length++] = encodingTable[((buffer[0] & 0x03) << 4) | ((buffer[1] & 0xF0) >> 4)];
    if (bufferLength > 1)
        characters[length++] = encodingTable[((buffer[1] & 0x0F) << 2) | ((buffer[2] & 0xC0) >> 6)];
    else characters[length++] = '=';
    if (bufferLength > 2)
        characters[length++] = encodingTable[buffer[2] & 0x3F];
    else characters[length++] = '=';    
}

return [[[NSString alloc] initWithBytesNoCopy:characters length:length encoding:NSASCIIStringEncoding freeWhenDone:YES] autorelease];
}

@end

现在,我这样使用它:

NSData *messageData = [[NSArray arrayWithArray:myNSMutableArray] convertToData];
NSString *messageData = [messageData base64Encoding];

messageData是我现在发送到服务器的字符串。这很好。

现在反过来了:

NSData *arrayData = [NSData dataWithBase64EncodedString:serverResponseString]; //serverResponseString is the string returned from my server upon request

NSMutableArray *newArray = [[NSMutableArray alloc] initWithArray:[NSArray arrayWithData:arrayData]]; //here it crashes and points to: "return [NSArray arrayWithObjects:(id*)p count:n];"

我要么在这里丢失一些东西,要么完全偏离轨道。任何帮助赞赏。感谢。