Reputation: 7375
Alright, I know this is new for everybody but I would think it'd be a simple concept - I am following this here to make a custom sticker message app extension:
https://code.tutsplus.com/tutorials/create-an-imessage-app-in-ios-10--cms-26870
Ive copied everything exactly and am trying to create a basic MSStickerBrowserView displaying (then later filtering using logic, but haven't attempted that yet) sticker pngs I have in my assets folder here:
The tutorial did not load from assets it seems but rather just from their project, regardless their code is old as here:
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)
}
}
}
}
I get the error
Bundle has no member URLforResource
I can't find anything on this. How can I just display my stickers programmatically in the app?
Error:
These are the images Im trying to load regardless of their name:
Upvotes: 4
Views: 2549
Reputation: 1
You can put the images in a folder like so (XCODE Viewport):
It make things more organised but doesnt need as much code as if you would put them in a .xcasset.
It can be put done by creating a new group instead of creating an .xcasset by (Right Clicking Message Extension and clicking New Group):
The following code for the StickerBrowserView can be called like so:
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. Not my blog, but found it on google and it has been very useful)
Upvotes: 0
Reputation: 774
Just replace "resourceUrl" with:
let url = Bundle.main.url(forResource: "Sticker \(i)", withExtension: "png")
The code got replaced in Swift 3.
Upvotes: 1
Reputation: 3235
The reason that tutorial doesn't use asset catalogs is that you cannot get a valid fileURL for images placed in an .xcassets folder when calling the urlForResource method on the bundle.
You need to add your assets individually like you would other files you are bringing in to the app. Calling pathForResource or urlForResource on the bundle at that point will no longer return nil.
EDIT: Here is a function that will take a folder name, loop through it's contents and return [MSSticker]? based on what it finds
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
}
This should let you just call this and get what you are after:
let stickers = createStickers(from: "YourFolderName")
Please note not to include the forward slash ('/') at the beginning of the folder name.
Upvotes: 5