Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/113.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何在SwiftUI上将来电视图显示为顶部?_Ios_Swift_Swiftui - Fatal编程技术网

Ios 如何在SwiftUI上将来电视图显示为顶部?

Ios 如何在SwiftUI上将来电视图显示为顶部?,ios,swift,swiftui,Ios,Swift,Swiftui,我试图模拟如何在所有视图的顶部显示调用视图。但我有一些不明确的观点: 有没有办法让它变得更简单 在这种情况下,视图层次结构是否受保护 AppView.swift import SwiftUI struct AppView: View { @ObservedObject var callVM: CallViewModel init() { self.callVM = CallViewModel() } var bo

我试图模拟如何在所有视图的顶部显示调用视图。但我有一些不明确的观点:

  • 有没有办法让它变得更简单
  • 在这种情况下,视图层次结构是否受保护
AppView.swift

import SwiftUI

struct AppView: View {
    
    @ObservedObject var callVM: CallViewModel
    
    init() {
        self.callVM = CallViewModel()
    }
    
    var body: some View {
        VStack {
            IncomingCallView(rootView: appView, isActive: self.$callVM.isIncomingCallActive)
            TabView {
                TabOne()
                    .tabItem {
                        Image(systemName: "list.dash")
                        Text("Menu")
                    }

                TabTwo()
                    .tabItem {
                        Image(systemName: "square.and.pencil")
                        Text("Order")
                    }
            }
        }
        .onAppear(perform: load)
    }
    
    var appView: some View {
        Text("")
    }
    
    func load() {
        self.callVM.getCall()
    }
}

struct AppView_Previews: PreviewProvider {
    static var previews: some View {
        AppView()
    }
}
import SwiftUI

struct IncomingCallView<RootView: View>: View {
    private let rootView: RootView
    @Binding var isActive: Bool

    init(rootView: RootView, isActive: Binding<Bool>) {
        self.rootView = rootView
        self._isActive = isActive
    }

    var body: some View {
        rootView
            .background(Activator(isActive: $isActive))
    }

    struct Activator: UIViewRepresentable {
        @Binding var isActive: Bool
        @State private var myWindow: UIWindow? = nil

        func makeUIView(context: Context) -> UIView {
            let view = UIView()
            DispatchQueue.main.async {
                self.myWindow = view.window
            }
            return view
        }

        func updateUIView(_ uiView: UIView, context: Context) {
            guard let holder = myWindow?.rootViewController?.view else { return }

            if isActive && context.coordinator.controller == nil {
                context.coordinator.controller = UIHostingController(rootView: loadingView)

                let view = context.coordinator.controller!.view
                view?.backgroundColor = UIColor.black.withAlphaComponent(1)
                view?.isUserInteractionEnabled = true
                view?.translatesAutoresizingMaskIntoConstraints = false
                holder.addSubview(view!)
                holder.isUserInteractionEnabled = true

                view?.leadingAnchor.constraint(equalTo: holder.leadingAnchor).isActive = true
                view?.trailingAnchor.constraint(equalTo: holder.trailingAnchor).isActive = true
                view?.topAnchor.constraint(equalTo: holder.topAnchor).isActive = true
                view?.bottomAnchor.constraint(equalTo: holder.bottomAnchor).isActive = true
            } else if !isActive {
                context.coordinator.controller?.view.removeFromSuperview()
                context.coordinator.controller = nil
                holder.isUserInteractionEnabled = true
            }
        }

        func makeCoordinator() -> Coordinator {
            Coordinator()
        }

        class Coordinator {
            var controller: UIViewController? = nil
        }
        
        private var loadingView: some View {
            HStack(spacing: 20) {
                
                Button(action: {
                    print("acceptCall pressed")
                    // change UI for accepted call
                }) {
                    Image("acceptCall")
                        .resizable()
                        .frame(width: 50, height: 50, alignment: .center)
                        .aspectRatio(contentMode: .fit)
                }

                Button(action: {
                    // close the view
                    print("rejectCall pressed")
                    self.isActive = false
                }) {
                    Image("rejectCall")
                        .resizable()
                        .frame(width: 50, height: 50, alignment: .center)
                        .aspectRatio(contentMode: .fit)
                }
                
            }
            .frame(width: 300, height: 300)
            .background(Color.primary.opacity(0.7))
            .cornerRadius(10)
        }
    }
}
CallViewModel.swift

import Foundation

class CallViewModel: ObservableObject {
    
    @Published public var isIncomingCallActive = Bool()
    
    init() {
        self.isIncomingCallActive = false
    }
    
    func getCall() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
            self.isIncomingCallActive = true
        }
    }
}
IncomingCallView.swift

