그래서 Singleton 인스턴스를 사용하여 핑 (SimplePing 사용)을 만들고 핑 요청 완료 블록을 보유하는 objc 코드가 있습니다. ObjC에서는 다음과 같습니다.
@interface SimplePingClient()
{
NSMutableArray* _currentPings;
NSMutableDictionary* _currentCallbacks;
}
@end
@implementation SimplePingClient
-(id)init
{
if( self = [super init] )
{
_currentPings = [NSMutableArray new];
_currentCallbacks = [NSMutableDictionary new];
}
return self;
}
핑을 시작하는 방법 :
-(void)pingHostname:(NSString*)hostName andResultCallBlock:(void(^)(NSString* latency))result
{
TSimplePing* pingClient = [TSimplePing simplePingWithHostName:hostName];
[_currentPings addObject:pingClient];
[_currentCallbacks setObject:result forKey:[NSValue valueWithNonretainedObject:pingClient]];
pingClient.delegate = self;
//some other irrelevant code
...
}
그리고 SimplePing 대리자 메서드가 호출되면 :
- (void)simplePing:(TSimplePing *)pinger didReceivePingResponsePacket:(NSData *)packet
{
void(^callback)(NSString* latency) = [_currentCallbacks objectForKey:[NSValue valueWithNonretainedObject:pinger]];
if( callback )
{
//some irrelevant code
...
callback(@"123");//hard coded for test, irrelevant code get this value correctly ;)
[_currentCallbacks removeObjectForKey:[NSValue valueWithNonretainedObject:pinger]];
}
[_currentPings removeObject:pinger];
}
따라서이 코드는 objc에서 완벽하게 작동합니다. 그러나 Swift에서 이것을 포팅하려고 할 때 EXC_BAD_ACCESS 오류가 계속 발생합니다. 예제를 단순화하기 위해 나는 모든 것을 지 웠고 Closure를 Dictionary에 저장하고 즉시 호출하면 나를 위해 작동하지 않는다는 것이 밝혀졌습니다.
typealias callbackClosure = (String) -> ()
class SimplePingClient: NSObject
{
// MARK: variables
var _currentPings = [TSimplePing]()
var _currentCallbacks: Dictionary<String, callbackClosure> = [String: callbackClosure]()
private func ping(hostname: String, resultCallback:callbackClosure)
{
var pingClient = TSimplePing(hostName: hostname)
pingClient.delegate = self
_currentPings.append(pingClient)
_currentCallbacks[pingClient.hostName] = resultCallback
if let callback = _currentCallbacks[pingClient.hostName]
{
callback("123213")//here program CRASHES
}
}
}
코드에서 볼 수 있듯이 일부 메모리 문제를 가정하여 NSValue 대신 호스트 이름 (문자열)을 사용하려고 시도하지만 그렇지 않습니다. 여전히 충돌합니다. 그러나이 오류는 확실히 메모리 관리와 관련이 있지만 내가 뭘 잘못하고 있는지 이해할 수 없습니다. 누구든지 내가 놓친 것을 지적 할 수 있다면 나는 그것을 정말로 평가할 것입니다.
@Owen Hartnett가 제안했듯이 여기에 답변 자체에서 솔루션을 이동하고 있습니다.
좋아요, 한 시간 더 디버깅을 한 후에 이유가 꽤 어리석은 것으로 밝혀졌습니다. 내가 내 코드를 포팅한다고 말했듯이 이전에는이 클래스를 브리지 된 목적 -c 코드로 사용 했으므로이 함수는 다음과 같습니다.
-(void)pingHostname:(NSString*)hostName andResultCallBlock:(void(^)(NSString* latency))result
다음과 같은 방식으로 연결되었습니다.
SimplePingClient.pingHostname(latencyUrl, refreshTime: refreshRate) { (latency: String!) -> () in
if nil != latency
{
//dummy code
}
}
따라서 SimplePingClient가 신속한 클래스가 된 후 내 새 클로저 서명은 다음과 같습니다. (이제 대기 시간은 강제로 풀리지 않으며 선택 사항이 아니며 nil에 대해 확인할 필요가 없습니다)
SimplePingClient.pingHostname(latencyUrl, refreshTime: refreshRate) { (latency: String) -> () in
//dummy code
}
그래서 단순히 메서드 호출을 변경함으로써 모든 것이 작동하기 시작했습니다. 컴파일러가이 문제를 알아 차리지 못하는 이상한 점.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다