SDWebImage / SDWebImageSwiftUI

SwiftUI Image loading and Animation framework powered by SDWebImage
https://sdwebimage.github.io/SDWebImageSwiftUI
MIT License
2.16k stars 223 forks source link

WebImage Instantly crashes on load when inside a TabView #133

Closed mjswen0923 closed 3 years ago

mjswen0923 commented 3 years ago

When used inside a TabView, any loading of a WebImage will immediately cause a crash. Here is the code that causes the crash:

TabView {

            Text("testing")
                .tabItem    {
                    Text("test")
                }
            WebImage(url: URL(string: "https://raw.githubusercontent.com/SDWebImage/SDWebImage/master/SDWebImage_logo.png"))
                .tabItem    {
                    Text("test2")
                }
}

I am using Xcode 12.0 with iOS 14.0, with SDWebImage 5.9.0 and SDWebImageSwiftUI 1.5.0.

Below is the stack trace:

0 0x00000001b30dcc64 in AG::AttributeID::size() const ()

1 0x00000001b30d0b2c in AG::Graph::add_indirect_attribute(AG::Subgraph&, AG::AttributeID, unsigned long, std::__1::optional, bool) ()

2 0x00000001b30e2fe8 in (anonymous namespace)::create_indirect_attribute(unsigned int, std::__1::optional) ()

3 0x00000001926b5bf4 in partial apply for thunk for @callee_guaranteed () -> (@unowned IndirectAttribute) ()

4 0x00000001926b5a24 in closure #1 in AGSubgraphRef.apply(_:) ()

5 0x00000001926b5818 in Attribute.makeReusable(indirectMap:) ()

6 0x00000001926b1fd0 in closure #1 in closure #1 in closure #1 in ModifiedElements.makeElements(from:inputs:indirectMap:body:) ()

7 0x00000001923fd324 in closure #1 in closure #1 in PlaceholderInfo.makeItem(placeholder:seed:) ()

8 0x0000000192525784 in thunk for @callee_guaranteed (@in_guaranteed _ViewInputs, @guaranteed @escaping @callee_guaranteed (@in_guaranteed _ViewInputs) -> (@out _ViewOutputs)) -> (@out _ViewOutputs?) ()

9 0x00000001926ad49c in closure #1 in closure #1 in _ViewList_Elements.makeOneElement(at:inputs:indirectMap:body:) ()

10 0x00000001926b7d58 in partial apply for thunk for @callee_guaranteed (@in_guaranteed _ViewInputs, @guaranteed @escaping @callee_guaranteed (@in_guaranteed _ViewInputs) -> (@out _ViewOutputs)) -> (@out _ViewOutputs?, @unowned Bool) ()

11 0x00000001926b1e78 in closure #1 in closure #1 in ModifiedElements.makeElements(from:inputs:indirectMap:body:) ()

12 0x00000001926b7d94 in partial apply for closure #1 in closure #1 in ModifiedElements.makeElements(from:inputs:indirectMap:body:) ()

13 0x00000001926b7d58 in partial apply for thunk for @callee_guaranteed (@in_guaranteed _ViewInputs, @guaranteed @escaping @callee_guaranteed (@in_guaranteed _ViewInputs) -> (@out _ViewOutputs)) -> (@out _ViewOutputs?, @unowned Bool) ()

14 0x00000001926b1e78 in closure #1 in closure #1 in ModifiedElements.makeElements(from:inputs:indirectMap:body:) ()

15 0x00000001926b7d94 in partial apply for closure #1 in closure #1 in ModifiedElements.makeElements(from:inputs:indirectMap:body:) ()

16 0x00000001926b7d58 in partial apply for thunk for @callee_guaranteed (@in_guaranteed _ViewInputs, @guaranteed @escaping @callee_guaranteed (@in_guaranteed _ViewInputs) -> (@out _ViewOutputs)) -> (@out _ViewOutputs?, @unowned Bool) ()

17 0x00000001926b1e78 in closure #1 in closure #1 in ModifiedElements.makeElements(from:inputs:indirectMap:body:) ()