import SwiftUI

struct AppView: View {
    
    @ObservedObject var callVM: CallViewModel
    
    init() {
        self.callVM = CallViewModel()
    }
    
    var body: some View {
        VStack {
            IncomingCallView(rootView: appView, isActive: self.$callVM.isIncomingCallActive)
            TabView {
                TabOne()
                    .tabItem {
                        Image(systemName: "list.dash")
                        Text("Menu")
                    }

                TabTwo()
                    .tabItem {
                        Image(systemName: "square.and.pencil")
                        Text("Order")
                    }
            }
        }
        .onAppear(perform: load)
    }
    
    var appView: some View {
        Text("")
    }
    
    func load() {
        self.callVM.getCall()
    }
}

struct AppView_Previews: PreviewProvider {
    static var previews: some View {
        AppView()
    }
}
import SwiftUI

struct IncomingCallView<RootView: View>: View {
    private let rootView: RootView
    @Binding var isActive: Bool

    init(rootView: RootView, isActive: Binding<Bool>) {
        self.rootView = rootView
        self._isActive = isActive
    }

    var body: some View {
        rootView
            .background(Activator(isActive: $isActive))
    }

    struct Activator: UIViewRepresentable {
        @Binding var isActive: Bool
        @State private var myWindow: UIWindow? = nil

        func makeUIView(context: Context) -> UIView {
            let view = UIView()
            DispatchQueue.main.async {
                self.myWindow = view.window
            }
            return view
        }

        func updateUIView(_ uiView: UIView, context: Context) {
            guard let holder = myWindow?.rootViewController?.view else { return }

            if isActive && context.coordinator.controller == nil {
                context.coordinator.controller = UIHostingController(rootView: loadingView)

                let view = context.coordinator.controller!.view
                view?.backgroundColor = UIColor.black.withAlphaComponent(1)
                view?.isUserInteractionEnabled = true
                view?.translatesAutoresizingMaskIntoConstraints = false
                holder.addSubview(view!)
                holder.isUserInteractionEnabled = true

                view?.leadingAnchor.constraint(equalTo: holder.leadingAnchor).isActive = true
                view?.trailingAnchor.constraint(equalTo: holder.trailingAnchor).isActive = true
                view?.topAnchor.constraint(equalTo: holder.topAnchor).isActive = true
                view?.bottomAnchor.constraint(equalTo: holder.bottomAnchor).isActive = true
            } else if !isActive {
                context.coordinator.controller?.view.removeFromSuperview()
                context.coordinator.controller = nil
                holder.isUserInteractionEnabled = true
            }
        }

        func makeCoordinator() -> Coordinator {
            Coordinator()
        }

        class Coordinator {
            var controller: UIViewController? = nil
        }
        
