Note: Content in this document need to be update for this release.
This section gives an overview of the program structure and development process.
The App is currently implemented to execute on the iPhone 6, 6s, 6s Plus, 6 Plus, 7, 7 Plus, 5, 5s, and SE devices running iOS v10.x and using the XCode 8.2.x IDE for the development/builds. Consideration has been given to extending this App to other platforms and venturing into multi-platform environments such as Xamarin for future Apps development.
Work started on this application back in 2014, shortly after I got into iOS development. Though Apple was just switching to the Swift programming language, I decided to continue implementing in Objective-C since, at the time, Swift was still relatively untested and provided fewer online resources. Fortunately Apple was expected to continue supporting Objective-C into the forseeable future and the Swift API allowed its libraries to be easily integrated into Objective-C applications making a gradual transition easier (I have since started going in this direction and the current apps I am working on use Swift)
The experience of using XCode for App development has been largely positive and I have found this IDE to be superior to many of the others used in the past including Eclipse, IntelliJ, and Visual Studio. It took a while getting used to Objective-C and the many IDE abstractions (such as XCode groups used to structure the project tree) especially coming from a Software Engineering background where much of my work was at the Linux OS level using scripting/interpretive languages.
A couple of notes about XCode. It is better run on MacOS systems and is easier to use on a larger screen. That being said, while I prefer XCode development on my iMac it also works fine on my 13 inch MacBook Pro with a bit of juggling.
As mentioned, most of my development involves switching between an iMac and MacBook Pro. The App Website (http://rgbutterfly.com) and Jenkins CI application (primarily used for database builds and the REST service) are hosted on Amazon AWS instances.
The main project (currently private) integrates a number of private GitHub repos as well as libraries from the IOS Utilities, IOS Algorithms, IOS Custom Cells, and RGButterfly Tests (Swift) public repos. Over time, as I refactored the code, it made sense create these separate frameworks of potentially resuable code (the plan is to eventually make all repos public). The down side of this approach has been needing to now integrate more than one GitHub repo into the application (something that is fortunately automatically done in XCode) and tagging the many repos. Since I am the only developer on this project, I have generally worked off of the Master branch except for a few occasions earlier on in the project.
One of the first tasks was to integrate into the development process Issue tracking. This is something I would highly recommend for any medium to large project. Though in the past I have used many commercial/open source issue tracking systems any of which would do the trick in multi-user environments, I felt that using such a system for this one-man project was overkill. The system I came up with uses a simple but effective Excel Spreadsheet with five sheets named Active, Pre-Release, Post-Release, Completed, and Next Release.
For each sheet I included six columns:
- Task ID: A numeric id prefixed by F (Feature) or B (Bug) (the Task ID should also be referenced in the Git commits)
- Component: Structural or functional component(s) the Feature or Bug affects
- Description: Brief description of the problem
- Status: Completions Status (i.e., PEND, IN PROG, DONE, or ABAND)
- Priority: Work priority starting at 20 with 1 assigned to DONE/ABAND (rows are desc sorted by this column ensuring that high priority items bubble to the top and DONE/ABAND ones to the bottom)
- Comments: Additional comments such as completion status or references
The workflow is simple: New issues are generally added to the Active sheet and DONE/ABAND ones get transferred to Completed. Issues tied to the Pre/Post-Release time-frames or slated for a future release get moved to the appropritate sheet or added directly to those sheets. To enhance readability selected rows are also color coded (i.e., yellow IN PROG and gray DONE/ABAND).
The several months I spent up front on the App Design and Prototyping paid off during development time. The process that I followed is outlined below:
-
Design the initial Wire Diagram: The 'Wire Diagram' was a schematic drawn on a large whiteboard. While the initial diagram did not take long to complete (maybe about an hour) it was the result of weeks of brainstorming and successfully outlined my vision. I would often tweak the drawing as I worked out the main features.
-
Detail the Main Features: This step involved writting down in a spreadsheet the key features I wanted to implement. I often refered to this document (along with the Issue Tracking Spreadsheet) while implementing the Proof-of-Concept outlined below.
-
Implement a Proof-of-Concept Prototype (POC): My first questions was Can the key features be implemented and produce the expected results? The best way to find out was to implement a simple POC that integrated these features, among them the Match Algorithms. My target was an iPad App and, despite a few bugs, it produced the results I hoped for and lay down the ground work for the next step.
-
Create the Mockup Application Prototype (MAP): By now I just about knew exactly what I wanted but instead of diving into the implementation, I was hoping that creating a MAP would allow me to more easily set up the UI, Control, and Navigation for a "finished" App without the time expenditure generally involved in developing. For this I turned to AppCooker, a MAP tool for the iPad. The $20 I invested on this App was well worth the cost. The tool allowed me to lay out the various controllers and UI elements in a way similar to an XCode Storyboard and simulate many of the real App interactive elements such as Actions, Segues and Navigation. Even though the MAP took several weeks to complete the finished framework served as an invaluable reference that helped, without a doubt, speed up the development process. An example MAP PDF generated earlier in the process is shown here.
Data is key to this application and this App is built on Core Data. A significant amount of time was spent developing the data model (and the many interfacing NSManagedObject sub-classes) even before diving, at least to a significant extent, into the UI controllers and views. Again, time well spent since changes to the Data Model tend to be costlier down the road than changes to the UI and Controllers.
The data model is currently at major version 63 and is composed of 20 entities (each mapping to a table in the backend SQLite store). The NSManagedObject classes provide many of the key operations (i.e., Object or NSSet get/set, add, remove) against the Entities, Attributes, and/or Relations. Additional custom methods were also implemented with a few generic ones packaged in the CoreDataUtils class but most currently private.
Since most of the controllers in this App are TableView Controllers the NSFetchedResultsController API is used frequently as it provides the built-in callback methods to populate the TableViews.
The initial ER relations were captured using a graphing application. After the initial implementation, additions/modifications were implemented directly by using the CoreData built-in Data Modelling tool.
Most of the 12 controllers are TableView Controllers as I found this type to generally be more versatile for scrolling and laying out the different types of subviews. All controllers but one are embedded in Navigation controllers and BarButtonItems are generally the widget of choice for actions or navigation between controllers.
Toolbars are used instead of TabBars (due to the "deeper" hierarchy of controllers which favors the former type) and Push Modal and Unwind Segues are used to communicated between controllers.
Throughout the App Design and Prototyping and into the implementation process I often had to come up with ways to effectively use the limited Navigation and Toolbar real estate available. In general, I opted for the following choices:
- Less is Better: I tried not to display a widget unless I felt it was essential (modifying behaviour in Settings often presented a better alternative to keep the UI uncluttered)
- Consistency is Better: Widgets that appear in multiple controllers are located in the same place (i.e., Back button top left, Edit/Done button top right, Settings button bottom right, and Home button bottom left)
- Group Related Functionality: To group related functionality, I often tied a UIAlertController to multiple UIAlertActions and linked the controller to a BarButtonItem (a good example of this is the use of a Photo Icon to group Camera and Photo Library actions)
For the most part, I haven't adhered to test-driven development and the initial suite of Unit tests written in Objective-C have recently been replaced with a Swift re-implementation. For now, these test are in their own stand-alone public repo but will eventually be re-integrated into the rgbutterfly repo.
The current set includes UI and Unit tests that integrate the XCTest framework. The Unit tests are divided into RGButterflyBaseTests (common to all Controllers), Controller, and Model Tests. The former two categories cover Controller components and their connnecting points. The Model tests cover datamodel entities and relations.
Developing the App has often been challenging and there have been times when I have spent hours or, in some cases, days trying to troubleshoot a problem. XCode alone has so many features and configuration options that three years later I continue to learn how to use many new ones.
The times when I have often encountered problems are during upgrades. Incompatibilites between the versions of XCode, the underlying OS, and/or the IOS deployment device can cause problems.
New features resulting from upgrades might also break the App due to configuration changes. A recent example of this was when the upgrade to IOS 10 broke access to the Camera and Photo Library. It was not until I fixed one of the XCode configuration files that I was able to get this working again.
Most of the day-to-day problems fortunately are associated with the development process and usually a trip to Stackoverflow or some other online help site provides the tips needed to resolve the problem in short order.
- For learning about IOS development I found the Stanford University (available on iTunes) and Apple's Worldwide Developers Conference videos are great resources.
- The IOS Human Interface Guidelines is a good resource for guidelines on designing the UI.