Swift의 무료 브리징 및 포인터 액세스
-
21-12-2019 - |
문제
Objective-C에서 Swift로 앱을 포팅하려고 하는데 다음 방법을 사용해야 합니다.
CFStreamCreatePairWithSocketToHost(alloc: CFAllocator!, host: CFString!, port: UInt32, \
readStream: CMutablePointer<Unmanaged<CFReadStream>?>, \
writeStream: CMutablePointer<Unmanaged<CFWriteStream>?>)
이전 논리는 다음과 같습니다(여러 웹 사이트가 이에 동의하는 것으로 보입니다).
CFReadStreamRef readStream = NULL;
CFWriteStreamRef writeStream = NULL;
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)(host), port, \
&readStream, &writeStream);
NSInputStream inputStream = (__bridge_transfer NSInputStream *)readStream;
NSOutputStream outputStream = (__bridge_transfer NSOutputStream *)writeStream;
무료 브리징 덕분에 잘 작동합니다.그러나 "Swift-space"에는 ARC가 존재하지 않으며 유형 체계가 변경되었습니다.
내 스트림을 인스턴스로 어떻게 바꾸나요?
CMutablePointer<Unmanaged<CFReadStream>?>, and
CMutablePointer<Unmanaged<CFWriteStream>?>
그런 다음 다시 변환하십시오. NSStream
이후의 서브클래스 CFStreamCreatePairWithSocketToHost
부르다?
해결책
나는 일하러 가고, 내 코드가있다. 연결 클래스를 어딘가에 보관하십시오 : -)
class Connection : NSObject, NSStreamDelegate {
let serverAddress: CFString = "127.0.0.1"
let serverPort: UInt32 = 8443
private var inputStream: NSInputStream!
private var outputStream: NSOutputStream!
func connect() {
println("connecting...")
var readStream: Unmanaged<CFReadStream>?
var writeStream: Unmanaged<CFWriteStream>?
CFStreamCreatePairWithSocketToHost(nil, self.serverAddress, self.serverPort, &readStream, &writeStream)
// Documentation suggests readStream and writeStream can be assumed to
// be non-nil. If you believe otherwise, you can test if either is nil
// and implement whatever error-handling you wish.
self.inputStream = readStream!.takeRetainedValue()
self.outputStream = writeStream!.takeRetainedValue()
self.inputStream.delegate = self
self.outputStream.delegate = self
self.inputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
self.outputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
self.inputStream.open()
self.outputStream.open()
}
func stream(stream: NSStream, handleEvent eventCode: NSStreamEvent) {
println("stream event")
}
}
. 다른 팁
다른 사람들 이이 스레드에서 일하기 위해 다른 사람들이 제공 한 예제를 얻을 수 없었습니다.물론 그들은 컴파일되었지만, 연결이 열려 자마자 충돌했습니다.
그러나 WWDC 2014 토론 (및 IOS 8 릴리스 노트)에서 NSStream을 in / out 스트림의 바운드 쌍을 생성하기 위해 NSStream을 초기화하는 새로운 방법이 있다는 것을 알아 차렸다.
아래를 참조하십시오 :
var inputStream: NSInputStream?
var outputStream: NSOutputStream?
NSStream.getStreamsToHostWithName("localhost", port: 1234, inputStream: &inputStream, outputStream: &outputStream)
.
이것은 어색한 CFSTREAMCREATEPARWITHSockEttoHost 호출의 필요성을 제거하고 관리되지 않는 자원의 필요성을 제거합니다.
나는 그것을하는 방법을 알아 냈습니다.몇 가지 중요한 참고사항:
CMutablePointers
& 연산자를 사용하면 자동으로 생성됩니다.- 에서 받으실 수 있습니다.
T
에Unmanaged<T>
~와 함께.getUnretainedValue()
그리고getRetainedValue()
(아마도.getUnretainedValue()
와 유사하다__bridge_transfer
) - 옵션은 자동으로 초기화됩니다.
nil
. - 선택사항인 경우
nil
그것은 다음으로 번역될 것이다false
상태.
지금까지 나는 (테스트되지 않음) :
var readStream: Unmanaged<CFReadStream>?
var writeStream: Unmanaged<CFWriteStream>?
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, host, port, \
&readStream, &writeStream)
if (readStream && writeStream) {
inputStream = readStream!.takeUnretainedValue();
outputStream = writeStream!.takeUnretainedValue();
}
NSStream 클래스의 GetStreamStohostwithName 함수를 사용하고 있습니다.CFSTREAMCREATEPARWITHSockETTOHOST
보다 쉽고 쉽게 쉽고 발이야합니다.func initnetworkcommunication () {
print("connecting...")
let serverAddress = "gzoa.vps.infomaniak.com"
let serverPort = 1234
NSStream.getStreamsToHostWithName(serverAddress, port: serverPort, inputStream: &inputStream, outputStream: &outputStream)
self.inputStream!.delegate = self
self.outputStream!.delegate = self
self.inputStream!.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
self.outputStream!.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
self.inputStream!.open()
self.outputStream!.open()
.
}
SWIFT 3 버전의 CF 및 NS 코드.둘 다 나를 위해 일합니다.
cf :
class Connection: NSObject, StreamDelegate {
private var inputStream: InputStream!
private var outputStream: OutputStream!
var connected = false
func connect(host: String, port: UInt32) {
var readStream: Unmanaged<CFReadStream>?
var writeStream: Unmanaged<CFWriteStream>?
CFStreamCreatePairWithSocketToHost(nil, host as CFString, port, &readStream, &writeStream)
self.inputStream = readStream!.takeRetainedValue()
self.outputStream = writeStream!.takeRetainedValue()
if let inputStream = inputStream, let outputStream = outputStream {
inputStream.delegate = self
outputStream.delegate = self
inputStream.schedule(in: RunLoop.current, forMode: RunLoopMode.defaultRunLoopMode)
outputStream.schedule(in: RunLoop.current, forMode: RunLoopMode.defaultRunLoopMode)
inputStream.open()
outputStream.open()
connected = true
}
}
func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
print("stream event, \(eventCode)")
}
}
.
ns :
class NSConnection: NSObject, StreamDelegate {
private var inputStream: InputStream?
private var outputStream: OutputStream?
var connected = false
func connect(host: String, port: Int) {
Stream.getStreamsToHost(withName: host, port: port, inputStream: &inputStream, outputStream: &outputStream)
if let inputStream = inputStream, let outputStream = outputStream {
inputStream.delegate = self
outputStream.delegate = self
inputStream.schedule(in: RunLoop.current, forMode: RunLoopMode.defaultRunLoopMode)
outputStream.schedule(in: RunLoop.current, forMode: RunLoopMode.defaultRunLoopMode)
inputStream.open()
outputStream.open()
}
}
func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
print("stream event, \(eventCode)")
}
}
.