Sublime Text 2 - Package Control installed but the list not shown

I am using Sublime Text 2 for Mac. I have installed the Package Control for Sublime Text 2, following the instructions from&nbsp;<a href="https://sublime.wbond.net/installation#st2" target="_blank">https://sublime.wbond.net/installation#st2</a>&nbsp;without any trouble. However, when I open up&nbsp;<code>Ctrl</code>+<code>Shif</code>+<code>P&nbsp;</code>to search for available packages, it does not show any.

I am using Sublime Text 2 for Mac. I have installed the Package Control for Sublime Text 2, following the instructions from https://sublime.wbond.net/installation#st2 without any trouble. However, when I open up Ctrl+Shif+to search for available packages, it does not show any.

See the image screenshot here

Do you have any solutions for it? I try restart Sublime but it doesn't solve the problem.

Connect to Microsoft SQL Server database on MacOS using Python

Connect to Microsoft SQL Server database on MacOS using Python

Connect to your MS SQL using python. The first thing you need is to install Homebrew. You need the copy the content in the square brackets which in my case is “ODBC Driver 13 for SQL Server”. Replace “ODBC Driver 13 for SQL Server” with the content you copied in the square brackets.

There are always situations where I want to automate small tasks. I like using Python for these kind of things, you can quickly get something working without much hassle. I needed to perform some database changes in a Microsoft SQL Server database and wanted to connect to it using Python. On Windows this is usually pretty straight forward. But I use macOS as my main operating system and I had some hurdles along the way so here is a quick how to.

Preparing

If Homebrew isn't installed yet let's do that first. It's an excellent package manager for macOS. Paste the following command in the terminal to install it:

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Once finished run the following commands to install the Microsoft ODBC Driver 13.1 for SQL Server. This driver will be used to connect to the MS SQL database.

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew tap microsoft/mssql-release https://github.com/Microsoft/homebrew-mssql-release
brew update
brew install [email protected] [email protected]
Python package: pyodbc or pypyodbc

With the driver installed, we'll be using a Python package that uses the driver to connect to the database. There are two frequently used packages to connect in Python: pyodbc and pypyodbcpypyodbc is a pure Python re-implementation of pyodbc. The main thing I took a way was that pypyodbcis easier to set up on different platforms. I could not get pyodbc working, it simply wouldn't connect to the database.

Installing pypyodbc can be done using pip, the python package installer.

pip install pypyodbc
Code

Now that the necessary components have been installed, let's open our favorite code editor and write code. The first thing that needs to be done is importing pypyodbc. The script starts with this:

import pypyodbc

Then we need a connection to the database:

sqlConnection = pypyodbc.connect(
                "Driver={ODBC Driver 13 for SQL Server};"
        "Server=<server IP address>;"
        "Database=<database>;"
        "uid=<username>;pwd=<password>");

Note that you have to replace four values in this code: server IP addressdatabase , username and password. The value for the driver is a hard coded value which indicates what driver to use to connect to the database, this value points to the driver that was installed earlier.

Now all what rests is use the connection and run a query.

cursor = sqlConnection.cursor()
cursor.execute("select * from Values")

The cursor now contains the result of our query, the property cursor.rowcount returns the number of rows the query returned. It's now possible to loop through the rows and access the different columns:

for row in cursor:
    print(cursor)
    # first column
    firstColumn = row[0]
    # ...

When we're done, we need to clean up the cursor and database connection by closing it.

cursor.close()
sqlConnection.close()

And that's it, save the file and use the python <filename>.py or python3 <filename.py> command, this depends on your configuration, to run. Here is the entire script:

import pypyodbc

sqlConnection = pypyodbc.connect(
"Driver={ODBC Driver 13 for SQL Server};"
"Server=<server IP address>;"
"Database=<database>;"
"uid=<username>;pwd=<password>");

cursor = sqlConnection.cursor()
cursor.execute("select * from Values")

for row in cursor:
print(cursor)
# first column
firstColumn = row[0]
# ...

cursor.close()
sqlConnection.close()

The with syntax can also be used to automatically close the cursor and the connection, this is another way of writing the same script:

import pypyodbc

with pypyodbc.connect(
"Driver={ODBC Driver 13 for SQL Server};"
"Server=<server IP address>;"
"Database=<database>;"
"uid=<username>;pwd=<password>") as sqlConnection:

with sqlConnection.cursor() as cursor:

    cursor.execute("select * from Values")

    for row in cursor:
        print(cursor)
        # first column
        firstColumn = row[0]
        # ...

If you're looking for some more reading on the topic:

Thanks for reading. If you liked this post, share it with all of your programming buddies!

Further reading

☞ Python for Time Series Data Analysis

☞ Python Programming For Beginners From Scratch

☞ Python Network Programming | Network Apps & Hacking Tools

☞ Intro To SQLite Databases for Python Programming

☞ Ethical Hacking With Python, JavaScript and Kali Linux

☞ Beginner’s guide on Python: Learn python from scratch! (New)

☞ Python for Beginners: Complete Python Programming

How To Use PostgreSQL with Your Ruby on Rails Application on macOS

How To Use PostgreSQL with Your Ruby on Rails Application on macOS

In this tutorial, you will set up a Ruby on Rails development environment connected to a PostgreSQL database on a local macOS machine. You will install and configure PostgreSQL, and then test your setup by creating a Rails application that uses PostgreSQL as its database server.

In this tutorial, you will set up a Ruby on Rails development environment connected to a PostgreSQL database on a local macOS machine. You will install and configure PostgreSQL, and then test your setup by creating a Rails application that uses PostgreSQL as its database server.

Introduction

When using the Ruby on Rails web framework, your application is set up by default to use SQLite as a database. SQLite is a lightweight, portable, and user-friendly relational database that performs especially well in low-memory environments, and will work well in many cases. However, for highly complex applications that need more reliable data integrity and programmatic extensibility, a PostgreSQL database will be a more robust and flexible choice. In order to configure your Ruby on Rails setup to use PostgreSQL, you will need to perform a few additional steps to get it up and running.

Prerequisites

This tutorial requires the following:

  • One computer or virtual machine with macOS installed, with administrative access to that machine and an internet connection.
  • A Ruby on Rails development environment installed on your macOS machine. To set this up, follow our guide on How To Install Ruby on Rails with rbenv on macOS. This tutorial will use version 2.6.3 of Ruby and 5.2.3 of Rails; for information on the latest versions, check out the official sites for Ruby and Rails.
Step 1 — Installing PostgreSQL

In order to configure Ruby on Rails to create your web application with PostgreSQL as a database, you will first install the database onto your machine. Although there are many ways to install PostgreSQL on macOS, this tutorial will use the package manager Homebrew.

There are multiple Homebrew packages to install different versions of PostgreSQL. To install the latest version, run the following command:

brew install postgresql

If you would like to download a specific version of PostgreSQL, replace postgresql in the previous command with your desired package. You can find the available packages at the Homebrew website.

Next, include the PostgreSQL binary in your PATH variable in order to access the PostgreSQL command line tools, making sure to replace the 10 with the version number you are using:

echo 'export PATH="/usr/local/opt/[email protected]/bin:$PATH"' >> ~/.bash_profile

Then, apply the changes you made to your ~/.bash_profile file to your current shell session:

source ~/.bash_profile

To start the service and enable it to start at login, run the following:

brew services start [email protected]

Check to make sure the installation was successful:

postgres -V

You will get the following output:

Output
postgres (PostgreSQL) 10.9 

Once PostgreSQL is installed, the next step is to create a role that your Rails application will use later to create your database.

Step 2 — Creating a Database Role for Your Application

In PostgreSQL, roles can be used to organize permissions and authorization. When starting PostgreSQL with Homebrew, you will automatically have a superuser role created with your macOS username. In order to keep these superuser privileges separate from the database instance you use for your Rails application, in this step you will create a new role with less access.

To create a new role, run the following command, replacing appname with whatever name you'd like to give the role:

createuser -P -d appname

In this command, you used createuser to create a role named appname. The -d flag gave the role the permission to create new databases.

