SwiftUI应用开屏广告界面项目(一)

瞎扯

最近开始玩Swift试试macOS和iOS开发

我都快忘了我是啥专业的了
在这里插入图片描述

不想看我瞎扯可以直接跳到这

需求

为iOS应用模拟开屏广告的模式,为应用做一个开屏活动页,远端提供活动页图片;
图片经过3s倒计时后消失,用户可以点击“跳过”按钮提前结束;

源码

废话不多说,先直接上源码。
工程中只修改了ContentView.swift文件,所以这里只放ContentView.swift的代码:

//
//  ContentView.swift
//  iOSTest
//
//  Created by WMIII on 2021/3/21.
//

import SwiftUI
import UIKit
import Combine

class TimeHelp {
    
    var canceller: AnyCancellable?
        
    //每次都新建一个计时器
    func start(receiveValue: @escaping (() -> Void)) {
        let timerPublisher = Timer
            .publish(every: 1, on: .main, in: .common)
            .autoconnect()
        
        self.canceller = timerPublisher.sink { date in
            receiveValue()
        }
    }
    
    //暂停销毁计时器
    func stop() {
        canceller?.cancel()
        canceller = nil
    }
}

struct ContentView: View {
    @State private var remoteImage :UIImage? = nil
    @State var isPresented = false
    let placeholderOne = UIImage(named: "Image1")
    // 这里的Image1为工程资源文件夹中的图片资源名,自己随便创建一个就行
    
    let timer = Timer.publish(every: 1, on: .main, in: .common)
    
    @State private var second = 5
    private let timeHelper = TimeHelp()
    @State private var end = true
                
    var body: some View {
        ZStack
        {
            Button("跳过 \(second)"){
                self.isPresented = true
            }
            .position(x: UIScreen.main.bounds.width - 45, y: 10.0)
            .onAppear()
            {
                guard self.end else {return}
                self.end = false
                self.second = 3
                self.timeHelper.start {
                    // print(second)
                    if self.second > 1 {
                        _ = self.second -= 1
                    }else{
                        //暂停
                        self.end = true
                        self.timeHelper.stop()
                        self.isPresented = true
                    }
                }
            }
            .fullScreenCover(isPresented: $isPresented) {
                print("消失")
            } content: {
                DetailView(message: "I'm missing you")
            }
            
            Image(uiImage: self.remoteImage ?? placeholderOne!)
            // Image(uiImage: self.placeholderOne!)
                .resizable()
                .scaledToFit()
                // .aspectRatio(contentMode: .fill)
                .onAppear(perform: fetchRemoteImg)
        }
    }
    
    func fetchRemoteImg()
    {
        guard let url = URL(string: "https://store.storeimages.cdn-apple.com/8756/as-images.apple.com/is/iphone-12-pro-family-hero?wid=940&hei=1112&fmt=jpeg&qlt=80&.v=1604021663000") else {return}
        
        URLSession.shared.dataTask(with: url)
        {
            (data, response, error) in
            if let img = UIImage(data: data!)
            {
                self.remoteImage = img
            }
            else
            {
                print(error ?? "1")
            }
        }
        .resume()
    }
}


struct DetailView: View{
    let message: String
    
