iOS 分享扩展(三):轻松定制 iOS 分享界面,提升用户体验

这里每天分享一个 iOS 的新知识,快来关注我吧

前言

在前两篇文章中,我们分别介绍了如何在 iOS 应用中添加分享扩展,以及如何通过 info.plist 配置文件来限定分享内容的格式。今天,我们将继续深入,探讨如何自定义 ShareViewController 的用户界面(UI),从而提升用户在分享过程中的体验。

往期内容:

iOS 分享扩展(一):如何让你的 App 出现在 iOS 系统的分享面板中

iOS 分享扩展(二):info.plist 文件配置全解析

初识 ShareViewController 的 UI

默认情况下,Xcode 为我们生成的 ShareViewController 是基于 SLComposeServiceViewController 的,这个类提供了一些基础的 UI 组件,比如文本输入框和附件预览。然而,这些默认组件可能无法满足应用的个性化需求,因此我们需要对其进行定制。

默认 ShareViewController 示例

以下是我们在项目中自动生成的 ShareViewController 代码:

swift 复制代码
import UIKit
import Social

class ShareViewController: SLComposeServiceViewController {
    override func isContentValid() -> Bool {
        return true
    }

    override func didSelectPost() {
        self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
    }

    override func configurationItems() -> [Any]! {
        return []
    }
}

自定义 UI 的步骤

1. 使用自定义 View

为了自定义分享页面的 UI,我们可以选择创建一个新的 UIView,并将其添加到 ShareViewController 的视图层次结构中。首先,我们需要创建一个新的 UIView 子类,用于定义自定义 UI 元素。

swift 复制代码
import UIKit

class CustomShareView: UIView {
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupView()
    }
    
    private func setupView() {
        // 设置背景颜色
        self.backgroundColor = UIColor.systemGray6
        
        // 添加自定义子视图,如标签和按钮
        let label = UILabel()
        label.text = "分享你的内容"
        label.textAlignment = .center
        label.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(label)
        
        // 使用自动布局设置位置
        NSLayoutConstraint.activate([
            label.centerXAnchor.constraint(equalTo: self.centerXAnchor),
            label.centerYAnchor.constraint(equalTo: self.centerYAnchor)
        ])
    }
}

2. 在 ShareViewController 中加载自定义 View

接下来,我们在 ShareViewController 中使用这个自定义视图。我们需要在 viewDidLoad 方法中添加代码,将 CustomShareView 加载到视图控制器的视图中。

swift 复制代码
override func viewDidLoad() {
    super.viewDidLoad()
    
    // 移除自带的文本输入框
    self.textView.removeFromSuperview()
    
    // 添加自定义视图
    let customShareView = CustomShareView(frame: self.view.bounds)
    customShareView.translatesAutoresizingMaskIntoConstraints = false
    self.view.addSubview(customShareView)
    
    // 设置自动布局
    NSLayoutConstraint.activate([
        customShareView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
        customShareView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
        customShareView.topAnchor.constraint(equalTo: self.view.topAnchor),
        customShareView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor)
    ])
}

3. 添加交互功能

我们可以在自定义视图中添加按钮、输入框等交互元素,并在 ShareViewController 中实现其功能。例如,添加一个确定分享的按钮和一个取消分享的按钮,来执行自定义的分享操作:

swift 复制代码
class CustomShareView: UIView {
    
    var shareButtonAction: (() -> Void)?
    var cancelButtonAction: (() -> Void)?
    
    private func setupView() {
        // 其他视图设置...
        
        let cancelButton = UIButton(type: .system)
        cancelButton.setTitle("取消", for: .normal)
        cancelButton.addTarget(self, action: #selector(cancelButtonTapped), for: .touchUpInside)
        cancelButton.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(cancelButton)
        
        // 设置按钮位置
        NSLayoutConstraint.activate([
            cancelButton.centerXAnchor.constraint(equalTo: self.centerXAnchor),
            cancelButton.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -60)
        ])
        
        let shareButton = UIButton(type: .system)
        shareButton.setTitle("分享", for: .normal)
        shareButton.addTarget(self, action: #selector(shareButtonTapped), for: .touchUpInside)
        shareButton.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(shareButton)
        
        // 设置按钮位置
        NSLayoutConstraint.activate([
            shareButton.centerXAnchor.constraint(equalTo: self.centerXAnchor),
            shareButton.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -20)
        ])
    }
    