You also specified the -P flag, which means you will be prompted to enter a password for your new role. Enter your desired password, making sure to record it so that you can use it in a configuration file in a future step.

If you did not use the -P flag and want to set a password for the role after you create it, enter the PostgreSQL console with the following command:

psql postgres

You will receive the following output, along with the prompt for the PostgreSQL console:

Output
psql (10.9)
Type "help" for help.
 
postgres=#

The PostgreSQL console is indicated by the postgres=# prompt. At the PostgreSQL prompt, enter this command to set the password for the new database role, replacing the highlighted name with the one you created:

\password appname

PostgreSQL will prompt you for a password. Enter your desired password at the prompt, then confirm it.

Now, exit the PostgreSQL console by entering this command:

\q

Your usual prompt will now reappear.

In this step, you created a new PostgreSQL role without superuser privileges for your application. Now you are ready to create a new Rails app that uses this role to create a database.

Step 3 — Creating a New Rails Application

With your role configured for PostgreSQL, you can now create a new Rails application that is set up to use PostgreSQL as a database.

First, navigate to your home directory:

cd ~

Create a new Rails application in this directory, replacing appname with whatever you would like to call your app:

rails new appname -d=postgresql

The -d=postgresql option sets PostgreSQL as the database.

Once you've run this command, a new folder named appname will appear in your home directory, containing all the elements of a basic Rails application.

Next, move into the application's directory:

cd appname

Now that you have created a new Rails application and have moved into the root directory for your project, you can configure and create your PostgreSQL database from within your Rails app.

Step 4 — Configuring and Creating Your Database

When creating the development and test databases for your application, Rails will use the PostgreSQL role that you created in Step 2. To make sure that Rails creates these databases, you will alter the database configuration file of your project. You will then create your databases.

One of the configuration changes to make in your Rails application is to add the password for the PostgreSQL role you created in the last step. To keep sensitive information like passwords safe, it is a good idea to store this in an environment variable rather than to write it directly in your configuration file.

To store your password in an environment variable at login, run the following command, replacing APPNAME with the name of your app and PostgreSQL_Role_Password with the password you created in the last step:

echo 'export APPNAME_DATABASE_PASSWORD="PostgreSQL_Role_Password"' >> ~/.bash_profile

This command writes the export command to your ~/.bash_profile file so that the environment variable will be set at login.

To export the variable for your current session, use the source command:

source ~/.bash_profile

Now that you have stored your password in your environment, it's time to alter the configuration file.

Open your application's database configuration file in your preferred text editor. This tutorial will use nano:

nano config/database.yml

Under the default section, find the line that says pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> and add the following highlighted lines, filling in your credentials and the environment variable you created. It should look something like this:

config/database.yml

...
default: &default
  adapter: postgresql
  encoding: unicode
  # For details on connection pooling, see Rails configuration guide
  # http://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: appname
  password: <%= ENV['APPNAME_DATABASE_PASSWORD'] %>
 
development:
  <<: *default
  database: appname_development
...

This will make the Rails application run the database with the correct role and password. Save and exit by pressing CTRL+X, Y, then ENTER.

For more information on configuring databases in Rails, see the Rails documentation.

Now that you have made changes to config/database.yml, create your application's databases by using the rails command:

rails db:create

Once Rails creates the database, you will receive the following output:

Output
Created database 'appname_development' 
Created database 'appname_test' 

As the output suggests, this command created a development and test database in your PostgreSQL server.

You now have a PostgreSQL database connected to your Rails app. To ensure that your application is working, the next step is to test your configuration.

Step 5 — Testing Your Configuration

To test that your application is able to use the PostgreSQL database, try to run your web application so that it will show up in a browser.

First, you'll use the built-in web server for Rails, Puma, to serve your application. This web server comes with Rails automatically and requires no additional setup. To serve your application, run the following command:

rails server --binding=127.0.0.1

--binding binds your application to a specified IP. By default, this flag will bind Rails to 0.0.0.0, but since this means that Rails will listen to all interfaces, it is more secure to use 127.0.0.1 to specify the localhost. By default, the application listens on port 3000.

Once your Rails app is running, your command prompt will disappear, replaced by this output:

Output
=> Booting Puma
=> Rails 5.2.3 application starting in development
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.12.1 (ruby 2.6.3-p62), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://127.0.0.1:3000
Use Ctrl-C to stop 

To test if your application is running, open up a new terminal window on your server and use the curl command to send a request to 127.0.0.1:3000:

curl http://127.0.0.1:3000

You will receive a lot of output in HTML, ending in something like:

Output
...
        <strong>Rails version:</strong> 5.2.3<br />
        <strong>Ruby version:</strong> 2.6.3 (x86_64-darwin18)
      </p>
    </section>
  </div>
</body>
</html>

You can also access your Rails application in a local web browser by visiting:

http://127.0.0.1:3000

At this URL, you will find a Ruby on Rails welcome page:

This means that your application is properly configured and connected to the PostgreSQL database.

Conclusion

In this tutorial, you created a Ruby on Rails web application that was configured to use PostgreSQL as a database on a local macOS machine.

Getting Started with macOS Programming

Getting Started with macOS Programming

Let’s go together to build our first macOS application!

Dear readers, let me welcome you and start by saying that this tutorial is the beginning of a new journey and new explorations, as it’s the first of a series of tutorials on a new topic: macOS programming!

Developing for macOS and creating desktop applications is a wonderful process if you want to go down that road. If you are coming from an iOS background like me, then you will find exciting and challenging at the same time to be able to make apps for both systems. What makes it even better is one simple fact: There are lots of common things between iOS and macOS programming. Several frameworks and SDKs, the language itself (Swift), even the coding style that one has used to remain almost the same. But macOS programming is not meant for people being iOS developers already. New programmers who have started learning Swift and they want to make their own desktop applications can follow along as well!

Starting from this tutorial we are going to meet and learn key concepts on macOS programming. I am planning to present various topics for which I will highlight their most important concepts and I will show techniques, how-to and best practices. It is obvious that it would take a series of books to cover everything about macOS programming, not just a series of tutorials. However, what I’m going to show you starting from this tutorial and onwards not only will get you started, but it will enable you to build full applications and it will put you on the right track so you know how to look further on topics you are interested in. Whenever possible, we will be going through the making process of a new macOS app that will have some usefulness at the end. Something that you can take with you when finish reading each post.

So, once again welcome to a new exciting journey! Let’s go together to build our first macOS application!

Our Roadmap

In this post we are going to see the basics of a macOS app through the creation of a simple, but at the same time useful for many developers app: A font viewer that will let us choose font families and it will be displaying the PostScript names of the available fonts. Clarifying why this is useful: The PostScript name is the font name we write in code when creating a NSFont object. Usually it’s not the same to the font’s file name, and without knowing the PostScript it’s impossible to create font objects in code or to add custom fonts into projects. There’s a manual process to reveal PostScript names as described here, but why not to have a macOS app that will let us get it instantly?

Our menu today contains a lot of key stuff:

  • How to create a new macOS project.
  • What the most important parts of the generated project are.
  • What is a window controller and how to configure its contained window, including size, position, title, and a lot more.
  • How to add graphical controls into a view controller.
  • How to interact with those graphical controls, update their values and react on actions triggered by them.
  • How to create additional window controllers.
  • How to change a window’s appearance so it looks like a utility or auxiliary panel.
  • How to load and present and close a window programmatically.

There are even more things to discuss in this post in addition to those listed above. We will talk about new classes that will be proved extremely valuable for our cause, we will talk about the custom logic that we will implement in the various parts of the app, and we will see small or big details that will produce at the end a complete project.

Here is what you are going to have in your hands by the time you will leave here:

Creating Your First Mac App

Launch Xcode, and then choose to create a new project:

In the first step of the guide that appears next do the following:

  • How to create a new macOS project.
  • What the most important parts of the generated project are.
  • What is a window controller and how to configure its contained window, including size, position, title, and a lot more.
  • How to add graphical controls into a view controller.
  • How to interact with those graphical controls, update their values and react on actions triggered by them.
  • How to create additional window controllers.
  • How to change a window’s appearance so it looks like a utility or auxiliary panel.
  • How to load and present and close a window programmatically.

