NGrid Swift Tutorial

Overview

This short tutorial explains the main concepts of the NGrid framework and helps you learn how to create tables using NGrid.
NGrid is a powerful library to create tables, grids and spreadsheets. It’s easy to use, easy to customize, optimized for work with large datasets and include functions for data interaction and analysis.

Introduction

This tutorial will show you how to install NGrid framework and build a simple project that demonstrates core usage and customization capabilities. The tutorial is related with samples provided on the NGrid macOS .dmg that can be downloaded here.
Screen 1

Installation

First, download the NGrid macOS .dmg. It is recommended to install the framework as it will allow you to add it via the "Developer Frameworks" section in Xcode. To install the framework, run “Install.pkg”. Alternatively, you can just copy the framework to your disk and then link it through the “Add Other...” option. The framework is located in the “NGrid.framework” directory, its documentation is located in the “Documentation” directory, and the set of samples is located in the “NGrid/Swift-Samples” directory.
For each sample, there is a pre-made Xcode project, so you can check them out to see whether everything works properly.
However, in this tutorial you will learn how to create a project from scratch. Let’s begin!
Create a new project of the "Single View Application" type. At the next window select "Swift" in the language list.
If you installed the framework properly, you should be able to link it to your application in the usual way. Click the top-level element in your project’s tree (it contains the name of your project), select the tab "General", scroll down add hit the "+" button. Then find the NGrid.framework that should be in the "Developer Frameworks" section.
Double-click it, and it will be linked to your project.
Screen 2-1
Then, select the tab "Build Settings" and find property "Objective-C Bridging Header". Double click to it and drag and drop header named "NGrid.h" from NGrid.framework to this property. Press Enter button to confirm.
Screen 2-2
After that add the value $(DEVELOPER_FRAMEWORKS_DIR) to the set of values of the option "Framework search paths" in the project settings.
Make a test run to check whether the project is able to build and run.
Now your project is set up and you are ready to start using the NGrid framework!

Anatomy of Grids

Before we start, let’s explain a little bit of terminology.
Screen 3

Simple Sample

First of all, create a new project as explained in Installation paragraph. Open ViewController.swift file and find ViewController class (or create, if this file does not exist).
Now we can start creating our first NGrid application. We’ll use ViewController class as our main class providing data source and delegate functionality. For this purpose we should define ViewController class as implementing NGridDataSource and NGridDelegate protocols:

class ViewController: UIViewController, NGridDataSource, NGridDelegate
We should implement all required methods from that protocols. So we should implement gridView:cellWithKey:, gridView:valueForCellWithKey:, gridViewRowCount:, gridViewColumnCount:, gridViewRowHeaderCount: and gridViewColumnHeaderCount: from the data source and gridView:widthForColumnWithKey: and gridView:heightForRowWithKey: from the delegate. And two optional methods from delegate should also be implemented because we need row and column headers in our table. These are gridView:widthForHeaderRowWithKey: and gridView:heightForHeaderColumnWithKey:.
// MARK: Data source stuff

func gridView(_ gridView: NGridView!, cellWith cellKey: NGridCellKey!) -> NGridCell! {
    
    var cell = gridView.dequeueReusableCell(withIdentifier: "CellID") as! NGridCommonCell!
    if (cell == nil) {
        cell = NGridCommonCell(reuseIdentifier: "CellID")
    }
    
    let cellValue = self.gridView(gridView, valueForCellWith: cellKey)
    cell?.text = "\(cellValue!)"
    return cell
}

func gridView(_ gridView: NGridView!, valueForCellWith cellKey: NGridCellKey!) -> NSObject! {
    
    var valuePrefix: String
    switch cellKey.type {
    case .cornerHeader:
        valuePrefix = "Corner header"
        
    case .columnHeader:
        valuePrefix = "Column header"
        
    case .rowHeader:
        valuePrefix = "Row header"
        
    case .regular:
        valuePrefix = "Regular"
    }
    return "\(valuePrefix) \(cellKey.rowKey):\(cellKey.columnKey)" as NSObject!
}

func gridViewRowCount(_ gridView: NGridView!) -> Int {
    return 15
}

func gridViewColumnCount(_ gridView: NGridView!) -> Int {
    return 10
}