18 0x00000001926b7d94 in partial apply for closure #1 in closure #1 in ModifiedElements.makeElements(from:inputs:indirectMap:body:) ()

19 0x00000001926afe78 in UnaryElements.makeElements(from:inputs:indirectMap:body:) ()

20 0x00000001926b3350 in SubgraphElements.makeElements(from:inputs:indirectMap:body:) ()

21 0x00000001926b1d5c in closure #1 in ModifiedElements.makeElements(from:inputs:indirectMap:body:) ()

22 0x00000001926b1c28 in ModifiedElements.makeElements(from:inputs:indirectMap:body:) ()

23 0x00000001926b1d5c in closure #1 in ModifiedElements.makeElements(from:inputs:indirectMap:body:) ()

24 0x00000001926b1c28 in ModifiedElements.makeElements(from:inputs:indirectMap:body:) ()

25 0x00000001926b1d5c in closure #1 in ModifiedElements.makeElements(from:inputs:indirectMap:body:) ()

26 0x00000001926b1c28 in ModifiedElements.makeElements(from:inputs:indirectMap:body:) ()

27 0x00000001926b3350 in SubgraphElements.makeElements(from:inputs:indirectMap:body:) ()

28 0x00000001926ad420 in closure #1 in _ViewList_Elements.makeOneElement(at:inputs:indirectMap:body:) ()

29 0x00000001923fcedc in closure #1 in PlaceholderInfo.makeItem(placeholder:seed:) ()

30 0x00000001923fc984 in PlaceholderInfo.updateValue() ()

31 0x00000001920d83e4 in partial apply for specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init(_:) ()

32 0x00000001b30cc194 in AG::Graph::UpdateStack::update() ()

33 0x00000001b30cc5c8 in AG::Graph::update_attribute(AG::data::ptr, bool) ()

34 0x00000001b30d5728 in AG::Subgraph::update(unsigned int) ()

35 0x0000000192738af4 in GraphHost.runTransaction() ()

36 0x000000019224d780 in ViewGraph.updateOutputs(at:) ()

37 0x000000019269604c in closure #1 in ViewRendererHost.render(interval:updateDisplayList:) ()

38 0x0000000192695274 in ViewRendererHost.render(interval:updateDisplayList:) ()

39 0x000000019214d748 in closure #1 in _UIHostingView.requestImmediateUpdate() ()

40 0x0000000192801ec0 in thunk for @escaping @callee_guaranteed () -> () ()

41 0x00000001050f3b68 in _dispatch_call_block_and_release ()

42 0x00000001050f55f0 in _dispatch_client_callout ()

43 0x0000000105104890 in _dispatch_main_queue_callback_4CF ()

44 0x000000018b9731e4 in CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE ()

45 0x000000018b96d3b4 in __CFRunLoopRun ()

46 0x000000018b96c4bc in CFRunLoopRunSpecific ()

47 0x00000001a23f1820 in GSEventRunModal ()

48 0x000000018e310734 in -[UIApplication _run] ()

49 0x000000018e315e10 in UIApplicationMain ()

50 0x00000001926cd32c in closure #1 in KitRendererCommon(_:) ()

51 0x00000001926cd2b8 in runApp(_:) ()

52 0x0000000192246b08 in static App.main() ()

53 0x0000000104c130b4 in static SDWebImageTestCrashApp.$main() ()

54 0x0000000104c13154 in main ()

55 0x000000018b633e60 in start ()

yonaskolb commented 3 years ago

I'm also getting a crash in iOS 14.0 within the SwiftUI AG Graph when a list item with a WebImage is scrolled onto screen

mjswen0923 commented 3 years ago

I'm also getting a crash in iOS 14.0 within the SwiftUI AG Graph when a list item with a WebImage is scrolled onto screen

Was it AGGraph::getValue()? I was experiencing that as well, but this bug was much easier to repro and track down.

dreampiggy commented 3 years ago

Need some dig into SwiftUI issue of this. I didn't realize that user will put this WebImage inside the TabView.