Once you do so, it’s time to “baptise” the project and set all the rest initial information. Since we’re going to create our custom font viewer, why not to call it just like that, Font Viewer? Set that as the value to the Product Name field, and configure the other properties such as Team, Organization Name, Organization Identifier. Generally, make sure that your window looks like the next one:

Finally, choose a place to save the project on your disk, and finish with the creation process.

Running The App

While having Font Viewer project open in Xcode, press Cmd + R on your keyboard to run the app. Here’s what you’ll see appearing on your screen:

Congratulations! You just ran your first macOS app!

It’s an empty window for now, but it doesn’t matter as we will change that. Look and play around with it. You will notice that standard behaviour and attributes are assigned by default to the window, such as resizing, moving or going full screen. Also, there’s the main menu at the top bar, where some common functionalities are provided already, while some others are just disabled as they don’t trigger any action.

Exploring The Project

If you have prior experience to iOS development, you will find out that a macOS project looks pretty much the same to an iOS project. Project Navigator lists all files and groups, tabs like General, Capabilities, Build Settings, etc are here too, and generally everything looks familiar. Displayed settings and options are specific to macOS though.

In the Project Navigator you will find all files and groups that Xcode creates by default for a Cocoa App. What is new here (comparing again to iOS projects), is an .entitlements file. This is a property list file that contains rights an app is granted with. Most of the times there is no need to edit it manually. Changes made through the Capabilities tab update this file automatically.

Other than that, two code files are created automatically. AppDelegate.swift and ViewController.swift. We will add more code to ViewController.swift in a while. There is also:

  • How to create a new macOS project.
  • What the most important parts of the generated project are.
  • What is a window controller and how to configure its contained window, including size, position, title, and a lot more.
  • How to add graphical controls into a view controller.
  • How to interact with those graphical controls, update their values and react on actions triggered by them.
  • How to create additional window controllers.
  • How to change a window’s appearance so it looks like a utility or auxiliary panel.
  • How to load and present and close a window programmatically.

Looking at the General tab of the Font Viewer target, in the Identity section you can find the Bundle Identifier, as well as the Version and Build Number. But what is more interesting here, is the Application Category popup, where you can find all available app categories also found on App Store. This is the place where we set the category of our app. Which category would be suitable for us here? We could assign it under Developer Tools since it’s going to display font information, but we could also have it in the Utilities category. Right now it doesn’t really matter as we are not going to publish it, but remember to choose a category for your app before you send it to the App Store (it’s still okay if you don’t, you can choose app category on the App Store as well, but why not to do it here?).

Looking a bit lower you will see the Deployment Info section. Here you specify the minimum macOS version required by your app to run. You can have it run on macOS Mojave only (10.14), or enable it running on High Sierra (10.13) or older versions too. Keep that option in mind if you ever want to support older operating systems.

Take your time to go through every aspect of the project. Switch to the Capabilities tab, and see what kind of options are available, or go to Build Settings and see if you find something interesting there too. Once you finish your exploration, let’s take a few moments to see what Main.storybard file contains.

Exploring The Main.storyboard

Clicking on the Main storyboard file in the Project Navigator, the automatically created, default user interface will be revealed in Interface Builder. Any Cocoa based app contains three default scenes:

  • How to create a new macOS project.
  • What the most important parts of the generated project are.
  • What is a window controller and how to configure its contained window, including size, position, title, and a lot more.
  • How to add graphical controls into a view controller.
  • How to interact with those graphical controls, update their values and react on actions triggered by them.
  • How to create additional window controllers.
  • How to change a window’s appearance so it looks like a utility or auxiliary panel.
  • How to load and present and close a window programmatically.

Let’s focus on some interesting details now. Click on the window in the window controller scene, and open Attributes Inspector in the inspectors panel of Xcode. This is what you should be seeing:

For some of them, just enabling or disabling options has immediate visual effect on the window. For some others it has not. Let me highlight the most important ones, but if you find yourself needing information for options not mentioned below, feel free to search for them on the web.

  • How to create a new macOS project.
  • What the most important parts of the generated project are.
  • What is a window controller and how to configure its contained window, including size, position, title, and a lot more.
  • How to add graphical controls into a view controller.
  • How to interact with those graphical controls, update their values and react on actions triggered by them.
  • How to create additional window controllers.
  • How to change a window’s appearance so it looks like a utility or auxiliary panel.
  • How to load and present and close a window programmatically.

Leaving the rest options to their default settings makes sure that a window fits to the general macOS environment and it follows workflows that users are already familiar with. Of course, you can find additional information about them and their purpose if you wish so, I just highlighted the most important ones here.

With the window still being selected, show the Size Inspector. Here, you can set the content size of the window, the allowed maximum and minimum size, as well as the initial place of the window on screen.

Setting the content size (width and height) makes the obvious, it changes the window’s default content size. By leaving the Minimum Content Size and Maximum Content Size unchecked, users can resize the window and make it as small or as big they want. To limit the minimum content size so users cannot decrease it further than that, just enable the Minimum Content Size checkbox and specify values for the min width and height. Similarly, enable the Maximum Content Size checkbox to prevent your window grow more than the values you specify.

To keep a constant content size and disallow resizing, then set the exact same values to both minimum and maximum content size.

By default a window is displayed to the bottom left side of the screen. You can change that by either dragging the window sample in the small screen preview window, or just change the initial position X and Y values. Just remember: coordinates in macOS are not like iOS. The Y=0 point is the bottom side of the screen, not the top.

Windows can also be shown centered on the screen. To do that, click on the Proportional Horizontal and Proportional Vertical popup buttons, and select Center Horizontally and Center Vertically respectively. The screen sample in the Size inspector will be updated, and you can verify that by running the app; the window will be shown on the center of the screen.

Setting Up The UI

After that quick walkthrough to the macOS project, let’s do some real work on our app. For starters, select the default Window and open the Size Inspector in the inspectors panel. Change the Content Size to 370×250. Then, select the view controller’s view and do the same.

Now let’s add the graphical controls to the default view of the view controller.

Begin by clicking on the Library Button on Xcode to open the Objects Library:

In the Objects Library, type popup in the top search field:

Choose the Pop Up Button item, and drag and drop it to the view controller’s view. Select the popup control you just dragged to the view controller, and press Cmd + D on your keyboard to duplicate it.

Select both popup buttons, and add the following constraints: Top: 20, Leading: 20, Trailing: 20, Height: 21.

Following the above steps, let’s add also a push button and a label:

  1. Open the Objects Library again, and type button.
  2. Drag and drop a push button to view controller’s view below the popups.
  3. Set its constraints: Trailing: 20, Bottom: 20, Width: 120, Height: 21.
  4. Double click on the button to change its title to: Display All
  5. Open the Objects Library one last time, and type label in the search field.
  6. Drag and drop a label object into the view controller, under the popups but above the push button.
  7. Set the following constraints for the label: Top: 20, Leading: 20, Trailing: 20, Height: 80.

At the end, your view should be similar to this one:

The first popup button will be displaying all available font families on the system, while the second will contain all available font types (such as bold, italic, etc) for any selected font family in the first popup.

Label will show the PostScript name of the selected font family and type, formatted accordingly.

Lastly, the “Display All” button will be used to show all available font types of a font family at once. More about that later.

IBOutlet Properties And IBAction Methods

We will come to the need to interact with the controls we just added soon, so it’s necessary to create and connect IBOutlet properties and IBAction methods to them. Open the ViewController.swift file, and to the top of the class add the next IBOutlet property declarations:

@IBOutlet weak var fontFamiliesPopup: NSPopUpButton!
&nbsp;
@IBOutlet weak var fontTypesPopup: NSPopUpButton!
&nbsp;
@IBOutlet weak var sampleLabel: NSTextField!

Also, define the following IBAction methods:

@IBAction func handleFontFamilySelection(_ sender: Any) {
&nbsp;
}
&nbsp;
&nbsp;
@IBAction func handleFontTypeSelection(_ sender: Any) {
&nbsp;
}
&nbsp;
&nbsp;
@IBAction func displayAllFonts(_ sender: Any) {
&nbsp;
}

