快速将UnsafeMutableRawPointer转换为String(utf8)

时间:2019-05-24 07:25:41

标签: ios objective-c swift macos

问题很简单,如何快速将UnsafeMutableRawPointer?转换为String(encoding: utf8)

我从用obj c编写的套接字中获取了一些数据,模型类看起来像

@interface PTData : NSObject
@property (readonly) dispatch_data_t dispatchData;
@property (readonly) void *data;
@property (readonly) size_t length;
@end

用于将数据转换为String的相应obj c代码

PTExampleTextFrame *textFrame = (PTExampleTextFrame*)payload.data;
textFrame->length = ntohl(textFrame->length);
NSString *message = [[NSString alloc] initWithBytes:textFrame->utf8text length:textFrame->length encoding:NSUTF8StringEncoding];

这里PTExampleTextFramestruct

typedef struct _PTExampleTextFrame {
  uint32_t length;
  uint8_t utf8text[0];
} PTExampleTextFrame; 

但是我无法将代码转换为swift。但是当我尝试转换代码时,

let data = Data(bytesNoCopy: payload!.data, count: payload.length,deallocator: .none)

let text = String(bytes: data, encoding: String.Encoding.utf8)

我以某种方式得到了答案,但是文本的开头带有一些转义字符。

  

hi使\0\0\0\u{02}jj

     

long text\0\0L\u{1D}long text

我没有得到UnsafeMutableRawPointer的概念以及前缀是什么。

1 个答案:

答案 0 :(得分:2)

如果确认将数据转换为字符串的 obj c代码正常工作,建议您编写一个Objective-C扩展以与Swift一起使用。

例如:

PTData + Swift.h

#import <Foundation/Foundation.h>

@class PTData;

NS_ASSUME_NONNULL_BEGIN

@interface PTData (Swift)
@property (readonly) NSString *message;

@end

NS_ASSUME_NONNULL_END

PTData + Swift.m

#import "PTData.h"
#import "PTData+Swift.h"

@implementation PTData (Swift)

- (NSString *)message {
    PTExampleTextFrame *textFrame = (PTExampleTextFrame*)self.data;
    uint32_t length = ntohl(textFrame->length);
    NSString *message = [[NSString alloc] initWithBytes:textFrame->utf8text
                                                 length:length
                                               encoding:NSUTF8StringEncoding];
    return message;
}

@end

{YourProject} -Bridging-Header.h

#import "PTData.h"
#import "PTData+Swift.h"

(您可能需要修改#import "PTData.h"以包括实际的标头。)

有了以上扩展,您可以简单地用Swift编写:

debugPrint(payload.message)

否则,如果您不敢编写与将代码转换为String的 obj c代码等效的Swift ,则显示的Swift代码就太短了。

extension PTData {
    var textFrameMessage: String {
        let textFrame = self.data.assumingMemoryBound(to: PTExampleTextFrame.self)
        let length = Int(textFrame.pointee.length.bigEndian)
        let utf8text = self.data
            .advanced(by: MemoryLayout<UInt32>.size) // <- Sadly enough, `MemoryLayout.offset(of:)` does not work as expected for `utf8text`
            .assumingMemoryBound(to: UInt8.self)
        let bytes = UnsafeBufferPointer(start: utf8text, count: length)
        let message = String(bytes: bytes, encoding: .utf8)! // <- This may crash, if the message is not encoded in UTF-8
        return message
    }
}

debugPrint(payload.textFrameMessage)

我已经用最少的估计数据测试了上述代码,但可能与您收到的实际数据有所不同。如果您发现问题,请尝试告诉我。