首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在数据加载到视图SwiftUI后执行函数

在数据加载到视图SwiftUI后执行函数
EN

Stack Overflow用户
提问于 2021-09-16 13:45:23
回答 1查看 243关注 0票数 0

一旦我的ContentView加载了所有的网络数据,我想要执行快照函数。我对API调用没有问题,我只是想让快照函数在所有数据加载到ContentView之后运行。

按下按钮后的预期结果:按下按钮后的预期效果

按下按钮后的实际结果:按按钮后的实际效果

ContentView.swift

代码语言:javascript
复制
extension View {
    
    func Snapshot() -> UIImage {
        let controller = UIHostingController(rootView: self)
        let view = controller.view
        
        let targetSize = controller.view.intrinsicContentSize
        view?.bounds = CGRect(origin: .zero, size: targetSize)
        view?.backgroundColor = .clear
        
        let renderer = UIGraphicsImageRenderer(size: targetSize)
        
        return renderer.image { _ in
            view?.drawHierarchy(in: controller.view.bounds, afterScreenUpdates: true)
        }
    }
    
}



struct ContentView: View {
    
    @ObservedObject var FetchResults = fetchResults()
    
    var contentView: some View {
        
        ContentView()
        
    }
    
    var body: some View {
        
        Group {
            if FetchResults.dataHasLoaded {
                
                VStack {
                    Text(FetchResults.clout.postFound?.body ?? "n/a")
                        .padding()
                        .background(Color.blue)
                        .mask(RoundedRectangle(cornerRadius: 30, style: .continuous))
                        .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.3), radius: 10, x: 0, y:10)
                        .padding()
                        .frame(maxWidth: 300)
                    
                    
                }
                
                Button(action: {
                    
                    let image = contentView.Snapshot()
                    print(image)
                    
                }, label:{Text("press me to print view")})
                
                
            } else {
                
                Text("loading data")
                
            }
        }
        
        
        
    }
} 

GotPost.swift --运行API调用的ViewModel

代码语言:javascript
复制
class fetchResults: ObservableObject {
    
    @Published var clout = Cloutington()
    @Published var dataHasLoaded = false
    
    
    init() {
        
        getData { clout in
            self.clout = clout
        }
        
    }
    
    private func getData(completion: @escaping (Cloutington) -> ()) {
        
        let parameters =  "{\r\n \"PostHashHex\": \"2f9633c2460f23d9d5690fe9fd058457ebeb01f6f75805aa426cdaab90a1f4b4\"\r\n}"
        let postData = parameters.data(using: .utf8)
        var request =  URLRequest(url: URL(string: "https://bitclout.com/api/v0/get-single-post")!,timeoutInterval: Double.infinity)
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = postData
        request.httpMethod = "POST"
        
        let task =  URLSession.shared.dataTask(with: request) { (responseData, response, error) in

            print(error)
            print(response)
            print(responseData)
            
            if let resData = responseData {
                let decoder = JSONDecoder()
                
                do
                {
                    let finalData = try decoder.decode(Cloutington.self, from: resData)
                    DispatchQueue.main.async {

                        completion(finalData)
                        self.dataHasLoaded = true

                    }
                    
                }
                catch (let error)
                {
                    print(error)
                }

            }
            
        }
        task.resume()
        
    }
    
}

PostFound.swift --模型解析JSON数据

代码语言:javascript
复制
struct Cloutington: Decodable {
    
    var postFound: PostFound?
    
    enum CodingKeys: String, CodingKey {
        case postFound = "PostFound"
        
    }
    
}

struct PostFound: Decodable {
    
    var id: String?
    var postHashHex, posterPublicKeyBase58Check, parentStakeID, body: String?
    var imageURLs: [String]?
    //    var recloutedPostEntryResponse: JSONNull?
    var creatorBasisPoints, stakeMultipleBasisPoints: Int?
    var timestampNanos: Double?
    var isHidden: Bool?
    var confirmationBlockHeight: Int?
    var inMempool: Bool?
    var profileEntryResponse: ProfileEntryResponse?
    var likeCount, diamondCount: Int?
    var isPinned: Bool?
    var commentCount, recloutCount: Int?
    var diamondsFromSender: Int?
    
    enum CodingKeys: String, CodingKey {
        case postHashHex = "PostHashHex"
        case posterPublicKeyBase58Check = "PosterPublicKeyBase58Check"
        case parentStakeID = "ParentStakeID"
        case body = "Body"
        case imageURLs = "ImageURLs"
        case creatorBasisPoints = "CreatorBasisPoints"
        case stakeMultipleBasisPoints = "StakeMultipleBasisPoints"
        case timestampNanos = "TimestampNanos"
        case isHidden = "IsHidden"
        case confirmationBlockHeight = "ConfirmationBlockHeight"
        case inMempool = "InMempool"
        case profileEntryResponse = "ProfileEntryResponse"
        case likeCount = "LikeCount"
        case diamondCount = "DiamondCount"
        case isPinned = "IsPinned"
        case commentCount = "CommentCount"
        case recloutCount = "RecloutCount"
        case diamondsFromSender = "DiamondsFromSender"
    }
}

// MARK: - ProfileEntryResponse
struct ProfileEntryResponse: Decodable {
    var publicKeyBase58Check, username, profileEntryResponseDescription, profilePic: String?
    var isHidden, isReserved, isVerified: Bool?
    var coinPriceBitCloutNanos, stakeMultipleBasisPoints: Int?
    
    enum CodingKeys: String, CodingKey {
        case publicKeyBase58Check = "PublicKeyBase58Check"
        case username = "Username"
        case profileEntryResponseDescription = "Description"
        case profilePic = "ProfilePic"
        case isHidden = "IsHidden"
        case isReserved = "IsReserved"
        case isVerified = "IsVerified"
        case coinPriceBitCloutNanos = "CoinPriceBitCloutNanos"
        case stakeMultipleBasisPoints = "StakeMultipleBasisPoints"
    }
} ```

Really appreciate the help 
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-09-16 15:35:58

如果您遵循命名类型和变量的Swift API设计指南,一般会得到更多更好的帮助。这意味着对属性和方法的初始字母使用小写,对类型的初始字母使用大写。据我所知,您可能来自一个像C#这样的平台,那里的约定是不同的。但是,如果您不以Swift的方式(或者更糟糕的是,在您的代码中,两者都做!)做的事情,您会使我们更难理解您的代码。

此外,这也是一个糟糕的模式:

@ObservedObject var FetchResults = fetchResults()

问题是SwiftUI不理解FetchResults对象的所有权,每次重新创建视图时都会重新创建它。在这种情况下,您应该使用@StateObject

代码语言:javascript
复制
@StateObject var fetchResults = FetchResults()

查看保罗·哈德森撰写的这篇文章,了解何时使用@StateObject和何时使用@ObservableObject的指导。

然而,这并不能解决你发布的问题。代码通过这样的方式创建快照:contentView.Snapshot(),它调用您的contentView计算属性,它从头创建一个新的ContentView,它创建一个新的、卸载的FetchResults (不管您是使用@ObservedObject还是@StateObject)。

您需要重用已经加载其数据的FetchResults,因此只需使用self.snapshot()

代码语言:javascript
复制
Button(
    action: {
        let image = self.snapshot()
        print(image)
    },
    label: {
        Text("press me to print view")
    }
)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69209596

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档