iOS 命名管道,适用于 ObjC,不适用于 Swift,相同的代码

iOS named pipes, works in ObjC, does not work in Swift, same code

我一直在尝试在 iOS 中使用命名管道,但在 Swift 中似乎基本相同的代码失败了,而在 ObjectiveC 中却有效。

在 Swift 中,用于写入的 FileHandle 返回 nil,或者如果我使用 FileHandle(forWritingAt: URL) API,它会抛出一个 Permission Denied。 Objective C 数据通过管道成功发送并记录。

这两个中的路径完全相同。 Objective C 示例中的数据也是 "hello".data(using: .utf8),但已传递到函数中。

Swift

  do {
    try FileManager.default.removeItem(at: url)
  } catch let error {
    print("error deleting", error)
  }

  mkfifo(url.path, 0777)
  DispatchQueue.main.async {
    let fileHandle = FileHandle(forWritingAtPath: url.path)
    fileHandle?.write("hello".data(using: .utf8)!)
  }

  let fileHandle = FileHandle(forReadingAtPath: url.path)
  if let data = fileHandle?.availableData {
    print(String(data: data, encoding: .utf8))
  }

Objective C

  remove(path.UTF8String);
  mkfifo(path.UTF8String, 0777);
  dispatch_async(dispatch_get_main_queue(), ^{
    NSFileHandle *fileHandle=[NSFileHandle fileHandleForWritingAtPath: path];
    [fileHandle writeData:data];
  });

  NSFileHandle *fileHandle=[NSFileHandle fileHandleForReadingAtPath: path];
  NSData* read = fileHandle.availableData;
  NSLog([[NSString alloc] initWithData: read encoding: NSUTF8StringEncoding]);

这些应该只是调用 Objective C 函数吧?为什么他们会有不同的行为? XCode11.3,iOS13

@gnasher729 是正确的 - Swift 没有八进制,所以 0777 是错误的。我将八进制转换为十六进制并将文字替换为 0x1FF

Does Swift have octal numbers? I dont think so.
Swift does not have octal

恐怕Swift 有八进制数吗,看Integer Literals

mkfifo(url.path, 0o777)

我从这里路过,我在 swift 中寻找命名管道通信的完整解决方案。 这是我最后能做的。

private let path = "/tmp/myfifo"
func listen() {
        DispatchQueue.global(qos: .userInitiated).async { [weak self] in
            let url = URL(fileURLWithPath: self?.path ?? "")
            do {
              try FileManager.default.removeItem(at: url)
            } catch let error {
              print("error deleting", error)
            }

            mkfifo(url.path, 0o777)
            let fileHandle = FileHandle(forReadingAtPath: url.path)
            while true {
                if let data = fileHandle?.availableData {
                    if let readedData = String(data: data, encoding: .utf8), readedData != "" {
                        print(readedData)
                    }
                }
            }
        }
    }

发送(写入文件处理程序)

   func sendToDeamon(content: String) {
        let handler = FileHandle(forWritingAtPath: "/tmp/myfifo")
        let secData = content.data(using: .utf8)
        if let secData = secData {
            handler?.write(secData)
        }
        handler?.closeFile()
    }