19

I've created a project in xcode 12 and added a Widget Extension target. The target is created and I'm left with a simple widget that shows the time. The preview of the widget works as expected and the widget is shown as expected in the simulator. But if I change the view to use List instead of Text, like this:

struct SimpleWidgetEntryView : View {
    var entry: Provider.Entry

    var body: some View {
        List {
            Text("Something")
        }
    }
}

The preview and the simulator both show a red No Entry sign on a yellow background:

The No Entry sign shown in the xcode 12 preview

I've tried putting the List inside a VStack and using a dynamic list without any success. I can't find any documentation about List being prohibited in a widget. I've tried restarting xcode and the simulator, cleaning and rebuilding. I'm using xcode 12.0 beta 3.

~I also get this issue trying to use a UIView wrapped in UIViewRepresentable. The view is a LineChartView from the Charts library.~ Edit: according to this post on the Apple developer forums it isn't possible to use UIKit views in a WidgetKit widget.

Does anyone know how I can use a List in a widget? Any help much appreciated. Thanks

Paul
  • 1,897
  • 1
  • 14
  • 28
  • 1
    Lists are table views and table views are scroll views. Widgets probably don't support scroll views. – EmilioPelaez Jul 28 '20 at 14:57
  • Do you still get the error if you delete the line: var entry: Povider.Entry ? – Razvan S. Jul 28 '20 at 14:59
  • @EmilioPelaez That could well be the case. It'd be great to see some documentation that definitively says one way or the other though. – Paul Jul 28 '20 at 15:13
  • @RazvanS. The error does still occur if I remove that line (and change the places that are expecting to supply it to the default initialiser). – Paul Jul 28 '20 at 15:15
  • @Paul If I copy your code in playgrounds, without the line I mentioned, it works with no problems. MacOS Catalina, XCode 11.6 – Razvan S. Jul 29 '20 at 08:14
  • Hi @RazvanS. the problem occurs in the context of using a list in a widget built with WidgetKit – Paul Jul 30 '20 at 08:45
  • I am also encountering this problem, so any help is highly appreciated. – inexcitus Aug 08 '20 at 08:18
  • I couldn't find any Apple documentation saying a scrollView would result in this big "do not enter sign" appearing. I did find this, but it seems more like a suggestion: "Avoid putting a scroll view inside a Today widget. It’s difficult for users to scroll within a widget without inadvertently scrolling the Today view." So if it is true that the scrollView causes the yellow background red do not enter sign to appear, it would be good to find this documented somewhere so this question could officially be answered. I'm having this issue too by the way... – Jackson Sep 25 '20 at 00:58

3 Answers3

7

I got this yellow no entry (ghostbusters without the ghost lol) sign after trying to include a chart from the Charts library (subclass of UIView) using a UIViewRepresentable wrapper. I couldn't find the yellow no entry sign documented anywhere and wasn't sure if it originated from the Charts library or iOS itself so it was a relief to see that you saw the same issue and this set me on the right path to coming up with a solution.

From this post that you referenced above, an Apple Engineer says "UIKit views wrapped in UIViewRepresentable will not work in WidgetKit. When the views are encoded from your extension to be displayed they will appear blank.". I don't think that is entirely accurate. I think it will appear yellow with a red "no entry" sign.

https://developer.apple.com/forums/thread/653471?answerId=619627022#619627022

I got around this issue by rendering my chart as a UIImage and displaying the image on the widget instead of the UIView version of the chart. That should suffice for my purposes as I don't need it to be interactive like I do in the app.

Jackson
  • 3,555
  • 3
  • 34
  • 50
  • 1
    That's brilliant! I actually ended up on this post because I'm trying to use that same Charts library and ended up with the red/yellow error. For the imaging, do you process this in the widget's code, or are you doing this in the app? And do you do any calculations for size? – Sti Oct 18 '20 at 11:14
  • I am creating the image in the widget itself and I do pass a size parameter to the function I wrote to create a chart image. – Jackson Oct 19 '20 at 12:17
  • 2
    Thanks, I managed to do the same. Using `GeometryReader` I could pass the correct size to a function to do the UIGraphicsBeginImageContext for rendering the graph. Worked out perfectly:) – Sti Oct 19 '20 at 12:20
  • 1
    Yep I’m using GeometryReader as well. – Jackson Oct 20 '20 at 13:37
7

Background

Widget Views are static.

They don't support animation, navigation nor user interaction (with the exception of Link). And they must be written in pure SwiftUI.


List of views that are not allowed in WidgetKit

Note that the list is not exhaustive, provided mostly with examples:

  1. Interactive views (ones you can interact with, e.g., by touching them):

    • List
    • Form
    • ScrollView
    • TabView
    • Map
    • Picker
    • Slider
    • and so on...
  2. Animated views:

    • ProgressView
  3. Navigation views (you can't use the standard navigation - for this you have Link):

    • NavigationView
    • NavigationLink
  4. UIKit Wrappers for UIKit Views/ViewControllers:

    • UIViewRepresentable
    • UIViewControllerRepresentable

Replacements

If you want to use any of the above views, e.g. an interactive view like List, you need to create it out of non-interactive views - here VStack + ForEach.

pawello2222
  • 46,897
  • 22
  • 145
  • 209
4

Use ForEach inside a VStack:

 var body: some View{
        ZStack{
            self.backgroundColor
            VStack{
                ForEach(0...1, id: \.self){ entry in
                    Text("\(entry)")
                }
            }
        }
    }
the Reverend
  • 12,305
  • 10
  • 66
  • 121