        private var loadingView: some View {
            HStack(spacing: 20) {
                
                Button(action: {
                    print("acceptCall pressed")
                    // change UI for accepted call
                }) {
                    Image("acceptCall")
                        .resizable()
                        .frame(width: 50, height: 50, alignment: .center)
                        .aspectRatio(contentMode: .fit)
                }

                Button(action: {
                    // close the view
                    print("rejectCall pressed")
                    self.isActive = false
                }) {
                    Image("rejectCall")
                        .resizable()
                        .frame(width: 50, height: 50, alignment: .center)
                        .aspectRatio(contentMode: .fit)
                }
                
            }
            .frame(width: 300, height: 300)
            .background(Color.primary.opacity(0.7))
            .cornerRadius(10)
        }
    }
}
导入快捷界面
结构IncomingCallView:视图{
私有let rootView:rootView
@绑定变量是活动的:Bool
init(rootView:rootView,isActive:Binding){
self.rootView=rootView
self.\u isActive=isActive
}
var body:一些观点{
根视图
.background(激活器(isActive:$isActive))
}
结构激活器:UIViewRepresentable{
@绑定变量是活动的:Bool
@状态私有变量myWindow:UIWindow?=nil
func makeUIView(上下文:context)->UIView{
let view=UIView()
DispatchQueue.main.async{
self.myWindow=view.window
}
返回视图
}
func updateUIView(uiView:uiView,context:context){
guard let holder=myWindow?.rootViewController?.view else{return}
如果isActive&&context.coordinator.controller==nil{
context.coordinator.controller=UIHostingController(根视图:loadingView)
让view=context.coordinator.controller!.view
视图?.backgroundColor=UIColor.black.withAlphaComponent(1)
视图?.isUserInteractionEnabled=true
视图?.translatesAutoResizengMaskintoConstraints=false
holder.addSubview(视图!)
holder.isUserInteractionEnabled=true
视图?.leadingAnchor.constraint(等式:holder.leadingAnchor).isActive=true
视图?.trailingAnchor.constraint(等式:holder.trailingAnchor).isActive=true
视图?.topAnchor.constraint(等式:holder.topAnchor).isActive=true
视图?.bottomAnchor.constraint(等式:holder.bottomAnchor).isActive=true
}否则,我会主动的{
context.coordinator.controller?.view.removeFromSuperview()
context.coordinator.controller=nil
holder.isUserInteractionEnabled=true
}
}
func makeCoordinator()->Coordinator{
协调员()
}
班级协调员{
var控制器:UIViewController?=nil
}
私有变量加载视图:一些视图{
HStack(间距:20){
按钮(操作:{
打印(“按下接受呼叫”)
//更改已接受呼叫的用户界面
}) {
图像(“接受呼叫”)
.可调整大小()
.框架(宽度:50,高度:50,对齐:。中心)
.aspectRatio(内容模式:.fit)
}
按钮(操作:{
//关闭视图
打印(“拒绝呼叫已按下”)
self.isActive=false
}) {
图像(“拒绝呼叫”)
.可调整大小()
.框架(宽度:50,高度:50,对齐:。中心)
.aspectRatio(内容模式:.fit)
}
}
.框架(宽度:300,高度:300)
.背景(颜色.主色.不透明度(0.7))
.转弯半径(10)
}
}
}

swiftUI中的某些东西看起来像这样

struct-AppView:View{
@StateObject变量callVM=CallViewModel()
var body:一些观点{
ZStack{
TabView{
文本(“TabOne”)
.tabItem{
图像(系统名称:“list.dash”)
文本(“菜单”)
}
文本(“TabTwo”)
.tabItem{
图像(系统名称:“正方形和铅笔”)
文本(“命令”)
}
}
如果callVM.isIncomingCallActive{
ZStack{
颜色:绿色
VStack{
文本(“来电…”)
按钮(操作:{callVM.isIncomingCallActive=false}){
文本(“取消”)
}
}

}.edgesIgnoringSafeArea(.all)//你为什么在这里使用
UIViewRepresentable
?为什么不在SwiftUI中全部使用?@youjin我发现你下面的建议在展示图纸模型时不起作用。你还有其他建议吗?看起来我应该返回UIViewRepresentable。问题是:嗨,谢谢。但我看到一些空白对于顶部(状态栏)和底部安全区域。我们可以全部覆盖它们吗?编辑代码以覆盖所有安全区域。刚刚添加了
。edgesIgnoringSafeArea
,现在看起来和预期的一样。我设置了ObservedObject,它会继续工作。StateObject要求iOS14作为最低部署目标。同时,观察我认为的更改也会更好。