Generate Custom UIApplicationShortcutIcon without bundling the image. - swift

I currently have UIApplicationShortcutItem working, however, I would like to use my own custom Icon.
I know that I can use iconWithTemplateImageName to get my own custom icon. However, I would rather not include 100s of icons with the app. It seems that iconWithTemplateImageName requires the image file to be included in the xcassets.
I have a function that downloads and save an image to the Document folder upon the user dynamically adding UIApplicationShortcutItem. Is there a way to referance the newly downloaded image.
How I add UIApplicationShortcutItem
let icon = UIApplicationShortcutIcon(templateImageName: fileName)
let newItem = UIMutableApplicationShortcutItem(type: "Chance", localizedTitle: title, localizedSubtitle: chances.joinWithSeparator(", "), icon: icon, userInfo: ["Items":chances])
existingShortcutItems.append(newItem)
UIApplication.sharedApplication().shortcutItems = existingShortcutItems
Where fileName is the path to an image I have saved. I have tried both the full path and just the file name. Ofcourse that wont work since its not in the xcassets
Is there a way to add the image to the xcassets at runtime?
Is there a way to use an image on the fly?
Working version of the code:
let icon = UIApplicationShortcutIcon(type: .Favorite)
let newItem = UIMutableApplicationShortcutItem(type: "Chance", localizedTitle: title, localizedSubtitle: chances.joinWithSeparator(", "), icon: icon, userInfo: ["Items":chances])
existingShortcutItems.append(newItem)
UIApplication.sharedApplication().shortcutItems = existingShortcutItems

Related

Can I show an image in a HoverProvider?

I am new to vscode extension development so not sure best places to look for help. I want to hover over a word, and if that word matches the name in our icon directory, show a hover with that image. My first try was to use markdown to show the svg image from the web, but I believe that is not allowed for security that code could be executed. Can I show an svg in the markdown in a vscode.Hover? I can either include the svgs in the extension, or expect that the developer has already installed the npm package with the files into the workspace.
There is actually quite rich support for content and styling in MarkdownString in hovers.
You can use svg's directly this way:
const icon = new vscode.MarkdownString('<img src="icon.svg"/>');
icon.baseUri = vscode.Uri.file(path.join(context.extensionPath, 'images', path.sep));
The baseUri property is crucial. Here it gets the svgs from an images folder.
In the below I added the png images to an extension images folder. You can detect what word is hovered and load the corresponding icon.
Below is testing in a plaintext file:
// with this require/import
const path = require('path');
// ...
let disposable4 = vscode.languages.registerHoverProvider('plaintext', {
provideHover(document, position) {
// one way to find the current hovered word
// note that what is a 'word' is languaged-defined and typically does not include hyphens
// const word = document.getText(document.getWordRangeAtPosition(position));
// first check if there is an icon for the hovered word, if not return undefined
// glob the images folder and find 'icon'.svg
// const icon = new vscode.MarkdownString(`<img src="${word}.svg"/>`);
// dimensions not necessary if you aren't changing them
const content = new vscode.MarkdownString(`<img src="favicon144.png" width=144 height=144/>`);
content.appendMarkdown(`$(zap)`); // notice the little "zap" icon in the hover
content.supportHtml = true;
content.isTrusted = true;
content.supportThemeIcons = true; // to supports codicons
// baseUri was necessary, full path in the img src did not work
// with your icons stroed in the 'images' directory
content.baseUri = vscode.Uri.file(path.join(context.extensionPath, 'images', path.sep));
return new vscode.Hover(content, new vscode.Range(position, position));
}
});
There's only very limited Markdown support in hover items and images are not supported there at all, as far as I know.

Resize pdf document downloaded from API in Swift

