如何在SwiftUI中将print()打印到Xcode控制台?

zum*_*zum 8 swiftui

因此,我尝试在SwiftUI视图中调试时放入一条打印语句。

    print("landmark: \(landmark)")
Run Code Online (Sandbox Code Playgroud)

在下面的身体。

    var body: some View {
    NavigationView {
        List {
            Toggle(isOn: $userData.showFavoritesOnly) {
                Text("Favorite only")
            }
            ForEach(landmarkData) { landmark in
                print("landmark: \(landmark)")
                if !self.userData.showFavoritesOnly || landmark.isFavorite {
                    NavigationButton(destination: LandmarkDetail(landmark: landmark)) {
                        LandmarkRow(landmark: landmark)
                    }
                }
            }
        }.navigationBarTitle(Text("Landmarks"))

    }
}
Run Code Online (Sandbox Code Playgroud)

编译错误出: 在此处输入图片说明

那么,在SwiftUI中打印到控制台的正确方法是什么?

编辑:我使Landmark符合CustomStringConvertible

struct Landmark: Hashable, Codable, Identifiable, CustomStringConvertible {

var description: String { name+"\(id)" }

var id: Int
var name: String
.....
Run Code Online (Sandbox Code Playgroud)

我仍然收到“字符串不可转换为任何字符串”的错误。现在应该工作吗?

jul*_*665 87

至少在 Xcode 12/Swift 5.3 中,您可以轻松地在函数构建器的任何位置添加打印语句,只需将其返回值存储在通配符中,有效地忽略它:

let _ = print("hi!")
Run Code Online (Sandbox Code Playgroud)

无需设置或其他详细信息!

  • 天哪,为什么 SwiftUI 中的某些事情必须如此奇怪,这么多事情感觉像是“解决方法”或“黑客”只是为了达到一个简单的结果。 (47认同)
  • 这应该是公认的答案 (10认同)
  • @mfaani 阅读我几个月前的旧评论有点有趣,现在我实际上已经很好地掌握了 SwiftUI。我同意你的看法。我认为问题在于朱利安德的回答没有提到它不起作用的原因,并让人们相信这是无缘无故地完成的。另外,Xcode 的错误消息也可以更清楚地解释为什么这是不可能的:) (3认同)
  • @Big_Chair 好主意!我扩展了我的答案,解释了它的工作原理以及视图构建器为何以这种方式工作的一些想法。 (3认同)
  • @Big_Chair 我正在学习 SwiftUI,我有点同意你的观点。但与此同时,限制可能会导致更多的结构。也就是说:“body”中的所有内容都是“View”类型或带有编译器指令的内容,使其知道它会被忽略。 (2认同)

Rok*_*lec 48

这是一个辅助Print( ... )视图,它的作用类似于print( ... )函数,但位于视图中

把它放在你的任何视图文件中

extension View {
    func Print(_ vars: Any...) -> some View {
        for v in vars { print(v) }
        return EmptyView()
    }
}
Run Code Online (Sandbox Code Playgroud)

body像这样在里面使用

Print("Here I am", varOne, varTwo ...)
Run Code Online (Sandbox Code Playgroud)

或者ForEach {}像这样

self.Print("Inside ForEach", varOne, varTwo ...)
Run Code Online (Sandbox Code Playgroud)

Note: you might need to put Print() into a Group {} when combining with existing views

  • 此修改允许您使用“打印”语法: func Print(_ items: Any..., seperator: String = " ", terminator: String = "\n") -> some View { let string = items.map{String (describing: $0)}.joined(separator:separator) print("Print:", string, terminator: terminator) // 可以在此处添加其他内容 return EmptyView() } self.Print("viewnamed", self.someName , "编号:", self.num) (2认同)

Dar*_*isa 8

您可以在 body 结构中打印,但要这样做,您必须明确返回要渲染的视图。通常在 SwiftUI 中, body 属性会隐式返回视图。例如,当您尝试打印时,这将引发错误:

struct SomeView: View {
  @State var isOpen = false

  var body: some View {
    print(isOpen) // error thrown here

    VStack {
      // other view code
    |
  }
}
Run Code Online (Sandbox Code Playgroud)

但是如果我们明确地返回我们想要的视图,那么它就会起作用,例如

struct SomeView: View {
  @State var isOpen = false

  var body: some View {
    print(isOpen) // this ok because we explicitly returned the view below

     // Notice the added 'return' below
     return VStack {
      // other view code
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

如果您想在返回视图之前查看状态或环境对象的变化情况,则上述方法会很有效,但是如果您想在要返回的视图中更深入地打印一些内容,那么我会选择@Rok Krulec回答。


小智 6

尝试右键单击实时预览播放按钮,然后从弹出窗口中选择“调试预览”

  • 关于 macOS 中 SwiftUI 的调试预览,似乎最新的 Xcode (11.3) 还不支持使用 `print()` 将日志打印到 Xcode 的控制台。据我所知,目前只有带有日志消息操作的断点可以做到这一点。或者,作为另一种解决方法,您可以将调试预览与 Console.app 结合使用,以便可以在应用程序中查看调试日志。请注意,您需要使用“NSLog()”,因为“print()”不适用于输出到 Console.app。 (5认同)
  • 在 Xcode 12.3 中,将日志打印到 Xcode 的控制台似乎仍然不起作用:( (3认同)

Asp*_*eri 6

可以使用 print() ,记住所有 SwiftUI View 内容都是(a)隐式闭包,(b)强烈建议尽可能分解视图以具有简单的结构,因此它可能如下所示......

struct Model: Identifiable {
    let value: String
    var id: String {
        value
    }
    init (_ value: String) {
        self.value = value
    }
}

struct TestView: View {
    @State var showFavoritesOnly = false
    @State var listData: [Model] = [Model("one"), Model("two"), Model("three")]

    var body: some View {
        NavigationView {
            List {
                Toggle(isOn: $showFavoritesOnly) {
                    Text("Favorite only")
                }
                ForEach(listData) { data in
                    self.rowView(data: data)
                }
            }
        }
    }

    private func rowView(data: Model) -> some View {
#if DEBUG
        print(">> \(data.value)")
#endif
        return NavigationLink(destination: Text("Details")) {
            Text("Go next from \(data.value)")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

...然后右键单击“预览”以选择“作为调试预览运行”,我们得到:

2019-10-31 14:28:03.467635+0200 Test[65344:11155167] [Agent] Received connection, creating agent
2019-10-31 14:28:04.472314+0200 Test[65344:11155168] [Agent] Received display message
>> one
>> two
>> three
Run Code Online (Sandbox Code Playgroud)


Ami*_*rca 5

在 SwiftUI 视图中调试时最安全、最简单的打印方法。

extension View {
    func Print(_ item: Any) -> some View {
        #if DEBUG
        print(item)
        #endif
        return self
    }
}
Run Code Online (Sandbox Code Playgroud)

使用示例:

struct ContentView: View {
    var body: some View {
        VStack {
            ForEach((1...5), id: \.self) { number in
                Text("\(number)")
                    .Print(number)
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

控制台输出:

1
2
3
4
5
Run Code Online (Sandbox Code Playgroud)


ARG*_*Geo 5

您可以声明一个printing()包含print()并返回EmptyView结构的方法。

struct ContentView: View {
    
    @State private var offset = CGSize.zero
    
    func printing(_ items: Any...) -> some View {
        let _ = print(items)
        return EmptyView()
    }
        
    var body: some View {
        
#if DEBUG
        printing(offset)                // prints [(0.0, 0.0)]
#endif

        ZStack {
            Text("Hello")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)