Back to the Main.storyboard file, select the view controller object in the document outline:

In the inspectors panel, select to open the Connections inspector, where you will find all the IBOutlet properties and IBAction methods previously declared. Make the connections as follows:

  • How to create a new macOS project.
  • What the most important parts of the generated project are.
  • What is a window controller and how to configure its contained window, including size, position, title, and a lot more.
  • How to add graphical controls into a view controller.
  • How to interact with those graphical controls, update their values and react on actions triggered by them.
  • How to create additional window controllers.
  • How to change a window’s appearance so it looks like a utility or auxiliary panel.
  • How to load and present and close a window programmatically.

Before we make the simple user interface we just created usable, let’s take a look at the controls we just added. By default, each popup button contains three items, where each one is a menu item (more about menus and menu items in a future post). These can be changed either by double clicking on the popup button and then by double clicking on each item, or by selecting the popup button and spotting each item to the Document Outline.

In this demo application, we will change the menu items programmatically, but Interface Builder is a good option to do that if you have a constant set of items that are not meant to be changed on the fly.

Note: Popup button items can be always updated programmatically regardless of whether an initial set of real items has been set through Interface Builder.

In the Attributes inspector you can find all configurable properties of the popup button (after selecting one). For example, you can define the default selected item, or to set font properties and text alignment.

Similarly, label’s and button’s properties can be changed in the Attributes inspector too if you select the label or button object in the view controller. Feel free to look around and experiment a bit by changing any properties you want. It doesn’t matter if you “damage” any control by accident; just delete it and create a new one by following the steps described above.

Another interesting point is the object hierarchy and the actual contained objects in the Document Outline pane. One would expect to find there only the popup buttons, the label and the push button along with their constraints. However, if you start expanding the objects tree you will notice that there are more objects than those we specifically added. Apart from the menu items of the popups (which is fine to be found there since a menu item is actually another Cocoa control created automatically), you will also find a cell object going in pair with each control. For example, the fontFamiliesPopup is a NSPopUpButton object, but it contains a NSPopUpButtonCell item which in turn contains the menu items. Likewise, the label which is a NSTextField object contains a NSTextFieldCell item.

So, what is the purpose of those “Cell” objects?

Generally speaking, a cell object (any “…Cell” subclass) is responsible for implementing the actual Cocoa control and its functionalities. All those subclasses inherit from the same ancestor, NSCell, which implements several common properties and methods regarding the appearance and behaviour of controls. Even though we will be interacting with the popup buttons, the label and the push button objects directly in this app, behind the scenes any visual changes and updates will be handled by the matching cell subclasses.

Practically speaking now, we don’t have to worry about them as we won’t have to deal with any cell subclass. Just one general warning: make sure to connect IBOutlet properties to the actual controls and not their cell counterparts. It’s a common mistake that can happen if you perform the outlet connection by pressing Control and drag-and-dropping from Interface Builder to the Assistant Editor (code) and you don’t pay attention to what the origin (source) object of the dragging is.

Bringing App To Life

Building the UI, even a simple one, is an achievement. But without code, not much can happen.

Initial Configuration

Open the ViewController.swift file, where we’ll get started by implementing a function in the ViewController class that will perform some initial setup to the UI.

Go after the default view controller methods and add the following:

func setupUI() {
&nbsp;&nbsp;&nbsp;&nbsp;fontFamiliesPopup.removeAllItems()
&nbsp;&nbsp;&nbsp;&nbsp;fontTypesPopup.removeAllItems()
&nbsp;&nbsp;&nbsp;&nbsp;sampleLabel.stringValue = ""
&nbsp;&nbsp;&nbsp;&nbsp;sampleLabel.alignment = .center
}

In the first two lines we remove all default items from the two popup buttons. In the other two lines we empty the default text of the label, and we center it. Notice that the property to set the label’s text is stringValue; don’t look for a property called text or something like that.

Next step is to populate the first popup button with actual values: All font families existing in the Mac. We will achieve that by getting to know a new class called NSFontManager. It is responsible for several things including the Font panel and Font menu found in many apps, keeping record of the currently selected font, triggering font changes, and more. Among its “duties”, important information about available font families and font attributes is also included!

NSFontManager is used through a shared instance programmatically. A property named availableFontFamilies can give us what we need: A collection (array) with all the available font families!

Right next we define a new method that uses the NSFontManager class and adds the found family names as items to the fontFamiliesPopup:

func populateFontFamilies() {
&nbsp;&nbsp;&nbsp;&nbsp;fontFamiliesPopup.removeAllItems()
&nbsp;&nbsp;&nbsp;&nbsp;fontFamiliesPopup.addItems(withTitles: NSFontManager.shared.availableFontFamilies)
}
&nbsp;

Now, both of methods we implemented above have to be called once the app is started, and before the view gets appeared. Go right after the viewDidLoad() method and add the following:

override func viewWillAppear() {
&nbsp;&nbsp;&nbsp;&nbsp;super.viewWillAppear()
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;setupUI()
&nbsp;&nbsp;&nbsp;&nbsp;populateFontFamilies()
}

6

7

override func viewWillAppear() {

    super.viewWillAppear()

 

    setupUI()

    populateFontFamilies()

}

 

Let’s see what we’ve done so far. Run the app and open the first popup, you will find all available font families in it!

Handling Actions

NSFontManager class seems to be quite useful, as there are more interesting properties and methods to explore and use. One such method that is particularly interesting is called availableMembers(ofFontFamily:). It returns an array where each item is another array ([[Any]]) with four distinct values:

  1. Open the Objects Library again, and type button.
  2. Drag and drop a push button to view controller’s view below the popups.
  3. Set its constraints: Trailing: 20, Bottom: 20, Width: 120, Height: 21.
  4. Double click on the button to change its title to: Display All
  5. Open the Objects Library one last time, and type label in the search field.
  6. Drag and drop a label object into the view controller, under the popups but above the push button.
  7. Set the following constraints for the label: Top: 20, Leading: 20, Trailing: 20, Height: 80.

An item-array is called a member of the font family. The following example taken from Apple Documentation illustrates what availableMembers(ofFontFamily:) returns:

(("Times-Roman", "Roman", 5, 4),
("Times-Italic", "Italic", 6, 5),
("Times-Bold", "Bold", 9, 2),
("Times-BoldItalic", "Bold Italic", 9, 3)
)

Putting the above in different words, with *availableMembers(ofFontFamily:)* we can get all font variations that a font family supports, and display them on the *fontTypesPopup* popup button.

Before we make the actual use of the above method, let’s declare the following two properties to the ViewController class, they’ll become handy a bit later:

var selectedFontFamily: String?
&nbsp;
var fontFamilyMembers = [[Any]]()

What we need to do now is to make it possible to keep the selected font family and get its contained members every time the fontFamiliesPopup selection gets changed. This must be done in the handleFontFamilySelection(_:) IBAction method:

@IBAction func handleFontFamilySelection(_ sender: Any) {
&nbsp;&nbsp;&nbsp;&nbsp;if let fontFamily = fontFamiliesPopup.titleOfSelectedItem {
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;selectedFontFamily = fontFamily
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if let members = NSFontManager.shared.availableMembers(ofFontFamily: fontFamily) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fontFamilyMembers.removeAll()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fontFamilyMembers = members
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
}
&nbsp;

At first, we get the title of the item that gets selected in the fontFamiliesPopup; it matches to the font family name. We keep it in the selectedFontFamily property.

Next, we get all available members of the selected font family using the availableMembers(ofFontFamily:) method of the NSFontManager class. Those members are kept in the fontFamilyMembers class property. It’s important to remove any previous items existing in that array! We don’t want data from a previously selected font family to remain while we are selecting another one! That’s why removeAll() is called prior to assigning members to fontFamilyMembers.

However, just keeping the selected font family name and its members makes no real difference. We need to populate them to the fontTypesPopup so we see and use the font variations of each family. Why don’t we create a new method to do that? Add the next one to the ViewController class:

func updateFontTypesPopup() {
&nbsp;&nbsp;&nbsp;&nbsp;fontTypesPopup.removeAllItems()
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;for member in fontFamilyMembers {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if let fontType = member[1] as? String {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fontTypesPopup.addItem(withTitle: fontType)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
}

Here is what is going on in the above method:

  1. Open the Objects Library again, and type button.
  2. Drag and drop a push button to view controller’s view below the popups.
  3. Set its constraints: Trailing: 20, Bottom: 20, Width: 120, Height: 21.
  4. Double click on the button to change its title to: Display All
  5. Open the Objects Library one last time, and type label in the search field.
  6. Drag and drop a label object into the view controller, under the popups but above the push button.
  7. Set the following constraints for the label: Top: 20, Leading: 20, Trailing: 20, Height: 80.

You might want to run the app now and see the available font variations after having selected a font family first. Do it, and soon enough you will end up to an unpleasant result: The fontTypesPopup does not get any value at all! But why?

Well, the previous method does, indeed, populate the available members of a font family to the fontFamiliesPopup, but where exactly is it called? Nowhere yet!

Back to the handleFontFamilySelection(_:) IBAction method, which should be updated so it calls the updateFontTypesPopup() when the available members have been retrieved using the availableMembers(ofFontFamily:) method:

@IBAction func handleFontFamilySelection(_ sender: Any) {
&nbsp;&nbsp;&nbsp;&nbsp;if let fontFamily = fontFamiliesPopup.titleOfSelectedItem {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;selectedFontFamily = fontFamily
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if let members = NSFontManager.shared.availableMembers(ofFontFamily: fontFamily) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// ...
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;updateFontTypesPopup()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
}

Great, now you can run the app, select a font family, and then see the available members in the second popup!

So far so good, but we still have some more distance to run and get to finish line. When selecting a font member from the second popup, an actual sample should be shown in the sampleLabel label. We can make that happen if we update the font of the sample label every time a font variation is selected. And here is a new thing: How can we create a font (a NSFont object) using the data we have so far?

NSFontManager will be our tool again, as it provides a method named font(withFamily:traits:weight:size:) that returns a NSFont object. If you think about it, we have values for all parameters, as traits and weight are parts of the font member data that we keep in the fontFamilyMembers collection. Also, the selected font family is also kept to the selectedFontFamily property. Regarding size, we’ll set a random value, it doesn’t really matter.

In the handleFontTypeSelection(_:) IBAction method we are going to implement all the logic that will allow the creation of a new font object, which in turn we will set to the sample label along with the PostScript name of the font.

@IBAction func handleFontTypeSelection(_ sender: Any) {
&nbsp;&nbsp;&nbsp;&nbsp;let selectedMember = fontFamilyMembers[fontTypesPopup.indexOfSelectedItem]
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;if let postscriptName = selectedMember[0] as? String, let weight = selectedMember[2] as? Int, let traits = selectedMember[3] as? UInt, let fontfamily = selectedFontFamily {
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let font = NSFontManager.shared.font(withFamily: fontfamily,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; traits: NSFontTraitMask(rawValue: traits),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; weight: weight,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size: 19.0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sampleLabel.font = font
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sampleLabel.stringValue = postscriptName
&nbsp;&nbsp;&nbsp;&nbsp;}
}

  1. Open the Objects Library again, and type button.
  2. Drag and drop a push button to view controller’s view below the popups.
  3. Set its constraints: Trailing: 20, Bottom: 20, Width: 120, Height: 21.
  4. Double click on the button to change its title to: Display All
  5. Open the Objects Library one last time, and type label in the search field.
  6. Drag and drop a label object into the view controller, under the popups but above the push button.
  7. Set the following constraints for the label: Top: 20, Leading: 20, Trailing: 20, Height: 80.

Run the app again, and this time you will have both a sample of the selected font, and its PostScript name too!

An Eye To The Details

Our small app is working, but there are a few details left untouched. Let’s go through them.

Regarding the first one, it’s obvious that there is no font sample when the app starts. Moreover, no font members are contained in the fontTypesPopup popup button until we update the selected font family. To get around that, we will go back to one of the first methods created here, the populateFontFamilies(). In it we must make a call to the handleFontFamilySelection(_:) IBAction method and trigger that way the gathering of the font family’s available members:

func populateFontFamilies() {
&nbsp;&nbsp;&nbsp;&nbsp;// ...
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;handleFontFamilySelection(self)
}

 This fixes the missing values on the second popup when the app starts, but it doesn’t fix the missing font sample. To make the sample label show the font sample of the first member found in the fontTypesPopup popup button automatically, we need to update the updateFontTypesPopup() method as shown in the next snippet:

func updateFontTypesPopup() {
&nbsp;&nbsp;&nbsp;&nbsp;// ...
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;fontTypesPopup.selectItem(at: 0)&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;handleFontTypeSelection(self)
}

First, we auto-select the first item in the popup. Then, we call the handleFontTypeSelection(_:) IBAction method to create the font based on the selected member and update the sample label.

Lastly, one more detail that will show us a general technique beyond the demo app specifics…

Updating The Window title

Our app’s window title is saying “Window” (unless you changed that in Interface Builder), but wouldn’t be nice to make it show the selected font family’s name?

Accessing the window programmatically is easy and it’s done through the view property (main view) of the view controller as you will see right next. Go to the handleFontFamilySelection(_:) IBAction method and add the following line:

@IBAction func handleFontFamilySelection(_ sender: Any) {
&nbsp;&nbsp;&nbsp;&nbsp;if let fontFamily = fontFamiliesPopup.titleOfSelectedItem {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// ...
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;view.window?.title = fontFamily
&nbsp;&nbsp;&nbsp;&nbsp;}
}

The window now displays the selected font family!

Completing The App With A New Window Controller

Our small application is working perfectly at this point and all steps presented so far have already shown some important how-to stuff regarding macOS programming. However, the “Display All” push button is not functioning yet, and this is the part that we will focus on here. This will give us the chance to explore and talk about more things that will make this post more complete and valuable.

The purpose of the “Display All” push button is to present a new window where font variations of a selected font family will be displayed all together, formatted based on each font’s PostScript name. That might not sound such a big deal given that we can already see them one by one through the popup buttons we have. By doing that though, we will learn:

  • How to create a new macOS project.
  • What the most important parts of the generated project are.
  • What is a window controller and how to configure its contained window, including size, position, title, and a lot more.
  • How to add graphical controls into a view controller.
  • How to interact with those graphical controls, update their values and react on actions triggered by them.
  • How to create additional window controllers.
  • How to change a window’s appearance so it looks like a utility or auxiliary panel.
  • How to load and present and close a window programmatically.

So, if all that sound interesting to you, just keep reading.

Adding A New Window Controller

Back to Main.storyboard file, let’s add a new window controller along with a view controller to our canvas.

Note: Additional window controllers are not required to exist in the Main.storyboard file. You can create new storyboard files to host them. Here we will have them all into the Main storyboard so we keep things simple.

  • How to create a new macOS project.
  • What the most important parts of the generated project are.
  • What is a window controller and how to configure its contained window, including size, position, title, and a lot more.
  • How to add graphical controls into a view controller.
  • How to interact with those graphical controls, update their values and react on actions triggered by them.
  • How to create additional window controllers.
  • How to change a window’s appearance so it looks like a utility or auxiliary panel.
  • How to load and present and close a window programmatically.

You will notice that along with the window controller, an attached view controller is added as well!

What Kind Of Panel Do You Prefer?

Now, let’s see how we can change the default appearance so we can make our new window look like an auxiliary panel.

At first, click on the new window and then show the Identity Inspector. Look at the Custom Class section, where the window’s class is automatically set to NSWindow.

Click on that field, type: NSPanel and hit the Return key on your keyboard.

And now, switch to the Attributes Inspector. A new section has been added to the top, named Panel! The default value in the Style popup is Regular Panel, which means the normal window appearance. Two more panel types are supported:

  • How to create a new macOS project.
  • What the most important parts of the generated project are.
  • What is a window controller and how to configure its contained window, including size, position, title, and a lot more.
  • How to add graphical controls into a view controller.
  • How to interact with those graphical controls, update their values and react on actions triggered by them.
  • How to create additional window controllers.
  • How to change a window’s appearance so it looks like a utility or auxiliary panel.
  • How to load and present and close a window programmatically.

Both of them are meant to exist as auxiliary windows that contain supplementary options or information to the content shown on the main window.

Change the panel style and go through all options; see how the window’s appearance is being changed accordingly. A HUD panel is similar to a Utility panel, with the obvious graphical difference. It’s darker and translucent. Also, only the close button is available on the window’s bar.

Once you finish examining panel style settings, choose HUD as the style for our new window.

You are encouraged to read the Human Interface Guidelines about panels here.

While still being in the Attributes Inspector, set the “Fonts Display” text (without the quotes) as the window’s title.

One last thing before we move to the next step. Show the Identity inspector and in the Identifier text field under the Identity section type the value: fontsDisplayStoryboardID. You will see in a while why we need that.

The Fonts Display View Controller

Along with the window controller, a new view controller was added too to the project. That brings us to the need to create a new NSViewController subclass that we will connect to that new view controller. Press Cmd + N in your keyboard, and select Cocoa Class under the Source section.

Click Next, and change the Subclass of: field to NSViewController. In the Class field, type FontsDisplayViewController. Get finished with the creation of the new file.

Again to the Main.storyboard file, click on the View Controller object, and set the FontsDisplayViewController value to the Class field in the Identity Inspector.

Next, click on the main view of the view controller, and show the Size Inspector. Set its size to 480×400.

Let’s add two new Cocoa controls now to the view.

  1. Open the Objects Library again, and type button.
  2. Drag and drop a push button to view controller’s view below the popups.
  3. Set its constraints: Trailing: 20, Bottom: 20, Width: 120, Height: 21.
  4. Double click on the button to change its title to: Display All
  5. Open the Objects Library one last time, and type label in the search field.
  6. Drag and drop a label object into the view controller, under the popups but above the push button.
  7. Set the following constraints for the label: Top: 20, Leading: 20, Trailing: 20, Height: 80.

We will use the textview to display all available font members of a font family formatted. The button will be used to close the window.

Note: Adding a button to close the window is not really necessary, as the panel itself provides a close button. However, we are doing that here clearly for learning reasons; to see how we can close a window programmatically.

In the FontsDisplayViewController.swift file now, let’s declare an IBOutlet property for the textview, and an IBAction method for the button:

@IBOutlet var fontsTextView: NSTextView!
&nbsp;
@IBAction func closeWindow(_ sender: Any) {
&nbsp;
}

Finally, in the Main.storyboard file again, click to select the Fonts Display View Controller object and from the Connections Inspector connect the fontsTextView outlet to the textview, and the closeWindow(_:) action to the button.

There is one disturbing thing in the UI we are being creating, and that is the white textview on the dark and translucent HUD window. That’s okay and tolerable in the storyboard, however who would want it when using the app?

So, open the FontsDisplayViewController.swift file and add the following function:

func setupTextView() {
&nbsp;&nbsp;&nbsp;&nbsp;fontsTextView.backgroundColor = NSColor(white: 1.0, alpha: 0.0)
&nbsp;&nbsp;&nbsp;&nbsp;fontsTextView.enclosingScrollView?.backgroundColor = NSColor(white: 1.0, alpha: 0.0)
&nbsp;&nbsp;&nbsp;&nbsp;fontsTextView.isEditable = false
&nbsp;&nbsp;&nbsp;&nbsp;fontsTextView.enclosingScrollView?.autohidesScrollers = true
}
&nbsp;

The above:

  • How to create a new macOS project.
  • What the most important parts of the generated project are.
  • What is a window controller and how to configure its contained window, including size, position, title, and a lot more.
  • How to add graphical controls into a view controller.
  • How to interact with those graphical controls, update their values and react on actions triggered by them.
  • How to create additional window controllers.
  • How to change a window’s appearance so it looks like a utility or auxiliary panel.
  • How to load and present and close a window programmatically.

We will call setupTextView() right before the view gets appeared:

override func viewWillAppear() {
&nbsp;&nbsp;&nbsp;&nbsp;super.viewWillAppear()
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;setupTextView()
}

Loading And Presenting The Window Controller

The UI of the auxiliary panel is ready, so let’s see how it looks like when the application is running. Before we load and present the new window controller, we must declare the following two properties in the FontsDisplayViewController.swift file:

var fontFamily: String?
var fontFamilyMembers = [[Any]]()

We need both of them, as we are going to pass the selected font family name and its members from the ViewController class to FontsDisplayViewController. We’ll see how we’ll make use of them in a while. Just declaring them for now is good enough.

So, let’s proceed to the presentation of the new window controller. Open the ViewController.swift file, and go to the displayAllFonts(_:) IBAction method. Remember that this action method is connected to the “Display All” button in the default window of our app, so any code added here will be executed when that button is clicked.

The idea behind presenting a window controller that has been created graphically in a storyboard file, is to initialize a **NSStoryboard** object and ask it to instantiate that window controller. A NSStoryboard object is being initialized by providing the storyboard name, but in a not-so-much straightforward way. Here it is:

let storyboardName = NSStoryboard.Name(stringLiteral: "Main")
let storyboard = NSStoryboard(name: storyboardName, bundle: nil)

As you can see, the NSStoryboard initializer does not accept a string value as an argument (aka the storyboard name). It expects for a NSStoryboard.Name value instead, where Name is String type alias. Value of bundle can be left nil.

With the storyboard object being initialized now, we can instantiate our window controller. For that purpose we will use the storyboard Identifier we had previously set in Interface Builder:

let storyboardID = NSStoryboard.SceneIdentifier(stringLiteral: "fontsDisplayStoryboardID")
&nbsp;
if let fontsDisplayWindowController = storyboard.instantiateController(withIdentifier: storyboardID) as? NSWindowController {
&nbsp;
}

instantiateController(withIdentifier:) is the method of the NSStoryboard class that instantiates the window controller in the above code. It returns an Any? value, so it is necessary to:

  • How to create a new macOS project.
  • What the most important parts of the generated project are.
  • What is a window controller and how to configure its contained window, including size, position, title, and a lot more.
  • How to add graphical controls into a view controller.
  • How to interact with those graphical controls, update their values and react on actions triggered by them.
  • How to create additional window controllers.
  • How to change a window’s appearance so it looks like a utility or auxiliary panel.
  • How to load and present and close a window programmatically.

Note: Apart from window controllers, it is also possible to instantiate view controllers using the *instantiateController(withIdentifier:)* method, as long as a storyboard Identifier has been set for them in Interface Builder. That’s why that method returns an *Any* value instead of a *NSWindowController* object. It’s our duty to cast to the proper type.

Also, in the above snippet you see that the window controller’s identifier is not given as a plain String value. Instead, a NSStoryboard.SceneIdentifier value must be provided, where SceneIdentifier is a String type alias.

Supposedly at this point the new window controller has been instantiated. That’s not enough though, we must access its content view controller, and pass the selected font family and its members collection to it. NSWindowController has a property named contentViewController which represents the view controller attached to the window controller. We will use it, and after having accessed it we will pass the values we want:

if let fontsDisplayVC = fontsDisplayWindowController.contentViewController as? FontsDisplayViewController {
&nbsp;&nbsp;&nbsp;&nbsp;fontsDisplayVC.fontFamily = selectedFontFamily
&nbsp;&nbsp;&nbsp;&nbsp;fontsDisplayVC.fontFamilyMembers = fontFamilyMembers
}

Finally, we can present the window as follows:

fontsDisplayWindowController.showWindow(nil)

The above are the steps required to instantiate a window controller programmatically, to get its content view controller, and eventually present them all. Right next is the displayAllFonts(_:) method in one piece:

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@IBAction func displayAllFonts(_ sender: Any) {
&nbsp;&nbsp;&nbsp;&nbsp;let storyboardName = NSStoryboard.Name(stringLiteral: "Main")
&nbsp;&nbsp;&nbsp;&nbsp;let storyboard = NSStoryboard(name: storyboardName, bundle: nil)
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;let storyboardID = NSStoryboard.SceneIdentifier(stringLiteral: "fontsDisplayStoryboardID")
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;if let fontsDisplayWindowController = storyboard.instantiateController(withIdentifier: storyboardID) as? NSWindowController {
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if let fontsDisplayVC = fontsDisplayWindowController.contentViewController as? FontsDisplayViewController {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fontsDisplayVC.fontFamily = selectedFontFamily
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fontsDisplayVC.fontFamilyMembers = fontFamilyMembers
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fontsDisplayWindowController.showWindow(nil)
&nbsp;&nbsp;&nbsp;&nbsp;}
}

Now you can run the app and click on the “Display All” button. There will be no content yet, however you will have your first HUD panel!

Displaying Fonts

What we are going to achieve in this part is to display all font variations contained in a selected font family one after another in the textview. More precisely, the font PostScript names. Furthermore, each displayed font variation is going to be formatted according to the font it represents.

We will achieve that by creating an attributed string that will contain all PostScript names separated by the newline character “\n”, and by adding new font attributes for each displayed line. At the end, that attributed string will be assigned to the textview.

Let’s get started by creating a new method in the FontsDisplayViewController class. We’ll name it showFonts(), and the first thing we’ll do is to make sure that the font family name exists.

func showFonts() {
&nbsp;&nbsp;&nbsp;&nbsp;guard let fontFamily = fontFamily else { return }&nbsp;&nbsp;&nbsp;&nbsp;
}
&nbsp;

Remember that fontFamily is supposed to get its value when the “Display All” push button is clicked on the main window of the app.

Next, let’s declare the following two variables:

var fontPostscriptNames = ""
var lengths = [Int]()

fontPostscriptNames is the string that will hold all PostScript names that will be displayed on the textview. lengths is an array that will keep the length of each PostScript name. I’ll explain why we need it later.

Now, let’s gather all PostScript names from the font family members and let’s build the display string. At the same time, we’ll be storing each name’s length:

for member in fontFamilyMembers {
&nbsp;&nbsp;&nbsp;&nbsp;if let postscript = member[0] as? String {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fontPostscriptNames += "\(postscript)\n"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lengths.append(postscript.count)
&nbsp;&nbsp;&nbsp;&nbsp;}
}

Once again, the fontPostscriptNames string is composed by appending each font PostScript name and the newline symbol “\n” to it.

Having the string value we want to display, we are able to create the attributed string that will format later:

let attributedString = NSMutableAttributedString(string: fontPostscriptNames)

Here’s what’s coming next: We will go once again through all font family members, and for each one we will be creating a new font (NSFont) object based on each member’s data.

for (index, member) in fontFamilyMembers.enumerated() {
&nbsp;&nbsp;&nbsp;&nbsp;if let weight = member[2] as? Int, let traits = member[3] as? UInt {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if let font = NSFontManager.shared.font(withFamily: fontFamily, traits: NSFontTraitMask(rawValue: traits), weight: weight, size: 19.0) {
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
}

We will use the font object above to create a new attribute which we will add it to the attributedString we initialized previously.

Now, there is a tricky part coming. Any attribute added to an attributed string must specify the range of text that it will be applied to. That range is a NSRange value, which is composed by two distinct values: location and length. Location indicates the index of the starting character a range starts from, and length shows how many characters the range will spread to.

Given the fact that we want each line of our text to have a different attribute because of the different font, we must calculate the range of the text that each font will be applied to. And here is where the lengths array is becoming handy. Each new range will start where the previous range stopped, and its length will be equal to the respective value in the lengths array. First range will start at zero.

The following code shows how we calculate the starting location for each range and how we create a new range:

var location = 0
if index > 0 {
&nbsp;&nbsp;&nbsp;&nbsp;for i in 0..<index {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;location += lengths[i] + 1
&nbsp;&nbsp;&nbsp;&nbsp;}
}
&nbsp;
let range = NSMakeRange(location, lengths[index])

In case index is zero, meaning this is the first member in the fontFamilyMembers array, the location is set to zero too (start of text). In every other case, location is the sum of all previous range lengths, including the “\n” symbol which counts as additional character in each line (that’s why “+ 1” is added to each length).

Last line shows how a range is created. NSMakeRange() function accepts two arguments, the location and the length of the range.

Finally, we can create a new attribute for each font now:

attributedString.addAttribute(NSAttributedString.Key.font, value: font, range: range)

All the above will happen for each single item found in the fontFamilyMembers array, or in other words, in the for (index, member) in fontFamilyMembers.enumerated() { ... } loop. There’s one more attribute we have to add to the entire text, and after the end of the loop. That is the text color. By default, black color is the text color of the textview. But since we are using a HUD panel which is already dark, we have to give a light color to the text.

Here is how we do that for the entire text. As you will see, specifying the range in that case is a lot easier than what we previously did:

attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: NSColor.white, range: NSMakeRange(0, attributedString.string.count))

Finally, the attributed string is ready with all the attributes set. It’s time to assign it to the textview, or more precisely, to the textStorage property of the textview:

fontsTextView.textStorage?.setAttributedString(attributedString)

Here’s the showFonts() method with its code all together:

func showFonts() {
&nbsp;&nbsp;&nbsp;&nbsp;guard let fontFamily = fontFamily else { return }
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;var fontPostscriptNames = ""
&nbsp;&nbsp;&nbsp;&nbsp;var lengths = [Int]()
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;for member in fontFamilyMembers {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if let postscript = member[0] as? String {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fontPostscriptNames += "\(postscript)\n"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lengths.append(postscript.count)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;let attributedString = NSMutableAttributedString(string: fontPostscriptNames)
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;for (index, member) in fontFamilyMembers.enumerated() {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if let weight = member[2] as? Int, let traits = member[3] as? UInt {
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if let font = NSFontManager.shared.font(withFamily: fontFamily, traits: NSFontTraitMask(rawValue: traits), weight: weight, size: 19.0) {
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var location = 0
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if index > 0 {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for i in 0..<index {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;location += lengths[i] + 1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let range = NSMakeRange(location, lengths[index])
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;attributedString.addAttribute(NSAttributedString.Key.font, value: font, range: range)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: NSColor.white, range: NSMakeRange(0, attributedString.string.count))
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;fontsTextView.textStorage?.setAttributedString(attributedString)&nbsp;&nbsp;&nbsp;&nbsp;
}

Do not forget to call it:

override func viewWillAppear() {
&nbsp;&nbsp;&nbsp;&nbsp;// ...
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;showFonts()
}

We are done! Run the app now, select any font family and click on the “Display All” button. You will get all available font variations in one place:

Closing The Window

There is one last thing to do, and that is to enable the Close button so it’s possible to close the window when clicking on it. Doing so is extremely easy as you can see right next:

@IBAction func closeWindow(_ sender: Any) {
&nbsp;&nbsp;&nbsp;&nbsp;view.window?.close()
}

Summary

We came eventually to the end of the tutorial! Through all previous parts it became quite obvious that creating a macOS application involves a lot of steps and details, and this post highlighted the most important ones given our today roadmap. There are definitely more things to explore and discuss, and in future posts we’ll be focusing on more and new stuff about macOS programming. Here we managed to create a small application with just a few graphical controls on its UI, we implemented code to get the font information we wanted, to make visual updates to controls and to “play” with windows. By going into the making process all these, we had the chance to meet important concepts and to talk about standard techniques and practices. I hope this post will become a guide to your efforts in building your own macOS applications. Don’t forget to visit Apple’s documentation and Human Interface Guidelines if you find yourself stuck, or you just want to make sure that you are playing by the rules. See you soon!

For reference, you can download the full project on GitHub.

Thanks for reading ❤

If you liked this post, share it with all of your programming buddies!

macOS Catalina: 5 Things Web Developers & Designers Should Know

macOS Catalina: 5 Things Web Developers & Designers Should Know

macOS Catalina is here and available for download, and you’ve no doubt heard all about the breakup of iTunes and the new consumer-oriented entertainment apps shipping with the system. But what do developers, designers, and other tech professionals need to know? We run through the key points.

32-bit Support Ends with Catalina

Are you relying on some older, obscure native app for a specific function, as so many developers and designers do? Your Catalina update could throw you a wildcard: it’s the first macOS release that drops support for 32-bit apps.

During the setup process, you’ll be given a list of installed apps that will no longer open after the update. If you want to keep using that tool, it’s time to hit up the developer for a long-overdue update… or stay on Mojave for a while longer yet.

A Cross-Platform Catalyst

Mojave brought iOS ports of the News, Stocks, Voice Memos and Home apps to macOS. In Catalina, Apple is opening the tools that enabled these ports up to developers under the name of Catalyst.

While this doesn’t directly affect web development work, it does make iOS a more attractive native development platform, which may inform your future platform choices. And if Apple’s plan to reinvigorate stale macOS third-party app development with some of the action from iOS works, you could incorporate better productivity and development apps into your workflow in the near future.

For now, Catalyst is available to developers of iPad apps — we expect that to broaden in the future.

Voice Control

Catalina offers accessibility improvements in the form of improved Voice Control for those who have difficulty seeing, or using keyboards and mice.

Of course, developers should ensure that their apps work as well as they can with this tool, because it’s the right thing to do.

Developers are known for their love of keyboard shortcut mastery, but no doubt the ability to create custom commands has inspired determined lifehackers. What if you never had to take your cursor or eyes off of VS Code to run other frequent workflows?

We look forward to seeing what the community comes up with.

Screen Time

Do you waste too much time using your computer for mindless entertainment, forcing you to stay up late making up the time productively?

Or are you a workaholic who just can’t find the will to shut off and disconnect?

If you’re like most of us in the industry, you’re a mix of the two. Catalina introduces a variant of the Screen Time app that’s been on iOS for a couple of years now.

Screen Time for macOS provides you with visual analytics that help you understand the way you’re spending time on your device, which can often lead to some unexpected epiphanies. It also lets you schedule downtime, forcing you off the computer and into the real world at the right time.

As with iOS, you can also set time limits for specific apps, and there are some ways to moderate your web content usage without outright blocking your web browser from opening.

Sidecar: The Most Expensive Secondary Display You’ll Ever Own

For developers, designers, and all other web professionals, the real headline feature of Catalina is Sidecar. Sidecar turns your iPad into a secondary display for your Mac, and it’s really easy to enable (provided you have the requisite tablet, which is not included with the operating system update).

The best reason to use Sidecar over a standard display is Apple Pencil integration. Designers will love the ability to draw directly on the screen when using Sketch and Illustrator without switching devices all the time. You can even mirror your Mac’s screen if you’d like an unobstructed view of what you’re sketching on one side.

Most of us will use Sidecar as a place to dump Slack or a terminal window, but in any case, it’s clear it’ll be the most beneficial update for many of us.

How’d You Go?

Let us know how you went with the upgrade, and what you’ve enjoyed most so far. We always recommend waiting a few days for the bugs to shake out — especially with Apple’s recent track record — but initial reports suggest the release version is pretty solid after all.

How to integrate your iOS Flutter App with Firebase on MacOS

How to integrate your iOS Flutter App with Firebase on MacOS

In this tutorial I am going to show you how to connect your Flutter iOS application to the Firebase Platform on a Mac Computer so you can utilize the powerful services provided by the firebase API in your future endeavors…

In this tutorial I am going to show you how to connect your Flutter iOS application to the Firebase Platform on a Mac Computer so you can utilize the powerful services provided by the firebase API in your future endeavors…

Firebase is a mobile app development platform developed by Firebase, Inc. in 2011, and then Acquired by Google in 2014. It provides various features such as Cloud Storage, Authentication and an ML kit, which are essential to developing modern mobile applications. Additionally, it provides services such as Performance Monitoring, Crashlytics and Google Analytics to help you improve the quality of your applications.

1. Readying a Gmail Account and a Flutter Project

In order to utilize services from Firebase and Google Cloud Platform, you will need a Google Account. If you do not have one, simply following the page instructions here to register for one.

This tutorial is going to show you how to connect your existing Flutter application to the Firebase platform. If you are interested in how to create your first Flutter application, I have a tutorial on How to create your first iOS Flutter app on MacOS. By the end of that tutorial, you should have a hello_world application ready in the simulator and understand how to alter the application by modifying the main.dart file.

2. Creating a Firebase Project

In order to integrate your Flutter application with the Firebase Platform, first you have to create a Firebase Project. And here are the steps.

  1. Go to the Firebase Console.

  2. Click on the big Add project button.

  1. Enter your Project name.
  • I used hello-world for this example. Firebase automatically appends a unique ID to your project name — for example, the project I created ended up with the name hello-world-f2206.
  1. You can pick a Cloud Firestore Location.
  • I used hello-world for this example. Firebase automatically appends a unique ID to your project name — for example, the project I created ended up with the name hello-world-f2206.
  1. Accept the Terms and Conditions.

  1. Once you are done, scroll to the bottom and click Create Project.

  • I used hello-world for this example. Firebase automatically appends a unique ID to your project name — for example, the project I created ended up with the name hello-world-f2206.

Firebase will take some time to ready your application. Once done, click on the Continue button to open up the Firebase Project Overview Page.

4. Configure an iOS Application

  1. In your Firebase Project Overview Page, launch the setup wizard for iOS.

  1. Inside the setup wizard, put in the iOS bundle ID. The Register app button should then light up, click on it.
  • I used hello-world for this example. Firebase automatically appends a unique ID to your project name — for example, the project I created ended up with the name hello-world-f2206.

  1. Download the GoogleService-Info.plist configuration file and put it into the iOS Project root folder, then click Next.
  • I used hello-world for this example. Firebase automatically appends a unique ID to your project name — for example, the project I created ended up with the name hello-world-f2206.

  1. Follow the instructions to add the Firebase SDK, then click Next.

  • I used hello-world for this example. Firebase automatically appends a unique ID to your project name — for example, the project I created ended up with the name hello-world-f2206.
  1. Modify the code inside the main AppDelegate as instructed by the setup wizard then click Next. For this example, I used Objective-C, and therefore replaced the contents inside AppDelegate.m with the following code.
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"

@import UIKit;
@import Firebase;

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[FIRApp configure];
return YES;
}

@end

  1. Get back to the root folder and run your app, after a while you should see the setup wizard showing that your app is added to Firebase. Click Continue to the Console to finish the setup.

Congratulations! You have successful added Firebase to your Flutter application. Despite the fact that having both Firebase and Flutter from Google is supper cool, it is actually a good Software Engineering practice to always have a plan B, as well as plan C, D,E, F, and G. In the future I will write another guide on an example application utilizing Firebase, and more on Flutter.

Have fun coding!!!

Appendices:

3.1 Switching to Administrator Account

If you ran into the following message, it means that you need to contact the organization of your Gmail account to grant you access to Google Developers Console.

4.1 Finding iOS Project root folder & Acquiring Bundle ID

  1. Launch Xcode from the Launchpad.

  2. Select “Open another project…” at the bottom of the prompt screen.

  1. Navigate to your Flutter project folder, open the “ios” folder and select “Runner.xcodeproj”. This should automatically open up the project in Xcode.

  1. Select the Runner project on the left, you should now see the Bundle Identifier under Identity.

4.2 Installing CocoaPods and Firebase SDK

In case the instructions inside the setup wizard did not work out, you will have to remove the existing Podfile in order to reinstall them correctly.

  1. CocoaPods is built with Ruby and is installable with the default Ruby available on MacOS. Use the following commands to install it.
sudo gem install cocoapods

  1. Initialize the Podfile with the following command.
pod init

  1. Then, add the following code to the initialized Podfile.
pod 'Firebase/Core'

  1. Once done, save the changes made to the Podfile, and install the Firebase SDK with the following command.
pod install

  1. After the installation, you will likely have to configure the .xcconfig files. First you will have to copy the files from the Pods/Target Support Files/Pods-Runner folder to Flutter folder.

  1. Then you will have to include them into the Debug.xcconfig and Release.xcconfig files inside the Flutter folder.

In Debug.xcconfig:

#include "Pods-Runner.debug.xcconfig"

In Release.xcconfig:

#include "Pods-Runner.profile.xcconfig"
#include "Pods-Runner.release.xcconfig"