dreampiggy commented 3 years ago

You can wrap that into a empty VStack or HStack.

var body: some View {
    TabView {
        Text("testing")
            .tabItem    {
                Text("test")
            }
        VStack {
            WebImage(url: URL(string: "https://raw.githubusercontent.com/SDWebImage/SDWebImage/master/SDWebImage_logo.png"))
        }
        .tabItem    {
            Text("test2")
        }
    }
}
yonaskolb commented 3 years ago

Was it AGGraph::getValue()? I was experiencing that as well, but this bug was much easier to repro and track down.

Yep

Screen Shot 2020-09-22 at 3 32 53 pm
yonaskolb commented 3 years ago

I've created a simple repro project that shows the crash I'm experiencing in lists and buttons in iOS 14.0 SDWebImageCrash.zip

djr commented 3 years ago

I'm also experiencing the AGGraph::getValue() crash but not inside a TabView. The images are in a SwiftUI List view. Wrapping them in an empty VStack or HStack didn't help.

mjswen0923 commented 3 years ago

I'm also experiencing the AGGraph::getValue() crash but not inside a TabView. The images are in a SwiftUI List view. Wrapping them in an empty VStack or HStack didn't help.

Yes, I had that problem as well

dreampiggy commented 3 years ago

Need some SwiftUI expert to help. This sounds like Apple's SwiftUI internal changes which effect the current WebImage implementation.

Baza207 commented 3 years ago

I'm having a similar issue in a ListView. I have a feeling it's an Async issue, where something returns but the returned thing has already been released by SwiftUI in the background. Harder to catch in a ListView though, but I get exactly the same AGGraph error.

I'm not sure if this is a big in SwiftUI though or something that can be fixed with work arounds, etc.

WunDaii commented 3 years ago

I'm also getting the same AGGraph::getValue() crash inside a List unfortunately.

ramunasjurgilas commented 3 years ago

I am getting this crash as well. HStack or VStack not helping.

image
maurovc commented 3 years ago

I'm also experiencing this issue. Did someone find a workaround or any info that could help? I'm happy to help even-though I'm not a SwiftUI expert.

Here's my crash stack trace:

