MessageAppExtension:如何将贴纸图像从资产加载到 MSStickerBrowserView?

Posted

技术标签:

【中文标题】MessageAppExtension:如何将贴纸图像从资产加载到 MSStickerBrowserView?【英文标题】:MessageAppExtension: how to load sticker images from assets to MSStickerBrowserView? 【发布时间】:2016-09-16 22:52:31 【问题描述】:

好吧,我知道这对每个人来说都是新的,但我认为这将是一个简单的概念 - 我在这里按照这个来制作自定义贴纸消息应用扩展:

https://code.tutsplus.com/tutorials/create-an-imessage-app-in-ios-10--cms-26870

我已经完全复制了所有内容,并正在尝试创建一个基本的 MSStickerBrowserView 显示(然后使用逻辑过滤,但尚未尝试过)我在我的资产文件夹中的贴纸 png:

该教程似乎不是从资产加载的,而是从他们的项目加载的,无论他们的代码是否像这里一样旧:

var stickers = [MSSticker]()

    func loadStickers() 
        for i in 1...2 
            if let url = Bundle.main.urlForResource("Sticker \(i)",  withExtension: "png")  //ERROR!!
                do 
                    let sticker = try MSSticker(contentsOfFileURL: url, localizedDescription: "")
                    stickers.append(sticker)
                 catch 
                    print(error)
                
            
        
    

我得到了错误

Bundle 没有成员 URLforResource

我在这方面找不到任何东西。如何在应用程序中以编程方式显示我的贴纸?

错误:

这些是我尝试加载的图像,无论其名称如何:

【问题讨论】:

好的,但是看看我的问题是否有错误 - 我怎样才能用这个加载我的资产文件夹的内容? 抱歉,新手 在 Swift 3 中应该是 Bundle.main.url(forResource: String?, withExtension: String?) 对不起,我提供了错误的陈述。立即检查。 好的,这行得通,但是我如何将我的贴纸包文件夹中的所有 png 加载到资产中?我在上面添加了一张图片 【参考方案1】:

教程不使用资产目录的原因是,在调用捆绑包上的 urlForResource 方法时,您无法为放置在 .xcassets 文件夹中的图像获取有效的 fileURL。

您需要像添加其他文件一样单独添加资产。此时在捆绑包上调用 pathForResource 或 urlForResource 将不再返回 nil。

编辑:这是一个函数,它将获取文件夹名称,遍历其内容并返回 [MSSticker]?基于它的发现

func createStickers(from folderName: String) -> [MSSticker]? 

    guard
        let path = Bundle.main.resourcePath
        else  return nil 

    var stickers = [MSSticker]()
    let folderPath = "\(path)/\(folderName)"
    let folderURL = URL(fileURLWithPath: folderPath)

    //get a list of urls in the chosen directory
    do 
        let imageURLs = try FileManager.default.contentsOfDirectory(at: folderURL,
                                                                    includingPropertiesForKeys: nil,
                                                                    options: .skipsHiddenFiles)
        //loop through the found urls
        for url in imageURLs 
            //create the sticker and add it, or handle error
            do 
                let sticker = try MSSticker(contentsOfFileURL: url, localizedDescription: "yourDescription")
                stickers.append(sticker)
             catch let error 
                print(error.localizedDescription)
            
        

     catch let error 
        print(error.localizedDescription)
    

    //return nil if stickers array is empty
    return stickers.isEmpty ? nil : stickers

这应该让你只需调用它并得到你想要的:

let stickers = createStickers(from: "YourFolderName")

请注意不要在文件夹名称的开头包含正斜杠 ('/')。

【讨论】:

是的,我想通了,但我想引入一个包含特定图像的文件夹并遍历它们(不仅仅是单个图像)。到目前为止,我无法引入文件夹,因为文件夹没有任何扩展名,因此您无法使用 urlForResource - 我该怎么做? @skyguy - 我添加了一个功能来完成你所追求的。我已经在一个示例项目中对其进行了测试,并且能够遍历文件夹并使用仅添加到扩展程序中的图像创建贴纸。 我把它放在扩展文件夹中,一切正常 它是一个 .xcassets 文件夹吗? 刚刚再次运行我的...工作正常,但在尝试访问不存在或资产文件夹的文件夹时收到相同的错误消息。我建议查看模拟器目录并按照路径验证它是否确实存在【参考方案2】:

只需将“resourceUrl”替换为:

let url = Bundle.main.url(forResource: "Sticker \(i)", withExtension: "png")

代码在 Swift 3 中被替换。

【讨论】:

【参考方案3】:

您可以将图像放在这样的文件夹中(XCODE Viewport):

它使事情更有条理,但不需要像将它们放在 .xcasset 中那样多的代码。

可以通过创建一个新组而不是通过(右键单击消息扩展并单击新组)创建一个.xcasset来完成:

以下 StickerBrowserView 的代码可以这样调用:

import UIKit
import Messages

class StickerBrowserViewController: MSStickerBrowserViewController 

  var stickers = [MSSticker]()

  func changeBrowserViewBackgroundColor(color: UIColor)
    stickerBrowserView.backgroundColor = color
  

  func loadStickers()

    createSticker(asset: "1", localizedDescription:"grinning face")
    createSticker(asset: "2", localizedDescription:"grimacing face")
    createSticker(asset: "3", localizedDescription:"grinning face with smiling eyes")
    createSticker(asset: "4", localizedDescription:"face with tears of joy")
    createSticker(asset: "5", localizedDescription:"smiling face with open mouth")
    createSticker(asset: "6", localizedDescription:"smiling face with open mouth and smiling eyes")

  

  func createSticker(asset: String, localizedDescription: String)

    guard let stickerPath = Bundle.main.path(forResource:asset, ofType:"png") else 
      print("couldn't create the sticker path for", asset)
      return
    

    // we use URL so, it's possible to use image from network
    let stickerURL = URL(fileURLWithPath:stickerPath)

    let sticker: MSSticker
    do 

      try sticker = MSSticker(contentsOfFileURL: stickerURL, localizedDescription: localizedDescription)
      // localizedDescription for accessibility

      stickers.append(sticker)
    catch 
      print(error)
      return
    

  

  override func numberOfStickers(in stickerBrowserView: MSStickerBrowserView) -> Int
    return stickers.count
  

  override func stickerBrowserView(_ stickerBrowserView: MSStickerBrowserView, stickerAt index: Int) -> MSSticker

    return stickers[index] as MSSticker

  


(Ps. 不是我的博客,是在google上找到的,很有用)

【讨论】:

以上是关于MessageAppExtension:如何将贴纸图像从资产加载到 MSStickerBrowserView?的主要内容,如果未能解决你的问题,请参考以下文章

如何在iOS中将重叠的贴纸与图像合并

如何将图像放在另一个图像视图中

如何本地化 iMessage 贴纸?

如何将图像的名称及其坐标写入 save.txt 文件?

在 Android 上将视频和贴纸图片分享到 Instagram Story

如何使用实时贴纸制作自定义相机