如何使用 CoreNFC 将 NFC 标签有效负载转换为 URL?
Posted
技术标签:
【中文标题】如何使用 CoreNFC 将 NFC 标签有效负载转换为 URL?【英文标题】:How I can convert NFC tag payload to URL using CoreNFC? 【发布时间】:2020-08-10 08:58:40 【问题描述】:我正在尝试编写一个函数,用于将 NFC 标签有效负载数据转换为 URL 以在 safari 中打开它,但由于某种原因它没有打开,因为它无法将其转换为 URL。我的代码在这里:
func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage])
var result = ""
for payload in messages[0].records
print("-> \(payload)") //Prints the Entire NFC Payload on the Tag.
result += String.init(data: payload.payload, encoding: .utf16) ?? "Format not supported"
DispatchQueue.main.async
guard let url = URL(string: result) else return
UIApplication.shared.open(url)
【问题讨论】:
String.init(data: payload.payload, encoding: .utf16)
产生什么?
developer.apple.com/documentation/corenfc/nfcndefpayload/… 另外,你能检查一下typeNameFormat
吗? let urls = messages[0].records.flatMap $0.wellKnownTypeURIPayload ; urls.forEach print("anUrl: \($0.absoluteString)"
另外,像这样附加网址?分块?
【参考方案1】:
您需要解码有效载荷,因为它按照 NFC 论坛技术规范中的描述进行编码(例如 NFCForum-TS-NDEF_1.0.pdf,在可能的地方抓取它,但在“白色方向” - 这个文件需要购买)
NDEF 是复杂的格式,为了正确解码,您需要遵守所有功能(无需实现所有功能,但您需要准备好理解负载中出现的所有数据)。
简而言之,对于 URL 类型的解码,您需要对两种类型的有效负载做出反应(我的代码在 Objective-C 中,但可以用 Swift 重写):
NSDictionary *urlData; // <- Desired URL placed here
NSString *payloadType = [[NSString alloc] initWithData:payload.type encoding:NSUTF8StringEncoding];
if ([@"Sp" isEqualToString:payloadType])
urlData = [NDEFProcessor parseSmartPoster:payload.payload];
else if ([@"U" isEqualToString:payloadType])
urlData = [NDEFProcessor parseUriPrimitive:payload.payload];
NDEFProcessor
函数在哪里:
+ (NSString *) uriPrefixForType: (uint8_t) type
switch (type)
default: return @"";
case 0x01: return @"http://www.";
case 0x02: return @"https://www.";
case 0x03: return @"http://";
case 0x04: return @"https://";
case 0x05: return @"tel:";
case 0x06: return @"mailto:";
+ (NSDictionary *) parseUriPrimitive:(NSData *) payload
NSMutableDictionary *result = [[NSMutableDictionary alloc] init];
int schemeType = ((uint8_t *) payload.bytes) [0];
NSString *uriRaw = [[NSString alloc] initWithBytes:payload.bytes + 1 length:payload.length - 1 encoding:NSUTF8StringEncoding];
NSString *proto = [NDEFProcessor uriPrefixForType:schemeType];
[result setObject: proto
forKey: @"PROTO"];
[result setObject: uriRaw
forKey: @"RAW"];
[result setObject: [NSString stringWithFormat:@"%@%@", proto, uriRaw]
forKey: @"URI"];
return [NSDictionary dictionaryWithDictionary:result];
+ (NSDictionary *) parseSmartPoster:(NSData *) payload
NSMutableDictionary *result = [[NSMutableDictionary alloc] init];
int pos = 0;
uint8_t recordHeader;
do
recordHeader = ((uint8_t *) payload.bytes)[pos];
uint8_t recordLength = ((uint8_t *) payload.bytes)[pos + 2];
uint8_t recordType = ((uint8_t *) payload.bytes) [pos + 3];
if (recordType == 0x55)
// URI
NSDictionary *uriDictionary = [self parseUriPrimitive:[payload subdataWithRange:NSMakeRange(pos + 4, recordLength)]];
if (uriDictionary != nil)
[result addEntriesFromDictionary:uriDictionary];
pos = pos + recordLength + 4;
while ((pos < payload.length) || ((recordHeader & (1 << 6)) != 0x40));
return [NSDictionary dictionaryWithDictionary:result];
【讨论】:
developer.apple.com/documentation/corenfc/nfcndefpayload/… 对于您的大多数情况来说还不够吗? @Larme,在 Smart Poster 记录的情况下,记录存在于两个“子记录”中:text+Uri。在这种情况下,您需要在两个原始 Uri+Text 中“反编译”复杂的 Sp 记录。我不确定 Apple - 它能否处理复杂的记录。以上是关于如何使用 CoreNFC 将 NFC 标签有效负载转换为 URL?的主要内容,如果未能解决你的问题,请参考以下文章
iOS CoreNFC - 类“NFTechnologyEvent”未加载或不存在