func gridViewRowHeaderCount(_ gridView: NGridView!) -> Int {
    return 1
}

func gridViewColumnHeaderCount(_ gridView: NGridView!) -> Int {
    return 1
}

// MARK: Delegate stuff

func gridView(_ gridView: NGridView!, widthForColumnWithKey columnKey: Int) -> CGFloat {
    return 150.0
}

func gridView(_ gridView: NGridView!, heightForRowWithKey rowKey: Int) -> CGFloat {
    return 50.0
}

func gridView(_ gridView: NGridView!, widthForHeaderRowWithKey key: Int) -> CGFloat {
    return 200.0
}

func gridView(_ gridView: NGridView!, heightForHeaderColumnWithKey key: Int) -> CGFloat {
    return 75.0
}
This code sets up a simple table with 15 rows and 10 columns. The table also has row and column headers. Width of all columns is 150.0px and height of all rows is 50.0px. Moreover, we define row and column header width and height, it’s 200.0px and 75.0px respectively. We are going to use cell type and key as cell content.
Finally, we have to create and initialize NGridView and use our ViewController as a root controller of application window. For this purpose we can use loadView and viewDidLoad methods of ViewController.
override func loadView() {
    self.view = NGridView()
}

override func viewDidLoad() {
    super.viewDidLoad()
    
    (self.view as! NGridView).licenseKey = ""
    
    (self.view as! NGridView).dataSource = self
    (self.view as! NGridView).delegate = self
    
    (self.view as! NGridView).reloadData()
}
Mind that you have to set the license key in your project (you got it in email after downloading NGrid installer).
Now we can build and run our application and see what happens.
Screen 4

Customizing Appearance

The resulting table displays data but doesn’t look pretty enough. To fix it, let’s try to use NGrid style engine: set alignment and padding, change colors and fonts, configure borders, etc. In order to do this, we should define styles for row headers, column headers, and for regular cells.
Style for column header is shown below.

