Project 7 – Petition the US Government

by | March 6, 2019

Project 7 – Petition the US Government

Jeff Summers

March 6, 2019

Today marked the beginning of Project 7 in the 100 Days of Swift challenge. After a fairly successful Consolidation Day III yesterday I was eagerly awaiting what new skills we would be asked to build for this project. Notice that I am stopping short of proclaiming I was eager and confident to undertake this one. The whole Learning Curve lesson has humbled me. I am constantly reminded of this quote from Sir Isaac Newton, “What we know is a drop, what we don’t know is an ocean.” With that, I began the new project.

Project 7 includes some interesting items but first let’s start with a description of what we are trying to build. I find it best to take a broad overview of the problem space before jumping into the details. Granted the details are where the fun stuff happens but if you don’t see the big picture you end up creating what I like to call, “Islands of Excellence”. This term describes where code (or teams for that matter) stay laser focused on delivering functionality. Left to do that they will make amazing products or decisions but at the end of the day if those teams don’t understand where their pieces fit you end up with an island paradise that cannot be accessed or used by anyone outside the island.

The United States government runs a web site called “We the People”. The goal of this web site is to provide a mechanism for the American people to create and/or sign petitions to ask the government to take some sort of action. Our app is to access this web site and provide a list of petition titles and allow users to read more details about the petition.

What we know is a drop, what we don’t know is an ocean.

-Sir Isaac Newton

I kind of had to cringe when I read the assignment. Given the current state of politics in this country I could not even imagine what we were going to find once we started mining the data to see what people were requesting. As expected, the petitions showed both serious requests such as saving Net Neutrality to the frivolous such as asking the US Government to build a Death Star.

From a Swift perspective this would be a great project. It would allow the introduction of the Codable protocol and give us an ability to read in data using JSON (JavaScript Object Notation) and display web content within an app. As an added benefit we would delve into more navigation this time using the UITabBarController which is the bar at the bottom of the screen to display alternate View Controllers.

The web content piece was similar to what we used in Project 4 but with a slight twist. The twist is that the data we were receiving was actually a formatted call to an API and then creating content to be shown in a WebView construct.

The project started the same as many others, we needed to create a TableViewController. I will again reiterate using my shortcut which deviates from what Paul Hudson teaches. He has us create a Single View app which provides a ViewController as the starting point. From there Paul has us modify the class to make the type a UITableViewController then delete the view controller from the main storyboard then add a TableViewController and embed it in a navigation controller.

My workflow is to create a Single View app then delete the ViewController Swift file and delete the view controller from the storyboard. I then add a Navigation Controller to the storyboard which automatically brings with it a Table View Controller. I then create a new Cocoa Touch file of class UITableViewController which includes the functions for numberOfRowsInSection and cellForRowAt saving me some typing and making sure the navigation and table view are properly connected. You end up in the same place just using different paths.

Once we have the navigation and table view controller in storyboard, we got to something new – embedding that in a Tab Bar Controller. Here is where you want to be careful as I got in a hurry and messed this up. Make sure you have highlighted the Navigation Controller when you Embed in Tab Bar Controller otherwise it will connect it to the Table View controller which kind of messes up the flow.

Setting up the JSON was relatively simple and easy to follow along and understand. Basically, we created new Swift files that created two structures. The first called Petition we defined the elements of the JSON file we wanted which in this case was the title, body, and number of people who signed the petition.

The second structure which we called Petitions was designed to unwrap the JSON so we could get to the individual data elements. This was required because the actual data we wanted was in a sub-section called results.

The new part we learned was the Codable protocol which is an internal construct within Swift that will take data in standard formats such as JSON and parse the data for us which is a huge time savings. The cool part was to invoke that all we had to do was modify the structure definition to add “: Codable” just before the beginning of the curly brace.

I’m going to skip ahead a little bit for the sake of time since much of the remaining project dealt with things we had already learned, and I have previously written about. I did want to touch on one piece I thought was cool.

After we had decoded the JSON and placed the data in our structure we needed to display the description or body of the petition in a Detail View Controller. This meant displaying HTML data in a view controller. We did this using loadHTMLString sent to a webView. The code for this was:

guard let detailItem = detailItem else { return }

self.title = detailItem.title

let html = """




\(detailItem.body)


"""

webView.loadHTMLString(html, baseURL: nil)

