SwiftUI 页面导航最佳实践

SwiftUI 页面导航最佳实践
Photo by Chris Lawton / Unsplash

通过全局 Router

  1. 定义一个全局 Router 对象,维护页面跳转类型和参数。
@Observable
final class Router {
    
    public enum Destination: Codable, Hashable {
        case pageA(models: [Model])
        case pageB
    }
    
    var navPath = NavigationPath()
    
    func navigate(to destination: Destination) {
        navPath.append(destination)
    }
    
    func navigateBack() {
        navPath.removeLast()
    }
    
    func navigateToRoot() {
        navPath.removeLast(navPath.count)
    }
}

枚举 Destination 可以指定要跳转到哪个页面以及携带的参数。

  1. 将 Router 和 NavigationStack 绑定在一起。
@Bindable var router = Router()    // 定义 router 变量   

NavigationStack(path: $router.navPath) {
    ContentView()
        .navigationDestination(for: Router.Destination.self) { destination in
            switch destination {
            case .pageA(let models):
                PageAView(models: models)
            case .pageB:
                PageBView()
            }
        }
}
.frame(width: CONTENT_VIEW_WIDTH, height: CONTENT_VIEW_HEIGHT)
.environment(router)

NavigationStack 的 path 传入的是 Router 的 path,这样 Router 就可以控制 NavigationStack 的页面跳转。在 navigationDestination 里处理各种页面的跳转。

.environment(router) 让 Router 传递给视图上的子视图,任意分支的子视图(包括子视图的子视图…)都可以拿到 Router 实例,控制页面跳转。

struct SubView: View {
    @Environment(Router.self) var router: Router
        
    private func gotoPageA() {
        router.navigate(to: .pageA(models: models))
    }
}

进阶版

利用泛型和协议,让路由支持自定义。

public protocol Destination: Hashable, Codable {
    
}

@Observable
final public class Router<Dest: Destination> {
    public var navPath = NavigationPath()
    
    public init() {
        
    }
}

public extension Router {
    func navigate(to destination: Dest) {
        navPath.append(destination)
    }
    
    func navigateBack() {
        navPath.removeLast()
    }
    
    func navigateToRoot() {
        navPath.removeLast(navPath.count)
    }
}

这样不同的业务就可以创建不同类别的页面枚举了。

enum BusinessDestination: Destination {
    case pageA(models: [Model])
    case pageB
}

struct ContainerView: View {
    @Bindable var router = Router<BusinessDestination>()
}

Read more

联通 FTTR 宽带从路由器设置自动重启和穿墙功率

联通 FTTR 宽带从路由器设置自动重启和穿墙功率

几个月前把家里宽带换成了联通的千兆 FTTR 宽带,包含一主一从两个点位。配套光猫设备是华为的星光 F50 尊享版。 主点位放置在客厅茶几上,方便连接电视。从点位放在卧室门口,那里恰好有一个不耽误过路的小拐角可以放路由器。平常我们基本不在客厅活动,其他区域最近的 Wi-Fi 信号源是从路由器,因此我们大多数的设备连接的都是从路由器。从路由器的工作负荷很大。 从路由器个头小主路由器很多,散热不咋地。工作时间久了发热就容易发生数据包堵塞,丢包延迟高。需要把它电源拔掉重启。从宽带开通到现在,数据包堵塞影响网络的情况每个月会发生一次。有一次还影响了居家办公的视频会议。宽带维修师傅也给不出有效的法子,建议就是定期插拔从路由器电源。 从路由器和书房之间隔了两堵墙。信号到我书桌那个位置时,千兆网速已经衰减到只有 400-500Mbps 了,折损将近一半。叠加路由器发热的 debuff,书桌位置的网速最差的时候几乎和百兆宽带差不多。 我尝试过在光猫后台管理将路由器功率设置到「穿墙」模式,但没有任何作用。今天在后台研究了一番发现,原来我之前设置的功率是仅对主路由器生效,从路由器还是标准功率。要修

By Gray
《漫步华尔街(第12版)》读书笔记

《漫步华尔街(第12版)》读书笔记

股票分析 基本面分析 * 基本面分析的四个基本决定因素 * 预期增长率 * 复合增长(复利)对投资决策有很重要的意义。 * 一只股票的股利增长和盈利增长率越高,理性投资者应愿意为其支付越高的价格。 * 推论:一只股票的超常增长率持续时间越长,理性投资者应愿意为其支付越高的价格。 * 预期股利支付率 * 对于预期增长率相同的两只股票来说,持有股利支付率越高的股票,较之股利支付率低的股票,会使你的财务状况更好。 * 在其他条件相同的情况下,一家公司发放的现金股利占其盈利的比例越高,理性投资者应愿意为其股票支付越高的价格。 * 特例,很多处于强劲增长阶段的公司,往往不支付任何股利。这时候不满足「在其他条件相同的情况下」。 * 风险程度 * 在其他条件相同的情况下,一家公司的股票风险越低,理性投资者(以及厌恶风险的投资者)应愿意为其股票支付越高的价格。 * 市场利率水平 * 在其他条件相同的情况下,市场利率越低,理性投资者应愿意为股票支付越高的价格。 * 举例,银行存款利率

By Gray