After a week, I'm pretty sure this can't be done, but I thought I'd give it one last ditch effort.
I have an API that I call that returns a Data object in the response.result.value. That data is a full fledged PDF file. For instance if I call the API with Postman, and then click on save the result, I can open that saved file with any PDF viewer.
Now, that I the data object in my viewController, I can call
data.write(to: pdfURL) and it writes the file to the URL I specified.
At this point the PDF is still good, I can print that URL, and then in finder locate that file and again view it with any PDF viewer, no problem.
Here's where the problem happens. Lastly, I want to send that PDF file to a small label printer, the labels in the printer are 2" wide, and 1" high. The PDF file that I am getting from the API, creates the PDF in 8.5" x 11" size.
So when it is printed on the label, it shrinks the file to fit on the label making the text and images on the label so small that it can't be read.
I can't change the PDF coming from the API.
I can't change any more settings on the printer.
The only chance I have to "zoom in" on this is to change the document or page size of the PDF file.
I have tried getting a handle to the file that is written to disk, then getting its page and then setting its bounds.
But not the page is just blank. I know that PDF cord start with x=0,y=0 in the bottom left corner, so I've used both of these as my page size:
let page = CGRect(x: 0, y: 0, width: 85, height: 40)
let page = CGRect(x: 472, y: 707, width: 85, height: 40)
guard let data = response.result.value else {
print("Did not get PDF data from API")
return
}
let page = CGRect(x: 472, y: 707, width: 85, height: 40)
let documentURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileName = "shelfTag.pdf"
let pdfURL = documentURL.appendingPathComponent("\(fileName)")
do {
print(pdfURL)
try data.write(to: pdfURL)
} catch {
print("Couldn't write PDF to file.)
}
if #available(iOS 11.0, *) {
let pdfDocument = PDFDocument(url: pdfURL)
let pdfPage = pdfDocument?.page(at: 0)
pdfPage?.setBounds(page, for: .mediaBox)
pdfDocument?.write(toFile: pdfURL.path)
} else {
// Fallback on earlier versions
}
Either the image and text is too small to read
or
The printed label is just blank.
PDF functionality in iOS is limited. You could use these classes to recreate a PDF of the desired size if you have access to the data on the PDF. https://developer.apple.com/documentation/uikit/1623915-uigraphicsbeginpdfpagewithinfo?language=objc
The other option is to use a 3rd party app like Foxit. There may be a free versions you could use.
Unfortunately, there is no easy answer!
This looks very promising to me: https://github.com/prachigauriar/ResizePDF
The author describes it this way:
"resizepdf is a tool for macOS that resizes PDFs! It’s written in Swift and is very simple. It has no external dependencies."
In my brief experimentation with it I found that although it's a Mac app intended as a command line tool I think it can be easily migrated to iOS.
I found that the app works but trivial bugs keep it from running right off the bat. (The test that runs on startup looks for a filename that is different from the one the asset has. Match that name on the asset to achieve success. It is not necessary to run the app as a command line tool -- it'll kick off a test task when run in Xcode.)

FontAwesome UITabBarItem not displaying correctly

I am trying to create icons for each of my view controllers, but it is creating a question mark block as if it does not understand the image
let settings = UINavigationController(rootViewController: SettingsController())
let individual = IndividualAthleteController()
var items: [FontAwesome: UIViewController] = [.slidersH: settings,.user: individual]
for (iconString, viewController) in items {
let icon = UIImage.fontAwesomeIcon(name: iconString, style: .brands, textColor: .black, size: CGSize(width: 30, height: 30))
let tabBar = UITabBarItem(title: viewController.title, image: icon, selectedImage: icon)
items[iconString]!.tabBarItem = tabBar
}
viewControllers = Array(items.values)
It is creating this image for each viewController:
What is the problem?
Make sure you're importing .ttf file into your project and set the target of the files. Then, make sure you're updating your plist:
Import .ttf file into you project simply by draggin&drop, check "copy if needed" (Es. fontawesome-webfont.ttf)
Select you .ttf file and in the inspector select the icon above similar to a sheet, then in the section below (Target Membership) select your project as target if not
Finally check you plist and add the key "Fonts provided by application in your", and as item0 (it is an array) put the name of your fonts as value (es. fontawesome-webfont.ttf )
Refer to this link to see images of the previous instructions
If you're using this library Vaberer/Font-Awesome-Swift, make sure you're doing the same as the above steps
NOTE: If you're not using the Vaberer library, give it a chance
Use .solid instead of .brands. Brands uses just the font awesome brands library, for using icons like apple, github, etc.

NSCollectionView Grid of Files Displayed with Icons from Finder's Preview

I am having trouble trying to create an NSCollectionView with icons that are taken from Finder's icon preview.
Ideally, if the file is a dmg it should display the hard drive icon, an mp3 should be the mp3 icon and a photo should display what the photo looks like itself.
There is one post that addresses this issue:
Is it possible to get programmatic access to finder preview images?
But the code is old and does not compile. I am also using Swift in this project.
I used this post to setup a template for my project:
Is there a way to set up a NSCollectionView programmatically in Swift?
Which adds a subview to NSView. If this can be modified to implement the icons, that would be ideal.
In addition I am using a NSFileManager.defaultManager to get the contents of a folder, and would like to display those contents in the collection view.
I am new to developing on the Mac platform and have more experience with iOS, specific answers are much appreciated, thanks!
Update, I was able to figure out how to use what Finder uses with the Quicklook library that Apple provides. Here is part of the code that I used. Note that if you are trying to use Quicklook on a file that does not have a preview, then there will be an error, so in those cases I just used the iconForFile function (below this code block)
let tmp = QLThumbnailImageCreate(kCFAllocatorDefault, tmpURL , CGSize(width: 64, height: 64), nil)
tmpImage = tmp.takeUnretainedValue()
tmpIcon = NSImage(CGImage: tmpImage!, size: NSSize(width: 64, height: 64))
Original:
I was able to find (almost) what I was looking for.
In the NSWorkspace class there is a method
func iconForFile(_ fullPath: String) -> NSImage
That will return an NSImage of the icon. Unfortunately, I do not see a way to get a preview of the image if it is a picture. Nor do I see a way to make the picture larger (only 32x32 pixels).
Hopefully this answer will help others that encounter this problem!
I've used your code from your answer but I noticed that it did not keep the file's aspect ratio and the low res version would just be the downsampled high res version. So based on your answer, here's my solution:
let imageLowResRef = QLThumbnailImageCreate(kCFAllocatorDefault, url as CFURL , CGSize(width: 32, height: 32), nil)
guard imageLowResRef != nil else {
return NSWorkspace.shared.icon(forFile: url.path)
}
let image = NSImage()
let imageLowRes = imageLowResRef!.takeUnretainedValue()
image.addRepresentation(NSBitmapImageRep(cgImage: imageLowRes))
let imageHighResRef = QLThumbnailImageCreate(kCFAllocatorDefault, url as CFURL , CGSize(width: imageLowRes.width*2, height: imageLowRes.height*2), nil)
let imageHighRes = imageHighResRef!.takeUnretainedValue()
image.addRepresentation(NSBitmapImageRep(cgImage: imageHighRes))
Edit: If you add let options = [kQLThumbnailOptionIconModeKey: true] as CFDictionary, you get to the options parameter, you get the preview rendered as icons.

cn1 - get file path to image for share()

I'm trying to use the share() method, including an image, but I'm having trouble supplying the proper path to the image. Where should I put the image file, and what is the path (putting in the default package and trying "jar:///myimage.png" didn't work), and why is this not documented clearly?
image can be stored in storage which is following path for window
C:\Users\userName.cn1
and the image can be read by using following codes
InputStream is = Storage.getInstance().createInputStream("tizbn.JPG");
EncodedImage i = EncodedImage.create(is, is.available());
Loading image from default folder
Image i =EncodedImage.create("/tizbn.png");
Loading image From Theme
EncodedImage current = (EncodedImage) fetchResourceFile().getImage("tizbn.png");
The share API works with https://www.codenameone.com/javadoc/com/codename1/io/FileSystemStorage.html[FileSystemStorage] and not with https://www.codenameone.com/javadoc/com/codename1/io/Storage.html[Storage].
You need to save the file into a file system path which is always an absolute path, we recommend using the app home to store files. There is a sample in the developer guide section on the ShareButton covering this:
Form hi = new Form("ShareButton");
ShareButton sb = new ShareButton();
sb.setText("Share Screenshot");
hi.add(sb);
Image screenshot = Image.createImage(hi.getWidth(), hi.getHeight());
hi.revalidate();
hi.setVisible(true);
hi.paintComponent(screenshot.getGraphics(), true);
String imageFile = FileSystemStorage.getInstance().getAppHomePath() + "screenshot.png";
try(OutputStream os = FileSystemStorage.getInstance().openOutputStream(imageFile)) {
ImageIO.getImageIO().save(screenshot, os, ImageIO.FORMAT_PNG, 1);
} catch(IOException err) {
Log.e(err);
}
sb.setImageToShare(imageFile, "image/png");