The cool part to me was that we created a string called html which basically included all the HTML tags we needed including changing CSS values. Once we had that string, we just placed that in the loadHTMLString function and Swift did the rest. That’s pretty cool!

The other part that I found especially interesting was creating Detailed View Controllers programmatically rather than through the storyboard. This was necessary because we actually needed two identical view controllers but that would display different data. To do that in storyboard would have been messy since we would be duplicating a lot of stuff and would have been problematic to maintain. Instead we created the controller in the AppDelegate.swift file.

Below is my code that I used. It should be noted that I went a little further than the example. Since the We the People API has several flags to send JSON data I added views for only open petitions, only closed petitions, the most recent petitions, and the most popular petitions.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
for n in 1...3 {
if let tabBarController = window?.rootViewController as? UITabBarController {
let storyboard = UIStoryboard(name: "Main", bundle: nil)

let vc = storyboard.instantiateViewController(withIdentifier: "NavController")
switch n {
case 1:
vc.tabBarItem = UITabBarItem(tabBarSystemItem: .topRated, tag: n)
case 2:
vc.tabBarItem = UITabBarItem(title: "Closed", image: UIImage(named: "closed.png"), tag: n)
case 3:
vc.tabBarItem = UITabBarItem(title: "Open", image: UIImage(named: "open.png"), tag: n)
default:
print("default reached")
}
tabBarController.viewControllers?.append(vc)
}
}
return true
}

A couple of things to note. We are creating buttons in the Tab Bar Controller. There are a series of system icons that can be used. If you use those you cannot change the title of the icon since Apple wants to make sure you are using the icon with an appropriate behavior. So, if you want to have custom titles to the icons you will need to define your own icons. I added graphics to the Assets.xcassets file for closed and open to do just that. You call them using a UIImage tag as seen above.

Once I had defined the detailed view controllers, I simply had to define what data went in each view. Below is the code I wrote for that:

switch navigationController?.tabBarItem.tag {
case 0:
urlString = "https://api.whitehouse.gov/v1/petitions.json?limit=100"
//urlString = "https://hackingwithswift.com/samples/petitions-1.json"
self.title = "Most Recent Petitions"
case 1:
urlString = "https://api.whitehouse.gov/v1/petitions.json?signatureCountFloor=10000&limit=100"
//urlString = "https://hackingwithswift.com/samples/petitions-1.json"
self.title = "Top Rated Petitions"
case 2:
urlString = "https://api.whitehouse.gov/v1/petitions.json?status=closed&limit=100"
//urlString = "https://hackingwithswift.com/samples/petitions-1.json"
self.title = "Closed Petitions"
default:
urlString = "https://api.whitehouse.gov/v1/petitions.json?status=open&limit=100"
//urlString = "https://hackingwithswift.com/samples/petitions-1.json"
self.title = "Open Petitions"
}

Overall this project was pretty interesting and gave me a lot of ideas for follow-on projects such as pulling JSON data for sports feeds and providing them in custom views. The biggest challenge is finding good data feeds that are not cost prohibitive for recreational developers who are not planning to monetize the feeds.

Share this Article

Posted by Jeff Summers

Author, technologist, and baseball aficionado specializing in information technology and developing new and creative ways to interact with the world around us. My goal is to extend the boundaries of what is possible and find ways to make the world a better place while having fun.

0 Comments

Trackbacks/Pingbacks

  1. Project 7 – White House Petitions: Part 3 – Jeff Blogs - […] was the conclusion of Project 7. We started off creating the project in Xcode and establishing a table view…
  2. Project 7 – White House Petitions: Part 2 – Jeff Blogs - […] Project 7 started, today was really devoted to taking the data that we collected in the JSON file, parsing…

Submit a Comment

Your email address will not be published. Required fields are marked *

Stay Connected

Search

More Articles

Pace Layered Architecture Categorization

Change is inevitable. Today’s computing environments are constantly in flux from internal and external forces that put demands on the systems and necessitate changes to maintain its value stream. Technology currency is a constant struggle that organizations must...

TBM, Another Holy Grail?

Technology Business Management or TBM as a term was coined around 2012 although many of the concepts making up this framework have been around for almost as long as there has been IT. In its simplest form, TBM represents the integration of business, technology, and...

Visionary or Dreamer?

Thinking back over your life you’ve met and worked with countless personality types. You have been a part of teams that struggled to complete simple tasks and the work felt meaningless. Perhaps your goal in these times was to just trudge through the mud hoping the...

Archives