【发布时间】:2011-04-23 15:35:09
【问题描述】:
我正在尝试通过蓝牙连接发送文件。
感谢我的previous post,我已经完成了这项工作,但该方法的内存效率不高。
整个文件在发送之前已加载到内存中,这会为 > ~20 MB 的文件带来问题(并使应用程序崩溃)。所以我想出了一种新方法,只在特定时间读取我需要的部分文件,从数据中创建数据包,发送它们并为文件的每个 8KB 块重复该过程。
所以我创建了一个类方法来生成数据包,通知控制器一个数据包可用(通过协议)并为每个可用的数据包重复此过程。
这是数据包生成器的代码:
+ (void)makePacketsFromFile:(NSString *)path withDelegate:(id <filePacketDelegate>)aDelegate {
if (![[NSFileManager defaultManager] fileExistsAtPath:path] || aDelegate == nil) return;
id <filePacketDelegate> delegate;
delegate = aDelegate;
const NSUInteger quanta = 8192;
uint filesize;
NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil];
filesize = [[fileAttributes objectForKey:NSFileSize] intValue];
int numOfPackets = (int)ceil(filesize/quanta);
if (numOfPackets == 0) numOfPackets = 1;
NSLog(@"filesize = %d, numOfPackets = %d or %.3f", filesize, numOfPackets, (float)ceil(filesize/quanta));
NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
int offset = 0;
int counter = 0;
while (counter != (numOfPackets + 1)) {
uint len = (filesize < quanta) ? filesize : quanta;
if (counter == numOfPackets) {
len = filesize - offset;
}
[handle seekToFileOffset:offset];
NSData *fileData = [handle readDataOfLength:len];
file_packet *packet = [[file_packet alloc] initWithFileName:[path lastPathComponent] ofType:0 index:counter];
packet.packetContents = fileData;
[fileData release];
packet.checksum = @"<to be done>";
packet.numberOfPackets = [NSString stringWithFormat:@"%d", numOfPackets];
[delegate packetIsReadyForSending:packet];
[packet release];
offset += quanta;
counter++;
}
[handle closeFile];
}
以及接收和发送文件:
- (void)packetIsReadyForSending:(file_packet *)packet {
NSData *fileData = [packet dataForSending];
[self.connectionSession sendDataToAllPeers:fileData withDataMode:GKSendDataReliable error:nil];
}
- (void)sendFileViaBluetooth {
[file_packet makePacketsFromFile:selectedFilePath withDelegate:self];
}
但是,内存使用量很大。不是我所期望的。
我对此有点坚持,因为我不想将蓝牙共享限制为小于 20MB 的文件。
任何帮助表示赞赏。
编辑:
我一直在考虑这个问题并得出结论,导致内存分配问题的不是我的代码,而是 GameKit 用于发送数据包的堆栈。
我认为我生成的数据包太快了,而且我认为 GameKit 发送它们的速度不够快。
所以我现在正在考虑一种方法来查看 GameKit 何时发送数据包,并且只有在 GameKit 确认已发送后才生成另一个数据包。
【问题讨论】:
标签: iphone objective-c memory-management memory-leaks bluetooth