我使用NSInputstream& NSOutputstream用于设置连接和发送数据.我的流对象具有打开和关闭流的功能.我使用以下代码:
@interface Stream()
{
NSInputStream *inputStream;
NSOutputStream *outputStream;
}
-(id)init
{
self = [super init];
if (self)
{
inputStream = nil;
outputStream = nil;
}
return self;
}
-(int)streamOpenWithIp:(Nsstring *)ip withPortNumber:(int)portNumber;
{
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(kcfAllocatorDefault,(__bridge CFStringRef)ip,portNumber,&readStream,&writeStream);
if(readStream && writeStream)
{
//Setup inpustream
inputStream = (__bridge NSInputStream *)readStream;
[inputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
//Setup outputstream
outputStream = (__bridge NSOutputStream *)writeStream;
[outputStream setDelegate:self];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream open];
}
}
- (int)streamClose;
{
CFReadStreamSetProperty((__bridge CFReadStreamRef)(inputStream),kcfStreamPropertyShouldCloseNativeSocket,kcfBooleanTrue);
CFReadStreamSetProperty((__bridge CFReadStreamRef)(outputStream),kcfBooleanTrue);
//Close and reset inputstream
[inputStream setDelegate:nil];
[inputStream close];
[inputStream removeFromrunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
inputStream = nil;
//Close and reset outputstream
[outputStream setDelegate:nil];
[outputStream close];
[outputStream removeFromrunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
outputStream = nil;
}
当我多次打开和关闭流时,此代码工作正常.当我使用Instruments检查我的应用程序内存泄漏时,它说CFStreamCreatePairWithSocketToHost函数泄漏了72%的内存.有人知道我做错了什么吗?我无法弄明白.
解决方法
添加CFRelease((CFStreamRef)inputStream);和CFRelease((CFStreamRef)outputStream);在streamClose方法中.
当CFStreamCreatePairWithSocketToHost返回时,readStream和writeStream的所有权将传递给您:
Ownership follows the Create Rule in Memory Management Programming Guide for Core Foundation.
即使使用ARC,也需要明确释放Core Foundation对象:
The compiler does not automatically manage the lifetimes of Core Foundation objects; you must call CFRetain and CFRelease (or the corresponding type-specific variants) as dictated by the Core Foundation memory management rules (see Memory Management Programming Guide for Core Foundation).
或者,更改此行(以及outputStream的相应行):
inputStream = (__bridge NSInputStream *)readStream;
至:
inputStream = (__bridge_transfer NSInputStream *)readStream;
这是因为readStream具有ARC未知的优秀保留计数.通过给ARC指定此指针的所有权,您授予它在适当时间释放指针的权限.进一步阅读:1,2