    var body: some View {
        VStack
        {
            Text(message)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

思路分析

由于我刚入门Swift,学艺不精,而且目前SwiftUI的教程比较少,所以有些地方的代码我是直接借(c)鉴(v)别处的,并且我也不能很好的理解。

页面跳转

从开屏广告页回到应用界面的思路,我找到两种:将广告界面贴在主界面上,然后删除;或者通过页面跳转。

虽说贴界面可以通过ZStack,但是我并不会在SwiftUI中删除页面,所以我选择页面跳转的方式。

目前各大博客平台能搜索到的SwiftUI界面跳转方法都是用NavigationView,NavigationLink等方式;虽说简单,但是这种方式不符合我的需求:通过以上方式跳转到的界面左上角会自带一个“返回”按钮,而且页面还会有页眉。

找来找去,发现一个通过fullScreenCover来进行页面跳转的方式。
参考:https://blog.csdn.net/u011146511/article/details/113763403

目前我并没有找到解释fullScreenCover的(中文)API文档;并且这名字听起来貌似也是将一个页面覆盖在原页面上…

// ContentView.swift
import SwiftUI
 
struct ContentView:View {
    @State var isPresented = false
    var body: some View{
        Button("present"){
            self.isPresented = true
        }.fullScreenCover(isPresented: $isPresented) {
        
        } content: {
            DetailView()
        }
   }
}

struct DetailView: View{
    var body: some View {
        VStack
        {
            Text("It's a beautiful night.")
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

点击时将isPresented置为true,然后fullScreenCover就将content中的DetailView展现在界面中。

计时

要求中需要3s的倒计时,所以需要用到SwiftUI中的Timer,所以我们把定时器添加到前面的代码中,同时将本地的一个测试图片显示到界面中,并做一些排版。

参考:https://www.jianshu.com/p/66b9ad87695c

// ContentView.swift
import SwiftUI
import UIKit
import Combine

class TimeHelp {
    var canceller: AnyCancellable?
    //每次都新建一个计时器
    func start(receiveValue: @escaping (() -> Void)) {
        let timerPublisher = Timer
            .publish(every: 1, on: .main, in: .common)
            .autoconnect()
        
        self.canceller = timerPublisher.sink { date in
            receiveValue()
        }
    }
    
    //暂停销毁计时器
    func stop() {
        canceller?.cancel()
        canceller = nil
    }
}

struct ContentView: View {
    @State var isPresented = false
    let placeholderOne = UIImage(named: "Image1")
    
    let timer = Timer.publish(every: 1, on: .main, in: .common)
    
    @State private var second = 5
    private let timeHelper = TimeHelp()
    @State private var end = true
                
    var body: some View {
        ZStack
        {
            Button("跳过 \(second)"){
                self.isPresented = true
            }
            .position(x: UIScreen.main.bounds.width - 45, y: 10.0)
            .onAppear()
            {
                guard self.end else {return}
                self.end = false
                self.second = 3
                self.timeHelper.start {
                    // print(second)
                    if self.second > 1 {
                        _ = self.second -= 1
                    }else{
                        //暂停
                        self.end = true
                        self.timeHelper.stop()
                        self.isPresented = true
                    }
                }
            }
            .fullScreenCover(isPresented: $isPresented) {

            } content: {
                DetailView()
            }
            
            Image(uiImage:placeholderOne!)
                .resizable()
                .scaledToFit()
                .onAppear(perform: fetchRemoteImg)
        }
    }
}

struct DetailView: View{
    var body: some View {
        VStack
        {
            Text("It's a beautiful night.")
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

远程图片获取

在ContentView中添加如下函数:

func fetchRemoteImg()
    {
        guard let url = URL(string: "https://store.storeimages.cdn-apple.com/8756/as-images.apple.com/is/iphone-12-pro-family-hero?wid=940&hei=1112&fmt=jpeg&qlt=80&.v=1604021663000") else {return}
        // 这里的string为图片的地址,这里我用的是Apple官网商店的图片
        URLSession.shared.dataTask(with: url)
        {
            (data, response, error) in
            if let img = UIImage(data: data!)
            {
                self.remoteImage = img
            }
            else
            {
                print(error ?? "1")
            }
        }
        .resume()
    }

在ContentView中添加一行属性:

@State private var remoteImage :UIImage? = nil

同时将ContentView中的Image控件更改为:

// 如果未获取到远端图片,则显示本地默认图片
Image(uiImage: self.remoteImage ?? placeholderOne!)
	.resizable()
	.scaledToFit()
	.onAppear(perform: fetchRemoteImg)

更改完成之后就可以实现需求功能了。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值