gpt4 book ai didi

ios - 带上传流的 NSURLSession - 子类化 NSInputStream - com.apple.NSURLConnectionLoader 异常

转载 作者:行者123 更新时间:2023-11-29 12:16:34 37 4
gpt4 key购买 nike

基本任务

我有一些使用某些 C++ 流接口(interface)的多平台库。我必须使用此流接口(interface)通过 NSURLSession 上传数据。我的实现应该在 OS X 和 iOS 上工作(目前我正在 OS X 上测试)

我做了什么

任务看起来很简单,我确信我会很快实现它。我已经配置了 NSURLSession,如果我将 NSURLRequest 与简单的 NSData 一起使用,它可以正常工作。我正在尝试像这样使用流:

        NSURLSessionDataTask *dataTask = [m_Private.session uploadTaskWithStreamedRequest: request];
HTTPDownoadTaskProxy *dataTaskProxy = [HTTPDownoadTaskProxy new];
// store data to properly handle delegate
dataTaskProxy.coreTask = dataTask;
dataTaskProxy.cppRequest= req;
dataTaskProxy.cppResponseHandler = handler;
dataTaskProxy.cppErrorHandler = errorHandler;

m_Private.streamedDataTasks[dataTask] = dataTaskProxy;

[dataTask resume];

到目前为止一切顺利。根据 uploadTaskWithStreamedRequest 的文档,我应该收到委托(delegate)的通知,我确实收到了:

- (void)URLSession: (NSURLSession *)session
task: (NSURLSessionTask *)task
needNewBodyStream: (void (^)(NSInputStream *bodyStream))completionHandler
{
HTTPDownoadTaskProxy *proxyTask = self.streamedDataTasks[task];
CppInputStreamWrapper *objcInputStream = [[CppInputStreamWrapper alloc] initWithCppInputStream:proxyTask.cppRequest.GetDataStream()];
completionHandler(objcInputStream);
}

现在我应该在 NSInputStream 的子类中接收调用,在我的例子中是 CppInputStreamWrapper,而且它非常简单:

@implementation CppInputStreamWrapper

- (void)dealloc {
NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (instancetype)initWithCppInputStream: (const std::tr1::shared_ptr<IInputStream>&) cppInputStream
{
if (self = [super init]) {
_cppInputStream = cppInputStream;
}
return self;
}

#pragma mark - overrides for NSInputStream
- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len {
return (NSInteger)self.cppInputStream->Read(buffer, len);
}

- (BOOL)getBuffer:(uint8_t **)buffer length:(NSUInteger *)len {
return NO;
}

- (BOOL)hasBytesAvailable {
return !self.cppInputStream->IsEOF();
}

#pragma mark - this methods are need to be overridden to make stream working
- (void)scheduleInRunLoop:(__unused NSRunLoop *)aRunLoop
forMode:(__unused NSString *)mode
{}

- (void)removeFromRunLoop:(__unused NSRunLoop *)aRunLoop
forMode:(__unused NSString *)mode
{}

#pragma mark - Undocumented CFReadStream Bridged Methods
- (void)_scheduleInCFRunLoop:(__unused CFRunLoopRef)aRunLoop
forMode:(__unused CFStringRef)aMode
{}

- (void)_unscheduleFromCFRunLoop:(__unused CFRunLoopRef)aRunLoop
forMode:(__unused CFStringRef)aMode
{}

- (BOOL)_setCFClientFlags:(__unused CFOptionFlags)inFlags
callback:(__unused CFReadStreamClientCallBack)inCallback
context:(__unused CFStreamClientContext *)inContext {
return NO;
}

@end

所以我在子类化 NSInputStream 时使用了所需的解决方法。

问题

现在应该可以了。但是我没有收到任何对 CppInputStreamWrapper 方法的调用(构造对象时调用除外)。

没有错误没有警告报告,什么都没有!

当我添加异常断点时我正在捕获

thread #8: tid = 0x155cb3, 0x00007fff8b770743 libobjc.A.dylib`objc_exception_throw, name = 'com.apple.NSURLConnectionLoader', stop reason = breakpoint 1.1

这来 self 没有创建的线程 com.apple.NSURLConnectionLoader

我很困惑,不知道我还能做什么。

更新

我使用了代码形式 link in comment这是 hosted on github .现在至少我的类的某些部分由框架调用,但我看到奇怪的崩溃。

Crash位于这个方法中:

- (BOOL)_setCFClientFlags:(CFOptionFlags)inFlags
callback:(CFReadStreamClientCallBack)inCallback
context:(CFStreamClientContext *)inContext {

if (inCallback != NULL) {
requestedEvents = inFlags;
copiedCallback = inCallback;
memcpy(&copiedContext, inContext, sizeof(CFStreamClientContext));

if (copiedContext.info && copiedContext.retain) {
copiedContext.retain(copiedContext.info);
}

copiedCallback((__bridge CFReadStreamRef)self, kCFStreamEventHasBytesAvailable, &copiedContext); // CRASH HERE
} else {
requestedEvents = kCFStreamEventNone;
copiedCallback = NULL;
if (copiedContext.info && copiedContext.release) {
copiedContext.release(copiedContext.info);
}

memset(&copiedContext, 0, sizeof(CFStreamClientContext));
}

return YES;

}

崩溃是 EXC_BAD_ACCESS(在 OS X 上运行测试时)。当我看到这段代码时,一切看起来都很好。它应该工作! self 指向保留计数为 3 的正确对象,所以我不知道它为什么会崩溃。

最佳答案

未记录的私有(private)桥接 API 并不是自定义 NSInputStream 实现中的唯一问题,尤其是在 CFNetworking 集成的上下文中。我想推荐使用我的 POSInputStreamLibrary作为基本构建 block 。与其实现大量 NSInputStream 方法并支持异步通知,不如实现更简单的 POSBlobInputStreamDataSource界面。至少你可以看看POSBlobInputStream咨询你应该实现什么样的功能来完全支持 NSInputStream 契约(Contract)。

POSInputStreamLibrary用于最流行的俄罗斯云存储服务Cloud Mail.Ru每天上传超过 100 万个文件,没有任何崩溃。

祝您好运,如有任何问题,请随时提出。

关于ios - 带上传流的 NSURLSession - 子类化 NSInputStream - com.apple.NSURLConnectionLoader 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31837909/

37 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com