Thread 0 name:
Thread 0 Crashed:
0   libsystem_kernel.dylib          0x00000001b4413414 __pthread_kill + 8
1   libsystem_pthread.dylib         0x00000001d092bb40 pthread_kill + 272 (pthread.c:1388)
2   libsystem_c.dylib               0x0000000190838b74 abort + 104 (abort.c:110)
3   libswiftCore.dylib              0x000000018b448f68 swift::fatalError(unsigned int, char const*, ...) + 60 (Errors.cpp:393)
4   libswiftCore.dylib              0x000000018b4490c0 swift::swift_abortRetainUnowned(void const*) + 36 (Errors.cpp:460)
5   libswiftCore.dylib              0x000000018b49888c swift_unknownObjectUnownedLoadStrong + 76 (SwiftObject.mm:895)
6   SwiftUI                         0x000000018dee6ad0 ViewGraph.graphDelegate.getter + 16 (ViewGraph.swift:234)
7   SwiftUI                         0x000000018e3f994c GraphHost.flushTransactions() + 204 (GraphHost.swift:441)
8   SwiftUI                         0x000000018e3f8e10 specialized GraphHost.asyncTransaction<A>(_:mutation:style:) + 252 (<compiler-generated>:0)
9   SwiftUI                         0x000000018dff0500 AttributeInvalidatingSubscriber.invalidateAttribute() + 236 (AttributeInvalidatingSubscriber.swift:89)
10  SwiftUI                         0x000000018dff03fc AttributeInvalidatingSubscriber.receive(_:) + 100 (AttributeInvalidatingSubscriber.swift:53)
11  SwiftUI                         0x000000018dff0b18 protocol witness for Subscriber.receive(_:) in conformance AttributeInvalidatingSubscriber<A> + 24 (<compiler-generated>:0)
12  SwiftUI                         0x000000018e19379c SubscriptionLifetime.Connection.receive(_:) + 100 (SubscriptionLifetime.swift:195)
13  Combine                         0x000000019b0b900c ObservableObjectPublisher.Inner.send() + 136 (ObservableObject.swift:115)
14  Combine                         0x000000019b0b87b4 ObservableObjectPublisher.send() + 632 (ObservableObject.swift:153)
15  Combine                         0x000000019b0a16e8 PublishedSubject.send(_:) + 136 (PublishedSubject.swift:82)
16  Combine                         0x000000019b0c7ffc specialized static Published.subscript.setter + 388 (Published.swift:0)
17  Combine                         0x000000019b0c75dc static Published.subscript.setter + 40 (<compiler-generated>:0)
18  Project Calathea                0x0000000101090054 _hidden#1975_ + 364 (__hidden#2238_:0)
19  SwiftUI                         0x000000018df08338 thunk for @escaping @callee_guaranteed () -> () + 28 (<compiler-generated>:0)
20  SwiftUI                         0x000000018df08360 thunk for @escaping @callee_guaranteed () -> (@out ()) + 28 (<compiler-generated>:0)
21  SwiftUI                         0x000000018df08338 thunk for @escaping @callee_guaranteed () -> () + 28 (<compiler-generated>:0)
22  SwiftUI                         0x000000018def70f0 static Update.end() + 536 (<compiler-generated>:0)
23  SwiftUI                         0x000000018ddff054 AppearanceEffect.disappeared() + 332 (Update.swift:45)
24  SwiftUI                         0x000000018ddff2dc static AppearanceEffect.willRemove(attribute:) + 48 (AppearanceActionModifier.swift:105)
25  SwiftUI                         0x000000018df16b3c closure #1 in AGSubgraphRef.willRemove() + 80 (AttributeGraphAdditions.swift:83)
26  AttributeGraph                  0x00000001afa4066c AG::Subgraph::apply(unsigned int, AG::ClosureFunctionAV<void, unsigned int>) + 420 (ag-closure.h:108)
27  SwiftUI                         0x000000018e3f97f4 GraphHost.updateRemovedState() + 152 (<compiler-generated>:0)
28  SwiftUI                         0x000000018e4c8010 _UIHostingView.updateRemovedState() + 112 (GraphHost.swift:107)
29  SwiftUI                         0x000000018e4ca154 _UIHostingView.__deallocating_deinit + 52 (UIHostingView.swift:1437)
30  SwiftUI                         0x000000018e4ca22c @objc _UIHostingView.__deallocating_deinit + 28 (<compiler-generated>:0)
31  libobjc.A.dylib                 0x000000019ba8a7b0 AutoreleasePoolPage::releaseUntil(objc_object**) + 204 (NSObject.mm:944)
32  libobjc.A.dylib                 0x000000019ba8a650 objc_autoreleasePoolPop + 212 (NSObject.mm:1211)
33  UIKitCore                       0x000000018a3e0104 -[UIView dealloc] + 876 (UIView.m:4639)
34  libobjc.A.dylib                 0x000000019ba69b10 object_cxxDestructFromClass(objc_object*, objc_class*) + 112 (objc-class.mm:455)
35  libobjc.A.dylib                 0x000000019ba80840 objc_destructInstance + 80 (objc-class.mm:469)
36  libobjc.A.dylib                 0x000000019ba8780c _objc_rootDealloc + 80 (objc-runtime-new.mm:8131)
37  UIKitCore                       0x0000000189ef8928 -[UIResponder dealloc] + 156 (UIResponder.m:136)
38  UIKitCore                       0x000000018a3e0120 -[UIView dealloc] + 904 (UIView.m:4640)
39  UIKitCore                       0x00000001896020b8 -[UICollectionViewCell dealloc] + 108 (UICollectionViewCell.m:910)
40  libobjc.A.dylib                 0x000000019ba8a7b0 AutoreleasePoolPage::releaseUntil(objc_object**) + 204 (NSObject.mm:944)
41  libobjc.A.dylib                 0x000000019ba8a650 objc_autoreleasePoolPop + 212 (NSObject.mm:1211)
42  QuartzCore                      0x000000018a87ff60 CA::Context::commit_transaction(CA::Transaction*, double, double*) + 544 (CAInternal.h:330)
43  QuartzCore                      0x000000018a8ab36c CA::Transaction::commit() + 732 (CATransactionInternal.mm:449)
44  QuartzCore                      0x000000018a8ac6fc CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 96 (CATransactionInternal.mm:925)
45  CoreFoundation                  0x000000018748f358 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 36 (CFRunLoop.c:1799)
46  CoreFoundation                  0x00000001874895c4 __CFRunLoopDoObservers + 576 (CFRunLoop.c:1912)
47  CoreFoundation                  0x0000000187489b74 __CFRunLoopRun + 1056 (CFRunLoop.c:2953)
48  CoreFoundation                  0x000000018748921c CFRunLoopRunSpecific + 600 (CFRunLoop.c:3242)
49  GraphicsServices                0x000000019e508784 GSEventRunModal + 164 (GSEvent.c:2259)
50  UIKitCore                       0x0000000189ec2200 -[UIApplication _run] + 1072 (UIApplication.m:3266)
51  UIKitCore                       0x0000000189ec7a74 UIApplicationMain + 168 (UIApplication.m:4738)
52  Project Calathea                0x0000000100fe7770 main + 68 (Auth.swift:7)
53  libdyld.dylib                   0x00000001871496c0 start + 4

