использование pipe () в Swift App для перенаправления stdout в textView (работает только в симуляторе, а не в нативном) - PullRequest
0 голосов
/ 30 декабря 2018

Я создал приложение для iOS для iPhone, используя Swift под Xcode IDE.В целях отладки я хотел бы, чтобы все, что print (и printf в C-коде) печатало на консоль Xcode нормально, перенаправлялось на UItextView.Мой код (в основном полученный из здесь ) выглядит следующим образом:

//
//  ViewController.swift
//  Scroll View Demo
//

//  
//

import UIKit

class ViewController: UIViewController {


    @IBOutlet weak var textView: UITextView!
    @IBOutlet weak var writeButton: UIButton!
    var pipe = Pipe()
    var count = 0

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        // dup2() makes newfd (new file descriptor) be the copy of oldfd (old file descriptor), closing newfd first if necessary.
        openConsolePipe()
        print("\npipe started")

    }

    @IBAction func buttonPressed(_ sender: Any) {
        print("\(count). Hello world")
        count += 1
    }
    public func openConsolePipe () {
        dup2(pipe.fileHandleForWriting.fileDescriptor, 
            STDOUT_FILENO)
        // listening on the readabilityHandler
        pipe.fileHandleForReading.readabilityHandler = {
         [weak self] handle in
        let data = handle.availableData
        let str = String(data: data, encoding: .ascii) ?? "<Non-ascii data of size\(data.count)>\n"
        DispatchQueue.main.async {
            self?.textView.text += str
        }
      }
    }

}

Код работает в режиме моделирования на физическом устройстве, а также на виртуальном iphone.Но когда я запускаю его изначально с обрезанным шнуром для Xcode, pipe () не работает.Я не знаю, почему pipe () не работает в автономном приложении.

1 Ответ

0 голосов
/ 10 января 2019

Изменение кода, которое сделало пример, наконец, сработало, изменило дескриптор файла stdout на небуферизованный (setvbuf (stdout, nil, _IONBF, 0)):

//
//  ViewController.swift
//  Scroll View Demo
//

//  
//



import UIKit

class ViewController: UIViewController {


@IBOutlet weak var textView: UITextView!
@IBOutlet weak var writeButton: UIButton!
var pipe = Pipe()
var count = 0

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    // dup2() makes newfd (new file descriptor) be the copy of oldfd (old file descriptor), closing newfd first if necessary.
    openConsolePipe()
    print("\npipe started")

}

@IBAction func buttonPressed(_ sender: Any) {
    print("\(count). Hello world")
    count += 1
}
public func openConsolePipe () {
    **setvbuf(stdout, nil, _IONBF, 0).** //<--------- !
    dup2(pipe.fileHandleForWriting.fileDescriptor, 
        STDOUT_FILENO)
    // listening on the readabilityHandler
    pipe.fileHandleForReading.readabilityHandler = {
     [weak self] handle in
    let data = handle.availableData
    let str = String(data: data, encoding: .ascii) ?? "<Non-ascii data of size\(data.count)>\n"
    DispatchQueue.main.async {
        self?.textView.text += str
    }
  }
}

Это потому, что приложение работаетотключенный от Xcode стандартный вывод перенаправляется во что-то вроде / dev / null с буферизацией, установленной в «буферизированный», и, таким образом, никогда не появляется в pipe ().Установка небуферизованного заставила вещи работать.

...