    @objc 
    private func shareButtonTapped() {
        shareButtonAction?()
    }

    @objc
    private func cancelButtonTapped() {
        cancelButtonAction?()
    }
}

ShareViewController 中,设置一下这两个按钮的操作:

swift 复制代码
override func viewDidLoad() {
    super.viewDidLoad()
    
    // 其他视图设置...
    
    let customShareView = CustomShareView(frame: self.view.bounds)
    customShareView.shareButtonAction = {
        self.performCustomShare()
    }
    customShareView.cancelButtonAction = {
        self.extensionContext!.cancelRequest(withError: NSError(domain: "CustomShare", code: 1, userInfo: [NSLocalizedDescriptionKey: "用户取消分享"]))
    }
    self.view.addSubview(customShareView)
}

private func performCustomShare() {
    // 执行自定义分享逻辑
    print("执行自定义分享操作")
    self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}

然后,我们可以把用户分享的内容读出来,显示在自定义视图的 UILabel 中,我这里还是以 URL 为例:

swift 复制代码
override func viewDidLoad() {
    super.viewDidLoad()
    
    // 其他视图设置...
    
    let customShareView = CustomShareView(frame: self.view.bounds)
    customShareView.shareButtonAction = {
        self.performCustomShare()
    }
    customShareView.cancelButtonAction = {
        self.extensionContext!.cancelRequest(withError: NSError(domain: "CustomShare", code: 1, userInfo: [NSLocalizedDescriptionKey: "用户取消分享"]))
    }
    self.view.addSubview(customShareView)

    // 读取用户分享的内容
    if let item = self.extensionContext?.inputItems.first as? NSExtensionItem,
       let itemProvider = item.attachments?.first as? NSItemProvider,
       itemProvider.hasItemConformingToTypeIdentifier("public.url") {
        itemProvider.loadItem(forTypeIdentifier: "public.url", options: nil) { (url, error) in
            if let url = url as? URL {
                DispatchQueue.main.async {
                    customShareView.shareContent = url.absoluteString
                }
            }
        }
    }
}

CustomShareView 中,添加一个 shareContent 属性,用于保存用户分享的内容:

swift 复制代码
var shareContent: String? {
    didSet {
        if let shareContent {
            self.contentLabel?.text = "你要分享的内容为:\(shareContent)"
        }
    }
}

如果你的应用分享更复杂的内容,也可以更定制化的添加更多内容,比如图片、视频等,这里就不一一列举了。最后看一下效果:

总结

通过自定义 ShareViewController 的 UI,我们可以为用户提供更为个性化和友好的分享体验。在今天的文章中,我们介绍了如何创建自定义视图,并将其集成到分享扩展中。希望这篇文章能为你的应用开发提供一些灵感和帮助。

在接下来的文章中,我们将继续探讨更多关于 iOS 分享扩展的高级特性。感谢你的关注和阅读!如果有任何问题或建议,欢迎留言与我交流。

这里每天分享一个 iOS 的新知识,快来关注我吧

本文同步自微信公众号 "iOS新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!

相关推荐
黑化旺仔6 小时前
【OC】KVO
macos·ios·objective-c·cocoa
HouWan8 小时前
SwiftUI 小技巧:如何读取 SwiftUI Font 的详细信息
ios·swiftui·apple
李游Leo8 小时前
HarmonyOS 7 实战开发 05:把页面做到可上线状态
ios·harmonyos
终端安全笔记14 小时前
描述文件、企业证书、MDM 不是三个名字,是三层
android·ios·智能手机
传奇开心果编程14 小时前
【SwiftUI入门练中学】第1课 从零开始
学习·ui·ios·swiftui·swift
丿Wayne20 小时前
iOS Token 刷新实战(Actor 避免并发重复刷新)
ios·swift·token·actor·swift并发
终端安全笔记2 天前
iOS 27 给了租赁一个新工具,但它只认受监督的设备
android·网络·安全·ios
大熊猫侯佩2 天前
独立 App 首发完成 iPhone Duo 展开态适配
ios·swiftui·swift
光影少年2 天前
setImmediate 和 setTimeout(0) 的区别
android·前端·react.js·ios·前端框架