Thanks!

Insofan commented 3 years ago

@yonaskolb I have run your demo on Xcode12.2 (12B45b) simulator and I can't reproduce crash. But poster‘s code reproduce crash.

yonaskolb commented 3 years ago

The crash in List and Button (my sample project above) seems to be fixed in iOS 14.2

yonaskolb commented 3 years ago

As for your crash @mjswen0923 (which is indeed not fixed in iOS 14.2) a workaround seems to be to wrap the WebImage in a HStack

TabView {
    Text("testing")
        .tabItem    {
            Text("test")
        }
    HStack {
        WebImage(url: URL(string: "https://raw.githubusercontent.com/SDWebImage/SDWebImage/master/SDWebImage_logo.png"))
    }
        .tabItem    {
            Text("test2")
        }
}

EDIT: I see now @dreampiggy already provided that solution above 😄

dreampiggy commented 3 years ago

Any extra workaround without that HStack to use on WebImage ?

Or can you have a try with other open source SwiftUI component to see whether they can used in TabView natively ? So that I can learn from them:

KFImage: https://github.com/onevcat/Kingfisher/releases/tag/5.15.8 URLImage: https://github.com/dmytro-anokhin/url-image

yonaskolb commented 3 years ago

Saw an interesting reference to SwiftUI crashes in the Kingfisher release notes https://github.com/onevcat/Kingfisher/releases/tag/6.2.0

Not sure if the fix they implemented there helps things here, I haven't delved into how SDWebImage handles this, but might be interesting to look at https://github.com/onevcat/Kingfisher/pull/1642

dreampiggy commented 3 years ago

@yonaskolb We already don't use @State. Can't version 2.0 solve this issue ?

Seems this issue is already stale.

yonaskolb commented 3 years ago

Oh, didn't see there was a release, will test and get back to you!

dreampiggy commented 3 years ago

Actually. TabView has some limitation for tabbar item:

Tab views only support tab items of type Text, Image, or an image followed by text. Passing any other type of view results in a visible but empty tab item.

You can use Image with ImageManager instead to supports dynamic URL bar item. Which may be better and follows Apples framework design.

yonaskolb commented 3 years ago

Looks like the same crash with List and Button is still present before iOS 14.2 with SDWebImageSwiftUI 2.0.1

dreampiggy commented 3 years ago

Should be fixed in v2.0.2

However, I strongly recommended don't use WebImage as the top level View component. Wrap it inside List, HStack is a better idea.

Since the layout of Web URL can not have the intrinsicContentSize (Which may changed when loading image from network). So you'd better provide the frame modifier to limit it container size.