美文网首页面试宝点
App Clips详细解析(二) —— 一个简单示例(一)

App Clips详细解析(二) —— 一个简单示例(一)

作者: 刀客传奇 | 来源:发表于2020-11-18 18:15 被阅读0次

    版本记录

    版本号 时间
    V1.0 2020.11.18 星期三

    前言

    App Clips是2020年WWDC新推出的功能,它的功能非常强大,因为它使没有您的应用程序的用户仍可以使用其功能。 从订购咖啡到停车,App Clips有很多很好的用途。 下面我们就一起学习和看一下。感兴趣的可以看下面几篇文章。
    1. App Clips详细解析(一) —— 基本概览(一)

    开始

    首先看下主要内容:

    就是一起设计和实现App Clips,内容来自翻译

    接着看下写作环境:

    Swift 5, iOS 14, Xcode 12

    下面就是正文啦

    在2020年苹果全球开发者大会(WWDC)上,苹果发布了App Clips:较小的按需版本的应用程序,允许用户执行特定任务。

    App Clips功能非常强大,因为它们使没有您的应用程序的用户仍然可以使用其功能。从订购咖啡到停车,App Clips有很多很好的用途。更好的是,App Clips提供了发现新应用的绝佳方法!

    在本教程中,您将为SwiftyLemonade创建一个App Clip体验,SwiftyLemonade是一个简单的应用程序,可让您使用App Clip购买柠檬水。在此过程中,您将学到:

    • What an App Clip is.
    • How to add an App Clip target.
    • How to share assets and code.
    • About App Clip experiences and how to make one.
    • How to confirm a user’s location using the Location Confirmation API.
    • Working with App Clip notifications.

    注意:本教程假定您了解SwiftUI的基础知识。如果您不熟悉SwiftUI,请先查看SwiftUI: Getting Started tutorial

    注意:您必须安装Xcode 12才能遵循本教程。您可以在本教程的大部分内容中使用模拟器,但是要测试Location Confirmation API,则需要一台运行iOS 14的设备。为此,您需要先在Starter应用中更新bundle ID,然后才能开始按照本教程的说明进行操作。

    打开入门项目。 在入门项目中,您会找到SwiftyLemonade,该应用程序显示了各大Major League Soccer (MLS)体育场上柠檬水摊位的列表。构建并运行以检出该应用程序:

    该应用程序显示了位于各个MLS体育场的Swifty柠檬水摊位的列表。 您还可以将一个摊位标记为喜欢,并在单独的标签中查看收藏夹列表:

    要收藏柠檬水摊位,请长按列表中的一个项目:

    在这里,您可以选择柠檬水摊位,并订购Swifty著名的柠檬水之一。 这对足球迷来说是一个真正的打击:

    在Xcode中,查看将要处理的主要文件:

    • LemonadeStand.swift包含一个代表柠檬水摊位的struct以及要在应用程序中显示的一系列摊位。
    • Lemonade.swift包含代表柠檬水的struct和两个菜单数组。
    • MenuList.swift显示所选柠檬水摊位的柠檬水菜单。
    • DetailView.swift显示所选柠檬水的详细信息。
    • StandList.swift显示一个可供选择的柠檬水摊位列表。 在这里,您可以长按收藏夹或取消收藏。
    • StandTabView.swift是一个TabView,用于显示柠檬水摊位或标记为收藏的柠檬水摊位的完整列表。
    • LemonadeStandLocations是一个Swift软件包,其中包含Swifty Lemonade摊位的位置。

    在本教程中,您将构建一个App Clip,将您带到LA Galaxy菜单购买柠檬水。


    What Exactly Is an App Clip?

    App Clip是应用程序的轻量级版本,它使用户无需安装完整版本的应用程序即可执行特定任务。这使用户可以在需要时立即访问应用的正确部分。要启动App Clip,请扫描NFC标签,QR码或App Clip代码。此流程称为App Clip experience

    如果用户安装了您的应用程序,则App Clip体验将充当该应用程序的切入点。例如,Coffee特许经营应用程序可能会具有App Clip体验,在扫描时会转到您所在的咖啡店的菜单。或者,如果未安装该应用程序,则会从App Store下载相关的App Clip卡。然后将App Clip Card呈现给用户,以启动此流程。作为开发人员,您可以使用App Store Connect配置App Clip Card,但请记住:它们需要一个主应用程序。

    注意:如果您想了解有关配置App Clip的启动体验的更多信息,请查阅Apple’s documentation on Configuring Your App Clip’s Launch Experience


    Adding an App Clip Target

    首先,将App Clip target添加到项目中,并将其命名为SwiftyLemonadeClip

    确保将Interface设置为SwiftUI,将Life Cycle设置为SwiftUI App。 然后,在出现提示时单击Activate。 一个名为SwiftyLemonadeClip的新组被添加到Project导航器中:

    此外,Xcode为您的App Clip设置名称和bundle identifier。 您可能会注意到,bundle identifier.Clip作为扩展名:

    现在,您已经添加了App Clip target,现在该进行测试了。 构建并运行:

    哇! 这里没有太多的事情。 在下一部分中,您将学习如何在appApp Clip target之间共享代码和资源。


    Sharing Assets and Code Between Targets

    设置好项目后,您就可以开始从AppApp Clip共享资源和代码了!

    注意:App ClipApp可以共享很多内容,但不应共享敏感信息。 如果您想了解有关将数据提供给App Clip的相应App的信息,请查阅Apple’s Documentation

    1. Sharing Code and Assets

    由于App Clips是主App的轻量级版本,因此将存在依赖性。 返回Xcode,单击SwiftyLemonadeClip target,然后在Frameworks,Libraries, and Embedded Content部分中将LemonadeStandLocations Swift软件包添加为依赖项。 您的App Clip现在可以访问柠檬水摊位的位置:

    接下来,共享一些Swift文件。 App Clips将需要了解有关柠檬水摊位的信息。 在项目导航器中单击LemonadeStand.swift,然后在文件检查器中更新target membership,以包括SwiftyLemonadeClip

    完成此操作后,您应该看到很多error

    不用担心! 添加剩余的依赖项后,这些错误将消失。

    就像对LemonadeStand.swift一样,更新以下文件的target membership

    • Lemonade.swift
    • MenuList.swift
    • DetailView.swift
    • OrderPlacedView.swift
    • StandList.swift
    • Assets.xcassets in the SwiftyLemonade group

    很好! 没有更多的错误!


    Designing the App Clip Experience

    App Clip experience是使用URL调用应用程序的切入点。 一个应用程序可能具有许多导致特定任务的App Clip体验URL。 在本教程中,您将在Swifty的一个柠檬水摊位上启动一个App Clip体验URL,其中显示了下订单的菜单。

    首先,在SwiftyLemonadeClip下创建一个新的Swift文件,并将其命名为SwiftyLemonadeClipModel.swift。 禁用SwiftyLemonade target,因为新文件只需要对您的App Clip可用:

    然后,在SwiftyLemonadeClipModel.swift中,在import Foundation下添加以下代码:

    class SwiftyLemonadeClipModel: ObservableObject {
      @Published var selectedStand: LemonadeStand?
    }
    

    在这里,您创建了一个符合ObservableObjectSwiftyLemonadeClipModel类。 您还添加了@Published属性,以将选定的摊位通知您的App Clip

    接下来,必须在SwiftyLemonadeClipApp.swift中实例化模型。 将以下属性添加到该结构体:

      @StateObject private var model = SwiftyLemonadeClipModel()
    

    现在,您必须将此属性提供给App Clip的子视图。 仍在SwiftyLemonadeClipApp.swift中,将body替换为以下内容:

    var body: some Scene {
      WindowGroup {
        //1
        ContentView()
          .environmentObject(model)
      }
    }
    

    在上面的代码中,将model设置为环境对象,使其可用于ContentView视图子层次结构。 接下来,您将确定要选择clip的正确摊位。

    1. Getting App Clip Experience Data

    数据通过App Store Connect中的注册URL传递到App Clip。 注册URL不在本教程的讨论范围之内,但这并不意味着您是失败的团队! 要从URL获取数据,您必须配置App Clip才能这样做。

    首先,单击Signing & Capabilities选项卡下的SwiftyLemonadeClip target,然后添加一个名为appClips:swiftyLemonade.example的新Associated Domain

    接下来,App Clip必须解释数据。 返回SwiftyLemonadeClipApp.swift,将body替换为以下内容以从URL获取查询项:

    var body: some Scene {
      WindowGroup {
        ContentView()
          .environmentObject(model)
          .onContinueUserActivity(
            NSUserActivityTypeBrowsingWeb,
            perform: handleUserActivity) //1
       }
    }
    
    // 2
    func handleUserActivity(_ userActivity: NSUserActivity) {
      //3
      guard 
        let incomingURL = userActivity.webpageURL,
        let components = URLComponents(
          url: incomingURL, 
          resolvingAgainstBaseURL: true),
        let queryItems = components.queryItems 
      else {
        return
      }
    
      //4
      guard 
        let latValue = queryItems.first(where: { $0.name == "lat" })?.value,
        let lonValue = queryItems.first(where: { $0.name == "lon" })?.value,
        let lat = Double(latValue),
        let lon = Double(lonValue) 
      else {
        return
      }
    
      //5
      print("Latitude: \(lat), Longitude: \(lon)")
    }
    

    主要做了这些:

    • 1) 注册NSUserActivityTypeBrowsingWeb的处理程序。当iOS遇到App Clip experience URL时,它将调用此处理程序。
    • 2) 处理URL数据。
    • 3) 仅当存在包含queryItemsURL时才继续执行
    • 4) 检查是否存在名为latlonqueryItems,并将它们分配给latValuelonValue。这些项目代表关联的柠檬水摊位的经度和纬度。如果这些值不存在,则对于此App Clip体验无效。这些值是String类型的,您可以将它们转换为Double类型。
    • 5) 将latlon值打印到控制台。

    2. Simulating a Clip Launch

    要对此进行测试,请创建启动URL。这使您可以模拟从App Clip experience URL启动App Clip。要创建一个,将活动scheme设置为SwiftyLemonadeClip。然后,编辑scheme并通过单击复选框启用_XCAppClipURL环境变量。最后,将其值设置为https://swiftyLemonade.example.com/order?lat=33.8644&lon=-118.2611,如下所示:

    您添加的URL的查询参数是latlon,它们的值表示柠檬水摊位的纬度和经度。

    现在,构建并运行。 您会看到纬度和经度值已打印到控制台:

    3. What Lemonade Stand Is This?!

    是时候找到离您最近的柠檬水摊位了。 返回SwiftyLemonadeClipApp,在import SwiftUI下,添加以下内容:

    import CoreLocation
    

    接下来,在handleUserActivity(_ :)中,用以下代码替换先前添加的print()

    //1
    let location = CLLocationCoordinate2D(
      latitude: CLLocationDegrees(lat),
      longitude: CLLocationDegrees(lon))
    
    //2
    if let stand = standData.first(where: { $0.coordinate == location }) {
      model.selectedStand = stand
      //3
      print("Welcome to \(stand.title)! :]")
    }
    

    这段代码:

    • 1) 使用从URL获得的latlon值创建一个CLLocationCoordinate2D变量
    • 2) 查询standData以查找具有匹配位置的第一个值。 如果找到位置,则将其设置为SwiftyLemonadeClipModel中的selectedStand
    • 3) 将stand名称打印到控制台

    要进行检查,请构建并运行并查看打印到控制台的欢迎消息:

    您已将App Clip配置为从URL获取数据!

    4. Ordering Some Lemonade

    现在该为SwiftyLemonade创建App Clip体验了。 在本部分中,您将采用所选的stand并显示其相关菜单。 然后,用户将能够订购一些柠檬水。

    首先,在SwiftyLemonadeClip下,打开ContentView.swift。 在ContentView中添加以下属性:

    @EnvironmentObject private var model: SwiftyLemonadeClipModel
    

    在这里,您已经添加了先前创建的模型作为环境对象。

    接下来,将body替换为以下内容:

    var body: some View {
      //1
      if let selectedStand = model.selectedStand {
        //2
        NavigationView {
          //3
          MenuList(stand: selectedStand)
        }
      }   
    }
    

    这段代码:

    • 1) 检查模型是否具有selectedStand
    • 2) 添加以MenuList作为根视图的导航层次结构。
    • 3) 实例化selectedStandMenuList以显示菜单项列表。

    要检查这一点,构建并运行:

    现在,您已将模型链接到内容视图,用户可以通过扫描Swifty's LA Galaxy Lemonade Stand上的URL代码订购柠檬水。 App Clip体验应专注于特定任务,例如订购柠檬水。 因此,请注意屏幕底部缺少tab bar,并且没有可供选择的stands列表:

    5. Can’t Find a Lemonade Stand?

    如果该应用找不到某个位置的柠檬水架怎么办? 向用户显示消息会很好。 打开SwiftyLemonadeClipModel.swift并添加以下属性:

    @Published var locationFound = true
    

    此属性跟踪应用程序是否找到柠檬水摊位。 默认情况下是true的,因为它很可能会找到柠檬水摊位。

    接下来,打开SwiftyLemonadeClipApp,并在handleUserActivity(_ :)中,在可选绑定代码之后添加else子句,以找到柠檬水摊位:

    else {
      model.locationFound = false
    }
    

    如果该位置没有柠檬水摊位,请将locationFound设置为false。 您还可以根据需要删除print语句,这仅用于调试。

    现在,回到SwiftyLemonadeClip下的ContentView.swift,将以下内容添加到body的末尾:

    if model.locationFound == false {
      Text("Error finding stand.")
    }
    

    如果附近没有摊位,则会显示一条好消息。

    要对此进行测试,请更新_XCAppClipURL以包含无效的纬度。 将值设置为https://swiftyLemonade.example.com/order?lat=33.8644&lon=0

    构建并运行以查看错误消息:

    很好!现在,您已经更新了App Clip,以处理无效的柠檬水摊位。在继续之前,请将_XCAPPClipURL更改回有效URL:https://swiftyLemonade.example.com/order?lat=33.8644&lon=-118.2611

    为了结束本节,您添加了一个App Clip体验,该体验通过使用URL作为启动参数来启动。该URL提供您所处柠檬水摊位的位置,并显示其菜单。您可以从这里下订单。

    但是,如果配送中心发生混乱,并且将错误的标签发送到错误的柠檬水摊位,该怎么办?您可能会在其他摊位订购柠檬水!或更糟糕的是,如果有人在商店放置了无效的标签进行欺诈,该怎么办?为避免这种情况,Apple引入了一个新的轻量级Location Confirmation API,您将在下一节中对其进行了解。


    Setting up Location Confirmation

    苹果与App Clip一起,引入了Location Confirmation API。该框架提供了足够的信息来验证调用的App Clip是否在预期的位置。Location Confirmation API的工作原理是将App Clip的激活负载与用户的位置进行比较。

    注意:您需要至少运行iOS 14的设备来测试位置确认API。在模拟器上,您只会在控制台中看到一条错误消息。

    SwiftyLemonade中,如果您不在正确的位置,则将禁用下订单的选项。为此,请打开SwiftyLemonadeClipModel.swift并添加以下属性:

    @Published var paymentAllowed = true
    

    此属性确定用户是否可以订购柠檬水。

    要设置位置确认,请打开App ClipInfo.plist。 单击App Clip键旁边的显示三角形,以显示Requests location confirmation键。 将其值更改为YES

    接下来,打开SwiftyLemonadeClipApp.swift,并在import CoreLocation下添加以下代码:

    import AppClip
    

    这使您可以访问App Clip有效负载信息以验证用户的位置。

    现在,在SwiftyLemonadeClipApp.swifthandleUserActivity(_ :)底部添加以下内容:

    //1
    guard let payload = userActivity.appClipActivationPayload else {
      return
    }
    
    //2
    let region = CLCircularRegion(
      center: location, 
      radius: 500,
      identifier: "stand_location"
    )
    
    //3
    payload.confirmAcquired(in: region) { inRegion, error in
      //4
      guard error == nil else {
        print(String(describing: error?.localizedDescription))
        return
      }
    
      //5
      DispatchQueue.main.async {
        model.paymentAllowed = inRegion
      }
    }
    

    这段代码:

    • 1) 通过启动App Clip获取有效载荷信息。 如果不存在,请停止执行。
    • 2) 使用URL中找到的位置创建一个具有500米圆形边界的区域。Core Location使用国际单位制作为距离。 如果您不习惯使用这些单位,那么一米就不止一码了。
    • 3) 检查是否在region内激活了App Clip
    • 4) 如果有error,请将其记录到控制台进行调试。
    • 5) inRegion指示是否在正确的位置调用了App Clip。 使用此值启用或禁用付款。

    注意:如果您想了解App Clips Activation负载,请查看关于APActivationPayloadApple’s Documentation

    1. Using Custom Flags

    接下来,如果用户不在预期的位置,则禁用下订单的功能。 打开在SwiftyLemonade下的Views组中找到的DetailView.swift。 此视图允许您订购柠檬水。 添加以下代码:

    @EnvironmentObject private var model: SwiftyLemonadeClipModel
    

    此代码使DetailView.swift可以访问App Clip的模型。 但是该模型在SwiftyLemonade target中不可用。 如果选择此scheme并尝试构建您的应用程序,则会看到以下错误:

    要解决此问题,请使用Swift Compilation Flag将此代码包装在有条件的代码中。 打开您的App Clip targetBuild Settings,然后将自定义标志APPCLIP添加到DebugRelease schemes中:

    返回到DetailView.swift,使用自定义标志将model包装在条件中:

    #if APPCLIP
    @EnvironmentObject private var model: SwiftyLemonadeClipModel
    #endif
    

    现在,选择App Clip scheme时使用条件中的代码将只编译。 编译应用程序,看看错误消失了!

    接下来,App Clip应显示一条警告,提示您付款被禁用。 为此,请在条件之外添加一个属性:

    @State private var showWarningAlert = false
    

    此属性确定是否显示警告弹窗。

    2. Disabling Ordering

    接下来,在placeOrder()内部,在orderPlaced = true之前添加以下代码:

    //1
    #if APPCLIP
    //2
    guard model.paymentAllowed else {
      //3
      showWarningAlert = true
      return
    }
    #endif
    

    这段代码:

    • 1) 仅当scheme中存在自定义标志时,才在条件条件内执行代码。
    • 2) 检查paymentAllowed是否为true。 这意味着App Clip可以下订单。
    • 3) 如果不允许付款,则将showWarningAlert设置为true,并且不执行placeOrder()中的其余代码。

    3. Showing an Alert

    要在调用placeOrder()时显示alert,请在sheet视图修饰符的右括号后添加以下代码到正文中:

    //1
    .alert(isPresented: $showWarningAlert) {
    //2
      Alert(
        title: Text("Payment Disabled"),
        message: Text("The QR was scanned at an invalid location."),
        dismissButton: .default(Text("OK"))
      )
    }
    

    这段代码:

    • 1) 如果showWarningAlert设置为true,则发出alert
    • 2) 将alert配置为具有标题,消息和关闭按钮。 此alert警告用户不允许付款。

    您可以再测试一步。 除非您居住在洛杉矶银河系所在地Dignity Health Sports Park 500米范围内,否则您将需要在设备上模拟自己的位置。 这样一来,您无需在SwiftyLemonade Stand附近就可以订购柠檬水。

    4. Simulating Location

    要模拟在洛杉矶银河体育场的身影,请在SwiftLemonadeClip组中创建一个GPX文件,并将其命名为LaGalaxy.gpx。 确保选择SwiftLemonadeClip target

    打开LaGalaxy.gpx并将其内容替换为以下内容:

    <?xml version="1.0"?>
    <gpx version="1.1" creator="Xcode">
        <wpt lat="33.8644" lon="-118.2611">
            <name>Dignity Health Sports Park</name>
            <time>2014-09-24T14:55:37Z</time>
        </wpt>
    </gpx>
    

    您添加的代码代表Dignity Health Sports ParkGPS坐标。

    5. Putting it all Together

    最后,要测试每种情况,在构建和运行应用程序时必须设置默认位置。 为此,您必须编辑App Clipscheme并设置默认位置。

    首先,在您不在预期位置的地方测试错误流。 要设置默认位置,请选择SwiftyLemonadeClip scheme,然后选择Edit Scheme

    现在该检查一下您添加的漂亮的错误alert了。 构建并运行该应用程序,然后尝试下订单:

    接下来是时候模拟在洛杉矶了。返回并编辑scheme,并将默认位置设置为您先前创建的GPX文件:

    现在,在设备中设置了体育场的GPS坐标后,您应该可以订购一些柠檬水了。 构建并运行:

    恭喜你! 您已使用Location Confirmation API来验证用户的位置并防止下错订单。

    如果柠檬水准备好时能收到通知,那不是很好吗? 这样,您就可以观看比赛而不会错过任何动作。 当短暂的通知在这里时,请不要担心!


    Using Ephemeral Notifications

    像主应用程序一样,App Clip可以接收通知。 通过在订单准备就绪时通知您,这些可以为App Clip增添巨大价值。 App Clip只能在启动后的很短时间内(最多八个小时)接收通知。

    打开您的App ClipInfo.plist并启用临时通知-它与位置确认权限位于同一位置:

    这将启用App Clip的通知,但用户可以选择加入App Clip Card。 结果,在SwiftyLemonadeClipApp.swift中,在handleUserActivity(_ :)下面添加以下代码:

    func requestNotificationAuthorization() {
      //1
      let notifCenter = UNUserNotificationCenter.current()
      notifCenter.getNotificationSettings { setting in
        //2
        if setting.authorizationStatus == .ephemeral {
          return
        }
        //3
        notifCenter.requestAuthorization(options: .alert) { result, error  in
          print("""
            Authorization Request result: \(result) \
            - \(String(describing: error))
            """)
        }
      }
    }
    

    这段代码:

    • 1) 检索应用程序的通知设置
    • 2) 检查是否已授权该应用接收短暂通知。 如果已经授予访问权限,则无需继续。 但是,如果未授予访问权限,则再次请求它。

    最后,尽管仍在SwiftyLemonadeClipApp.swift中,将以下代码添加到body的末尾。 确保它出现在WindowGroup的右括号内:

    //1
    .onAppear {
      requestNotificationAuthorization()
    }
    

    出现此视图时,此代码调用requestNotificationAuthorization()

    启用通知后,您现在无需错过所有足球比赛。

    注意:如果您想了解有关App Clip通知的更多信息,请查阅 Apple’s Documentation或我们的Push Notifications Tutorial

    在本教程中,您学习了如何:

    • 1) Add an App Clip target
    • 2) Share assets and code
    • 3) Use the Location Confirmation API to verify you are at the correct location
    • 4) Set up App Clip notifications

    如果您喜欢本教程,请查看SwiftUI by Tutorials.。 您将深入研究如何使用简洁的声明性语言来定义应用程序的UI,以及告别大量令人困惑的UIKit代码。

    如果您想了解有关App Clip的更多信息,请查阅 Apple’s Documentation

    后记

    本篇主要讲述了App Clips的一个简单示例,感兴趣的给个赞或者关注~~~

    相关文章

      网友评论

        本文标题:App Clips详细解析(二) —— 一个简单示例(一)

        本文链接:https://www.haomeiwen.com/subject/wfnfiktx.html