how to add custom icons using fontAwesome to UIbutton in swift 4 - ios

I am currently working on an IOS application and i want to add button labels or icon using FontAwesome i have successfully installed cocoapods in my project and now i have no idea of using cocoapods for adding library FontAwesome(More info:-enter link description here) icons in my IOS Application.
I need to know about the procedure of adding FontAwesome using
cocoapods,
and
I need to know if their is another way to add FontAwesome to my project
thanks

There are many ways of using font awesome icons in an iOS application.
You can opt out any one of them according to your understanding and comfort.
Approach 1:
Writing your own logic
Add font awesome files into your compile source and make sure added properly (See the attached pictures)
Keep Unicode string of any font-awesome icon(In the example code I am taking the close icon reference. Its font awesome class and Unicode texts are fa-close and f00d respectively (See example code). In my case, I have a class where I have all font awesome icon string and another class which accept font awesome class string and returns the appropriate Unicode string.
Create an attributed string with that Unicode string and set it to attributedText property (See the example code below).
You can search your desired font awesome string and Unicode here
Code Example
Step1
In this example, I have created an extension which returns the Unicode string.
extension String {
func fontAwesomeString(name: String) -> String {
switch name {
case "fa-close":
return "\u{f00d}"
default: // manage exhaustive case accordingly
}
}
}
Step2
Call above method by passing the appropriate font awesome string.
let iconUnicodeText = String.fontAwesomeString(name: "fa-close")
let iconAttributed = NSMutableAttributedString(string: iconUnicodeText)
self.iConLabel.attributedText = iconAttributed // iConLabel is a control type of UIlabel.
Or if you don't want to organise your source code you can directly create an attributed string with Unicode and set to attributedText property.
Note: You might be required to make changes in above code snippet. As I have written for Swift 4.0
Approach 2:
Using cocoa pods
Once you installed the pod library, you call the appropriate methods shown in the example as below
yourButton.titleLabel?.font = UIFont.fontAwesome(ofSize: 30, style: .brands)
yourButton.setTitle(String.fontAwesomeIcon(name:. gitgub), for : .normal) // you may change icon type with your desired one

If you have not already installed CocoaPods, these are good instructions: https://stackoverflow.com/a/25257238/8534588
Install FontAwesome with CocoaPods:
Open up Podfile which is in the same folder as your .xcodeproj file
Add this line to Podfile to install FontAwesome.swift: pod 'FontAwesome.swift'
Save changes to Podfile
Open up Terminal in the folder that contains Podfile and run the command pod install
How to use FontAwesome icons:
Add import FontAwesome_swift in your code file
Example code:
let image = UIImage.fontAwesomeIcon(name: .checkCircle, style: .solid, textColor: UIColor.black, size: CGSize(width: 40, height: 40))

Use like below:-
Step1 : Add framework like below image
Step 2:Drag and drop all .otf and .swift files into your project
Step 3:import FontAwesome_swift
Step 4: Use below code:-
let imageView = UIImageView(frame: CGRect(x: 80.0, y: 80.0, width: 50, height: 50))
imageView.image = UIImage.fontAwesomeIcon(name: .github, style: .brands, textColor: .black, size: CGSize(width:40,height:40))
self.view.addSubview(imageView)
Result:-

I have done this in Objective C, So hope this would be useful. The procedure will be same but you need to convert the Objective C code to Swift.
So for do this in Objective C,
You can follow the step mentioned in this link to add the FontAwesome manually to your project without using CocoaPod, If you are interested not to use CocoaPod
Manually Add FontAwesome
From that Github project takeout the NSString category class, i.e NSString+FontAwesome
You need to add the fontawesome-webfont.ttf in resource folder as well
NB: For me error was coming after I add NSString Category class mentioned there in the above link, If you are facing the issue like duplicate definition then just rename those enum constants those are not satisfying the variable naming convention. (For me some of the enum constant were using hypen(-) i replaced those with underscore(_)).

Related

Swift Package in workspace: import rule?

I create a swift package in my work space.
I followed this guide just to test things out:
https://sarunw.com/posts/how-to-modularize-existing-ios-projects-using-swift-package/
All went well.
One of the things I added to the package is:
public extension Color {
static let customRed:Color = Color(uiColor: UIColor(named: "customRed", in: .module, compatibleWith: nil)!)
}
I deleted the customRed from the Assets.xcassets in my main app after I added the Assets to the actual package.
Everything works fine now and the package uses the customRed as defined in the package Assets.xcassets.
I have a lot files that use that Color.customRed in the app and I was thinking I had to go to each file and add the import statement for the package at the top. So:
import MyColorPackage
Question: I don't understand why the app works fine without doing that. Files can use the Color.customRed call without adding the import MyColorPackage at the top of the file that uses it. How can files use that customRed without having the import MyColorPackage in the file? App runs fine without importing the module in the files that use the customRed. Why?
The reason for this is due to a longstanding swift bug so you’re not doing anything wrong per se. It has various forms, some fixed over the years, some not but in your case what happens is that the first file in your main project that imports MyColorPackage will cause the whole rest of the project to “see” that Color extension. In my experience this happens only with public extensions nowadays and your package happens to do just that - declare a public extension to SwiftUI’s Color
If you add some public entity in that package, say …
import SwiftUI
public enum MyColorTheme {
public static let myThemeButtonsColor = Color.green
}
… then you won’t be able to use MyColorTheme in any file that doesn’t import MyColorPackage, as per what is intuitively normal.
I would suggest to still add the missing imports whenever you use symbols from that package as this issue might be fixed in a future version and your project will fail to build
Reference: https://github.com/apple/swift/issues/46493

How to append extra value to an array in class from another file using Extension swift

I have class in a file name MyClass.swift
class MyClass {
var arrayOfString : [String] = []
}
I need my team to append strings in this array when needed without modifying in the same file (before runtime) so if there is any way to do this use extension and modify in this array class for example to make a new file called NewClass.swift?
extension MyClass {
arrayOfString = ["New Value"]
}
Add a function to the extension class and ask your team to add the data there.
extension MyClass {
func addDataHere() {
arrayOfString = ["New Value"]
//ASK THEM TO ADD DATA
arrayOfString.append("ONE")
arrayOfString.append("TWO")
}
}
Try this, if you are looking for the same.
If I understand correctly you wish to have different array initialisers in different files which are combined at compile time into a single initialiser, that is using your example convert:
class MyClass {
var arrayOfString : [String] = []
}
and:
extension MyClass {
arrayOfString = ["New Value"]
}
into:
class MyClass {
var arrayOfString : [String] = ["New Value"]
}
and:
extension MyClass {
// arrayOfString = ["New Value"]
}
or something equivalent to that.
I do not believe the Swift language supports that. However Xcode is can help you here, it has two facilities you can use to construct a solution:
Build Phases - Run Script
In your Project's Settings there is an entry "Build Phases" which defines the set of operations Xcode goes through in building your project. The default set is: Target Dependencies, Compile Sources, Link Binary With Libraries and Copy Bundle Resources. The list is processed in order, top to bottom.
You may add other phases including a "Run Script" one which runs a script you write, which could be a shell script, Python code, Ruby code, etc. etc. The phase can optional take specified input files and produce output files.
Xcode provides a temporary build products directory into which you can write output files, any output files are subject to further processing by Xcode.
Build Rules
Also in your Project's Settings there is an entry "Build Rules" which defines how Xcode handles different file types. This allows you to introduce new file extensions which you then process to produce a new file with a known extension in the temporary products directory which Xcode will then further process. For example, you could write files with a .ourSwift extension which a processed by a script you provide into .swift files.
What could you do with these?
Well you could write a script which scans the project's source files, extracts the distributed parts of the initialiser, combines them and writes them into an existing or new file. The design of this and what you implement it in is totally up to you. For example, if you have your team indicate what they need to add to the initialiser by a special comment you might be able to use a simple combination of grep and sed to achieve your goal. Apple used to publish a more involved example of processing .strings files using a Ruby script which you might still be able to find in the dusty corners of the internet.
Xcode's documentation for these features won't win any prizes but that is your primary source; go read, explore, trial and you'll probably quickly have a solution that meets your needs.
HTH
extention Myclass {
arrayofstirng.append("your value")
}

How to use a string defined in project into UILabel defined in Storyboard?

Basically in android studio there is a string.xml file in which you can define the strings that you will be using in your project.
Below I am giving the Android examples of how this is done:
String defined in string.xml:
<string name="lbl_login_banner">Find Professionals</string>
In the layout.xml (which would be equivalent of .storyboard, .xib or .nib):
android:text="#string/lbl_login_banner"
Is it possible to replicate this in Xcode version 9.2 or Swift 4.
In iOS you have to create Localizable.strings file, and inside that file you can define your strings.
"lbl_login_banner" = "Find Professionals";
How you can use it -
In Storyboard you can use the constant in label value like -
In Code -
myLabel.text = NSLocalizedString(lbl_login_banner, comment: "")
You can read documentation on how to use NSLocalizedString.
You can follow this tutorial on how to create and use Localizable.strings file.

Custom font on iOS always uses 'regular' style

I'm using a custom font (BebasNeueLight). It looks like this in Font Book:
I've added it to the iOS project in the usual style; copied it into the project added a key in the plist "Fonts provided by application" and added the name of the file (BebasNeueLight.otf).
In my label in Swift I do the following:
label.font = UIFont(name: "BebasNeueLight", size: 24.0)!
Which is the actual Postscript name of the font.
When I run the app I see the custom font is loaded; but it displays the regular style (which I neither added to my project or specified):
Font book screenshot with the 'regular' style:
Has anyone seen this before? I'm guessing there is something 'wrong' with the font itself. I works fine on Android btw.
-- Edit:
I'm using the correct name, I've gotten this name with fontconfig and Swift code for printing font (and it is loading the custom font; just not the correct style..). Output:
❯ fc-scan --format "%{postscriptname}\n" BebasNeueLight.otf
BebasNeueLight
--
The Storyboard also renders the font 'wrong'; I've selected the font with my label (as attributed so you can see the render preview):
But the Storyboard already renders it as the 'regular' type (just as the app):
So I'm thinking it is a problem with the font itself for some reason.
I guess the problem is at font name "BebasNeueLight", put below function at your app delegate and call it:
func printFonts() {
let fontFamilyNames = UIFont.familyNames
for familyName in fontFamilyNames {
print("------------------------------")
print("Font Family Name = [\(familyName)]")
let names = UIFont.fontNames(forFamilyName: familyName)
print("Font Names = [\(names)]")
}
}
then check the name of loaded font family name may be "BebasNeue-Light"
The problem is that "BebasNeueLight" in font file name does not correspond with real font title name. So you need to find you the font name somehow. One of the variants is:
func listFontsNames(){
for family : String in UIFont.familyNames as [String]
{
print("Family : \(family)")
for name in UIFont.fontNames(forFamilyName: family)
{
print("name : \(name)")
}
}
}
Of course you've added font to project and to info.plist?
1.Add font file into project
2.Add a new entry with the key "Fonts provided by application" in plist file
each of your files, add the file name to this array in Fonts provided by application
3.label.font = [UIFont fontWithName:#"BebasNeueLight" size:15];
Swift.
label.font = UIFont(name:"BebasNeueLight", size:15)
you can print all fonts (see below). You can also check if the font exists.
for family in UIFont.familyNames {
print("\(family)")
for name in UIFont.fontNames(forFamilyName: family) {
print(" \(name)") // <- FontName
}
}
copy and paste your font name from log and try to assign:
label.font = UIFont(name: "<PasteYourFontNameHere>", size: 24.0)!
sometimes the font name is different.
Did you setup everything from xcode etc? If not please follow this
If you are using webfont then download.ttf file and drop it into your project . Check mark on copy items if needed
Next add this on info plist
<key>UIAppFonts</key>
<array>
<string>Your fontname.ttf</string>
<string>Bakersfield Bold.ttf</string>
</array>
Now take a look the font family name. Which you will find on font file also. From where you have downloaded you will get there also. Like i added font which ttf file name is : Bakersfield Bold.ttf for this fontname is : Bakersfield-Bold Thats it Happy coding.
if you already done then follow this steps
label.font = UIFont(name: "BebasNeue-Light", size: 24.0)!
May be here you made a mistake on font name.
The latest iOS SDK and Xcode (9.3) fixes this problem, so I guess it was a bug in IOS < 11.3.
Current version in which it works as expected:
❯ xcodebuild -showsdks
iOS SDKs:
iOS 11.3 -sdk iphoneos11.3
The device also needs to be running at least iOS 11.3!
All the other setup (adding font to plist.info, using correct postscript font-name etc) was correct.

Custom font faces in jsPDF?

Is it possible to include custom fonts in jsPDF ?
With the basic library, if I console log 'doc.getFontList()' I get:
Courier, Helvetica, Times, courier, helvetica, times
But, say I want to use 'Comic Sans' ( not that I would ;o) ) can it be done ?
Even better, could I use a font is locally stored and has been declared in the site with #font-face ?
I found this was possible by modifying jsPDF.js to expose the existing addFont method in the public API.
In jsPDF.js, look for:
//---------------------------------------
// Public API
Add the following:
API.addFont = function(postScriptName, fontName, fontStyle) {
addFont(postScriptName, fontName, fontStyle, 'StandardEncoding');
};
I put this method near other font methods for clarity - API.setFont, API.setFontSize, API.setFontType, etc.
Now in your code, use:
doc.addFont('ComicSansMS', 'Comic Sans', 'normal');
doc.setFont('Comic Sans');
doc.text(50,50,'Hello World');
This works for me with #font-face fonts included with css before loading jsPDF, as well as system fonts. There's probably a better way to do this using jsPDF's plugin framework, but this quick and dirty solution should at least get you going.
Note that doc.getFontList() will not show added fonts:
// TODO: iterate over fonts array or return copy of fontmap instead in case more are ever added.
It seems to be a lot easier with the latest version of jsPDF (1.5.3):
If you look in the folder jsPDF-master > fontconverter, there's a file fontconverter.html. Open in your browser and use the Browse... button to navigate to, and select your .ttf font file.
Click 'Create'.
The page will offer a "download" to be saved. This will produce a .js file called [something like] RopaSans-Regular-normal.js. This needs to be included in your page producing the PDF's. Personally, I've done it in the main page's header (and please note the order of the scripts):
<!-- pdf creation -->
<script src="FileSaver.js-master/src/FileSaver.js"></script>
<script src="jsPDF-master/dist/jspdf.debug.js"></script>
<!-- custom font definition -->
<script src="path-to-the-file-just-saved/RopaSans-Regular-normal.js" type="module"></script>
Now in your PDF generation method in js:
doc.setFont('RopaSans-Regular');
doc.setFontType('normal');
Here is the solution I'm using...
First, as others have mentioned - you need these two libraries:
jsPDF: https://github.com/MrRio/jsPDF
jsPDF-CustomFonts-support: https://github.com/sphilee/jsPDF-CustomFonts-support
Next - the second library requires that you provide it with at least one custom font in a file named default_vfs.js. I'm using two custom fonts - Arimo-Regular.ttf and Arimo-Bold.ttf - both from Google Fonts. So, my default_vfs.js file looks like this:
(
(function (jsPDFAPI) {
"use strict";
jsPDFAPI.addFileToVFS('Arimo-Regular.ttf','[Base64-encoded string of your font]');
jsPDFAPI.addFileToVFS('Arimo-Bold.ttf','[Base64-encoded string of your font]');
})(jsPDF.API);
Obviously, you version would look different, depending on the font(s) you're using.
There's a bunch of ways to get the Base64-encoded string for your font, but I used this: https://www.giftofspeed.com/base64-encoder/.
It lets you upload a font .ttf file, and it'll give you the Base64 string that you can paste into default_vfs.js.
You can see what the actual file looks like, with my fonts, here: https://cdn.rawgit.com/stuehler/jsPDF-CustomFonts-support/master/dist/default_vfs.js
So, once your fonts are stored in that file, your HTML should look like this:
<script src="js/jspdf.min.js"></script>
<script src="js/jspdf.customfonts.min.js"></script>
<script src="js/default_vfs.js"></script>
Finally, your JavaScript code looks something like this:
const doc = new jsPDF({
unit: 'pt',
orientation: 'p',
lineHeight: 1.2
});
doc.addFont("Arimo-Regular.ttf", "Arimo", "normal");
doc.addFont("Arimo-Bold.ttf", "Arimo", "bold");
doc.setFont("Arimo");
doc.setFontType("normal");
doc.setFontSize(28);
doc.text("Hello, World!", 100, 100);
doc.setFontType("bold");
doc.text("Hello, BOLD World!", 100, 150);
doc.save("customFonts.pdf");
This is probably obvious to most, but in that addFont() method, the three parameters are:
The font's name you used in the addFileToVFS() function in the default_vfs.js file
The font's name you use in the setFont() function in your JavaScript
The font's style you use in the setFontType() function in your JavaScript
You can see this working here: https://codepen.io/stuehler/pen/pZMdKo
Hope this works as well for you as it did for me.
I'm using Angular 8 and Todd's answer worked for me.
Once you get the .js file from fontconverter.html, you can import it in typescript like so:
import fontref = require('path/to/font/CustomFont-normal.js')
Then all you have to do to load the font is 'call' fontref:
makePdf() {
let doc = new jsPDF();
fontref; // 'call' .js to load font
doc.getFontList(); // contains a key-value pair for CustomFont
doc.setFont("CustomFont"); // set font
doc.setFontType("normal");
doc.setFontSize(28);
doc.text("Hello", 20, 20);
window.open(doc.output('bloburl')); // open pdf in new tab
}
After looking at the fontconverter.html, and seeing that it does nothing more than package the TTF files into a base64 string inside a JS file, I came up with the following method that I call before creating my document. It basically does what the individual files resulting from fontconverter.html do, just on-demand:
async function loadFont(src, name, style, weight) {
const fontBytes = await fetch(src).then(res => res.arrayBuffer());
var filename = src.split('\\').pop().split('/').pop();
var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(fontBytes)));
var callAddFont = function () {
this.addFileToVFS(filename, base64String);
this.addFont(filename, name, style, weight );
};
jsPDF.API.events.push(['addFonts', callAddFont]);
}
Call it like this:
await loadFont("/css/fonts/exo-2-v9-latin-ext_latin-italic.ttf", "Exo-2", "italic", 400);
await loadFont("/css/fonts/exo-2-v9-latin-ext_latin-regular.ttf", "Exo-2", "normal", 400);
await loadFont("/css/fonts/exo-2-v9-latin-ext_latin-500.ttf", "Exo-2", "normal", 500);
await loadFont("/css/fonts/exo-2-v9-latin-ext_latin-500italic.ttf", "Exo-2", "italic", 500);
It loads the font from the URL, and adds it to the VFS and font manager. Important: the font name cannot include spaces. You won't get any warnings, but the resulting PDF will either not open or the text will look funny.
Some of these answers are outdated, so I am linking the readme file from Mr. Rio himself regarding the latest release as of this post. Below is a copy of the paragraph from that readme file followed by a link to the readme file itself. Hope this additional resource is helpful:
Use of UTF-8 / TTF:
The 14 standard fonts in PDF are limited to the
ASCII-codepage. If you want to use UTF-8 you have to to integrate a
custom font, which provides the needed glyphs. jsPDF supports
.ttf-files. So if you want to have for example chinese text in your
pdf, your font has to have the necessary chinese glyphs. So check if
your font supports the wanted glyphs or else it will show a blank
space instead of the text.
To add the font to jsPDF use our fontconverter in
/fontconverter/fontconverter.html . The fontconverter will create a
js-file with the content of the provided ttf-file as base64 encoded
string and additional code for jsPDF. You just have to add this
generated js-File to your project. You are then ready to go to use
setFont-method in your code and write your UTF-8 encoded text.
https://github.com/MrRio/jsPDF/blob/master/README.md#use-of-utf-8--ttf
//use necessary config, read the docs http://raw.githack.com/MrRio/jsPDF/master/docs/jsPDF.html
import MuliSemiB64 from "../functions/MuliSemiB64";
let doc = new jsPDF({
orientation: "p",
unit: "px",
format: "a5",
});
doc.addFileToVFS("MULI-SEMIBOLD.TTF", MuliSemiB64());
//MuliSemiB64() is a function that returns the Muli ttf file in its base64 string format, convert your font ttf file and copy the string, save to a variable and use the function to return the string. Use a site like https://www.giftofspeed.com/base64-encoder/ for the conversion
doc.addFont("MULI-SEMIBOLD.TTF", "Muli-Semi-Bold", "Semi-Bold");
doc.setFont("Muli-Semi-Bold", "Semi-Bold");
doc.text("Have Fun :*", 35, 25);
The easiest way that I have found by far is using the jspdf-customfonts package.
Simply install the package by
npm i jspdf-customfonts
then add the following files in the head tag of your index.html for default configurations
script src="https://unpkg.com/jspdf#latest/dist/jspdf.min.js"></script>
<script src="dist/jspdf.customfonts.min.js"></script>
<script src="dist/default_vfs.js"></script>
Now you can download the ttf file of whichever font you want. Then go to this site, select your font and copy the code, and you are done!

Resources