let columnHeaderCellStyle = NGridCellStyle.empty()!
columnHeaderCellStyle.backgroundColor = UIColor(red: 246.0/255.0, green: 246.0/255.0, blue: 246.0/255.0, alpha: 1.0)
columnHeaderCellStyle.setBorderColor(UIColor(red: 195.0/255.0, green: 195.0/255.0, blue: 195.0/255.0, alpha: 1.0))
columnHeaderCellStyle.textAlignment = NSTextAlignment.center;
columnHeaderCellStyle.textColor = UIColor(red: 50.0/255.0, green: 50.0/255.0, blue: 55.0/255.0, alpha: 1.0)
columnHeaderCellStyle.font = UIFont.boldSystemFont(ofSize: 14.0)
columnHeaderCellStyle.leftPadding = 7.0
columnHeaderCellStyle.rightPadding = 7.0
As basis for row header style we can use column header style.
let rowHeaderCellSyle = columnHeaderCellStyle.copy() as! NGridCellStyle
rowHeaderCellSyle.leftPadding = 25.0
rowHeaderCellSyle.textAlignment = NSTextAlignment.left
And we create regular cell style based on the default style. It frees us from unnecessary initialization.
let regularCellStyle = NGridCellStyle.default()!
regularCellStyle.textAlignment = NSTextAlignment.right
regularCellStyle.font = UIFont.systemFont(ofSize: 14.0)
regularCellStyle.textColor = UIColor(red: 70.0/255.0, green: 70.0/255.0, blue: 75.0/255.0, alpha: 1.0)
regularCellStyle.setBorderColor(UIColor(red: 195.0/255.0, green: 195.0/255.0, blue: 195.0/255.0, alpha: 1.0))
regularCellStyle.rightBorderDash = [1, 1]
regularCellStyle.bottomBorderDash = [1, 1]
regularCellStyle.leftBorderWidth = 0
regularCellStyle.rightBorderWidth = 1.0
regularCellStyle.leftPadding = 7.0
regularCellStyle.rightPadding = 7.0
regularCellStyle.backgroundColorInterchange = true
regularCellStyle.firstInterchangedColor = UIColor(red: 253.0/255.0, green: 253.0/255.0, blue: 253.0/255.0, alpha: 1.0)
regularCellStyle.secondInterchangedColor = UIColor.white
To manage styles NGrid uses NGridStyleManager from NGridProxyDataSourceImpl which provides methods to arrange style by style levels and to assemble resulting styles from it.
Use styleLevel: to get any style level from the style manager. It receives NGridStyleLevelOrder value as parameter.
The level objects are the instances of NGridStyleLevel class. It contains methods to specify the style of any of the grid elements.
let styleManager = (gridView.proxyDataSource as! NGridProxyDataSourceImpl).styleManager()!
let styleLevel = styleManager.styleLevel(NGridStyleLevelOrder.level0)!
styleLevel.setDefaultStyleForColumnHeader(columnHeaderCellStyle)
styleLevel.setDefaultStyleForRowHeader(rowHeaderCellSyle)
styleLevel.setDefaultStyle(regularCellStyle)
The whole resulting method is shown below:
func setupAppearance(_ gridView: NGridView) {
    let columnHeaderCellStyle = NGridCellStyle.empty()!
    columnHeaderCellStyle.backgroundColor = UIColor(red: 246.0/255.0, green: 246.0/255.0, blue: 246.0/255.0, alpha: 1.0)
    columnHeaderCellStyle.setBorderColor(UIColor(red: 195.0/255.0, green: 195.0/255.0, blue: 195.0/255.0, alpha: 1.0))
    columnHeaderCellStyle.textAlignment = NSTextAlignment.center;
    columnHeaderCellStyle.textColor = UIColor(red: 50.0/255.0, green: 50.0/255.0, blue: 55.0/255.0, alpha: 1.0)
    columnHeaderCellStyle.font = UIFont.boldSystemFont(ofSize: 14.0)
    columnHeaderCellStyle.leftPadding = 7.0
    columnHeaderCellStyle.rightPadding = 7.0
    
    let rowHeaderCellSyle = columnHeaderCellStyle.copy() as! NGridCellStyle
    rowHeaderCellSyle.leftPadding = 25.0
    rowHeaderCellSyle.textAlignment = NSTextAlignment.left
    
    let regularCellStyle = NGridCellStyle.default()!
    regularCellStyle.textAlignment = NSTextAlignment.right
    regularCellStyle.font = UIFont.systemFont(ofSize: 14.0)
    regularCellStyle.textColor = UIColor(red: 70.0/255.0, green: 70.0/255.0, blue: 75.0/255.0, alpha: 1.0)
    regularCellStyle.setBorderColor(UIColor(red: 195.0/255.0, green: 195.0/255.0, blue: 195.0/255.0, alpha: 1.0))
    regularCellStyle.rightBorderDash = [1, 1]
    regularCellStyle.bottomBorderDash = [1, 1]
    regularCellStyle.leftBorderWidth = 0
    regularCellStyle.rightBorderWidth = 1.0
    regularCellStyle.leftPadding = 7.0
    regularCellStyle.rightPadding = 7.0
    regularCellStyle.backgroundColorInterchange = true
    regularCellStyle.firstInterchangedColor = UIColor(red: 253.0/255.0, green: 253.0/255.0, blue: 253.0/255.0, alpha: 1.0)
    regularCellStyle.secondInterchangedColor = UIColor.white
    
    let styleManager = (gridView.proxyDataSource as! NGridProxyDataSourceImpl).styleManager()!
    let styleLevel = styleManager.styleLevel(NGridStyleLevelOrder.level0)!
    styleLevel.setDefaultStyleForColumnHeader(columnHeaderCellStyle)
    styleLevel.setDefaultStyleForRowHeader(rowHeaderCellSyle)
    styleLevel.setDefaultStyle(regularCellStyle)
}
Finally we should call this method after grid view was initialized.
override func viewDidLoad() {
    super.viewDidLoad()
    
    (self.view as! NGridView).licenseKey = ""
    
    (self.view as! NGridView).dataSource = self
    (self.view as! NGridView).delegate = self
    
    setupAppearance(self.view as! NGridView)
    
    (self.view as! NGridView).reloadData()
}

Screen 1

What's next?

You can find the full source code from this tutorial and the other information about using the NGrid framework in the samples in macOS .dmg. If you have any questions, feel free to contact us.