On my work, technology and related stuff....

Posts Tagged ‘mobile’

1 comment

There are many options available to display charts within your [native] iOS apps. You could write one yourself (why?) or use one of the many third party libraries that are available . Check out this GitHub repo for a list of charting libraries in swift/ ObjC.
 
However, if you are interested in using Highcharts within your app, then read on . Highcharts is a popular JS charting engine and you can learn more about it at http://www.highcharts.com.
 
 This  post will demonstrate how you can load a Highcharts based chart into a iOS native app.  We will use the example charts available as part of the Highcharts library. A more interesting and complete example that demonstrates how you can dynamically load chart data is available at https://github.com/rajagp/iOS_Highcharts_Sample.
 

1)   Download the sample xcode app project from http://www.priyaontech.com/wp-content/uploads/2017/01/HighchartDemo.zip.  This is a simple single view application that will load a .html file into a WKWebView.

2)   Download the Highcharts library from http://www.highcharts.com/download

3)   Once downloaded , unzip its contents and examine it. You should see contents list similar to screenshot below

4) Navigate to the “examples” folder

5) Copy the “index.htm” file from any of the examples into your project. Make sure you copy it into your project

6)  Your project should look something like this

7) In your xcode project, open and review the the index.htm file that you just copied over. It contains a JS function that creates a chart  using the Highcharts chart API as defined in http://api.highcharts.com/highcharts/chart. The chart data and options are defined statically. 

8) Now, open the “ChartViewController.swift” file and review it.  This is a simple view controller that manages a WKWebview and loads the index.html into the web view. 

 Look for  the “loadContainerPage” function . This is where the index.htm is loaded.


9) That’s it !  Run the app and you should see the sample chart load …

 The chart data and chart options were statically predefined as part of the JS function. In a real world application, you would probably want to load the chart data and options dynamically.

A complete example that demonstrates how you can dynamically load chart data is available at https://github.com/rajagp/iOS_Highcharts_Sample.

No comments

A software pattern is a template for solving a repeatable problem. Any user facing client app can be broadly composed of three main layers –
·      The Presentation / UI Layer:  Layer that a user interacts with.
·      The Business Logic Layer: Layer that handles the data model and interactions for local/remote databases
·      The Application Logic Layer : The glue between the Presentation and Business Logic Layers.

The Model View Controller (MVC):

 

The MVC is a well-known architectural pattern used for building iOS Apps.  
·      The View , which is generally not passive, corresponds to the  Presentation Layer
·      The Model , corresponds to the  Business Logic Layer
·      The Controller sits between the View and the Model , corresponds to the Application Logic Layer.
However, the controller becomes the catch-all for everything that isn’t exactly a UI control or a data model,  leading to the  “Massive View Controller” issue.
 
Two popular alternatives to the MVC pattern are the MVP and MVVM patterns, both of which are essentially variants of the MVC pattern.
 

The Model View Presenter (MVP):


The MVP defines the following
·      The View , which is generally passive, corresponds to the  Presentation Layer
·      The Model , corresponds to the  Business Logic Layer and is identical to the MVC pattern
·      The Presenter sits between the View and the Model , corresponds to the Application Logic Layer.
A View is typically associated with one Presenter.
 
In iOS, the interaction between the View and Presenter can be implemented using the Delegation Pattern (https://developer.apple.com/library/content/documentation/General/Conceptual/DevPedia-CocoaCore/Delegation.html). The Delegation Pattern allows one object to delegate tasks to another object. In iOS, the pattern is implemented using a Protocol. The Protocol defines the interface that is to be implemented by the delegate.

In the MVP pattern, the View and Presenter are aware of each other. The Presenter holds a reference to the view it is associated with.
 
The PresenterProtocol defines the base set of methods that any Presenter must implement. Applications must extend this Protocol to include application specific methods.
 

 
The PresentingViewProtocol  defines the base set of methods that View must implement. By providing default implementation of the methods in this interface, the conformant view does not have to provide its own implementation. This interface can be extended to define application specific methods.
 

 
 
 

The Model View View Model (MVVM) :

 

 
 
The MVVM defines the following
·      The View , which is generally passive, corresponds to the  Presentation Layer
·      The Model , corresponds to the  Business Logic Layer and is identical to the MVC pattern
·      The View Model sits between the View and the Model , corresponds to the Application Logic Layer.
The key aspect of the MVVM pattern is the binding between the View and the View Model.  In other words, the View is automatically notified of changes to the View Model.

In iOS, this can be accomplished using Key-Value-Observer (KVO) Pattern. In the KVO Pattern (https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html) , one object is automatically notified of changes to the state of another object. In Objective C, this facility is built into the run-time. However, it’s not as straightforward in Swift. One option would be to add the “dynamic” modifiers to properties that need to be dynamically dispatched. However, this is limiting as objects now need to be of type NSObject.  The alternate is to simulate this behavior by defining a generic type that acts as a wrapper around properties that are observable.
 
 

 
The View can “bind” an appropriate callback to the ViewModel by using the “bind” method on the DynamicType. Every time the property value changes, the callback is automatically invoked.
 

Code and More:

A sample app that showcases the implementation of the MVC, MVP and MVVM pattern is available on GitHub at https://github.com/rajagp/iOS_MVC_MVP_MVVM_SampleApp
 
Slides from a related talk on supporting the MVP and MVVM patterns in iOS apps can be downloaded from iOS_MVP_MVVM_Patterns  .
 

5 comments

In iOS8 Apple introduced the Modern WebKit framework. The Modern WebKit supports a multi-process architecture wherein web content is loaded in a process separate from the app (upto a limit). The framework is unified across the iOS and OS X platforms and includes a lot of performance enhancements such as the optimized JS Nitro Engine , hardware accelerated 60fps scrolling etc. It also includes support for WebGL for 3D rendering.

The WKWebView For Displaying Web Content

The WKWebView is a replacement for the UIWebView on iOS for loading web content within a native app. It is essentially a wrapper around the WebKit.framework and exposes an interface that is a lot more powerful than what the UIWebViews allowed.

One of the significant improvements is the simplified communication model between Native and JS .
This article will discuss how Native-WebView bridging can be achieved.

WKWebViews are associated with a WKWebViewConfiguration object. Multiple webviews can share the configuration object.

The following code snippet creates an instance of WKWebView
Obj-C

Swift

Native to JS Bridging Using User Scripts.

User Scripts are JS that you inject into your web page at either the start of the document load or after the document is done loading. User scripts are extremely powerful because they allow client-side customization of web page, allow injection of event listeners and can even be used to inject scripts that can in turn call back into the Native app.
The following code snippet creates a user script that is injected at end of document load. The user script is added to the WKUserContentController instance that is a property on the WKWebViewConfiguration object.

ObjC:

Swift:

JS to Native Bridging Using Script Messages

Your web page can post messages to your native app via the
window.webkit.messageHandlers.<name>.postMessage (<message body>) method.
Here,  “name” is the name of the message being posted back. The JS can post back any JS object as message body and the JS object would be automatically mapped to corresponding ObjC / Swift native object.
The following JS code snippet posts back a message when a button click event occurs on a button with Id “ClickMeButton”

JS

Handling Callbacks Using Script Message Handlers

In order to receive messages posted by your web page, your native app needs to implement the WKScriptMessageHandler protocol.
The protocol defines a single required method. The WKScriptMessage instance returned in the callback can be queried for details on the message being posted back.

ObjC :

Swift:

Finally, the native class that implements WKScriptMessageHandler protocol needs to register itself as a message handler with the WKWebView as follows.

ObjC:

Swift:

Sample Code:

A complete example app demonstrating the bridging concept can be downloaded from https://github.com/rajagp/iOS-WKWebViewBridgeExample-ObjC.git. The Swift Version can be downloaded from https://github.com/rajagp/iOS-WKWebViewBridgeExample-Swift.git.

In this sample app, we load a simple HTML page that has a button using a WKWebView. When the page loads, the native app injects a JS (“User Script”) into the loaded document that listens for button click event and calls back into the native app (“Script Message”) . The native app implements a listener to handle the callback message from the web page and updates the color of the button from within the callback handler

I did a short presentation on this topic at CocoaHeads. The presentation can be downloaded from here.

No comments

I recently gave a talk on Dynamic Fonts at Cocoaheads meeting. You can download the presentation and sample code from here.

iOS7 introduced a cool feature called Dynamic Fonts. What it essentially allows you to do is to set your preferred reading text size in Settings (General or Accessibility) app of your phone and voilà, all apps that support dynamic type automatically adjust to display text content according to the preferred size setting

In this post, I’ll go over what you would need to do to support dynamic type within your apps so that yours will be one of the cool apps that reacts to the preferred text size change!

UITextKit, Text Styles and Font Descriptors

iOS7 introduced UITextKit – a powerful framework that allows you to support rich text content, layouts and without the complexities of drawing it with Core Text or having to use UIWebView.
An important component of UITextKit is TextStyles. Text Styles describe an intended use of a font .

The table below shows the list of supported text styles and the font descriptors that define them for the case when we set the preferred text size slider settings to the center.
 

Text Styles
Font Descriptor
UIFontTextStyleHeadline
(headings)
  NSCTFontUIUsageAttribute = UICTFontTextStyleHeadline;
NSFontNameAttribute = ".AppleSystemUIHeadline";
NSFontSizeAttribute = 17
UIFontTextStyleSubheadline (more…)

No comments

As an iOS developer (or any developer for that matter), it is not uncommon (or dare I say- its “very common”) for us to defer things while coding so as to not disrupt the current coding flow. For instance, handling of a special case or updating an algorithm with a more efficient one or just a reminder to double check a certain logic . To remind ourselves, we typically include a comment like “ToDo: Handle error code -1020” in our code.

 

Now, before we realize it, we have several “ToDos” and “FixMe” scattered throughout our project and unfortunately, many of them go unattended . Note that “attending” to them may be as simple as removing the comment because we have in fact handled the “To Do” but have just forgotten to remove the now obsolete comment which leads to clutter and confusing code.

 
 

So here is a neat little perl script that I found (and tweaked a wee bit for my purpose) that solves the problem. The script is executed  every time my project is built. The purpose of script is simple. The script greps for keywords in all the .h and .m files in the  ${SRCROOT} folder and prefixes it with a “warning”  label.

 

Now, every time, I compile my project, the script runs and displays all statements that begin with keywords listed in the KEYWORDS reg expression show up as warnings. They are now hard to miss and I can ensure that all the “To Do”s are handled in a timely manner.

To add the script, select “Add Build Phase” under the “Build Phases” tab of Xcode project settings.

 

Then , cut and paste the script to the “Run Script” section


Now, when you build your app, you should see all comments that include the keywords mentioned in the script listed as warnings.

Mobile Video Streaming

Feb 07, 2012

12 comments

Consumption of mobile streaming video is on an upward trend. Supporting video streaming on mobile platforms presents a lot of challenges, primarily due to the diversity of devices. The decisions include encodings , file formats, streaming protocol etc. Content Distribution Networks (CDNs) and video delivery platforms exist today to alleviate the process so you don't have to worry about the video delivery aspect and can focus on the mobile app that consumes the video.
However, in order to make an informed choice about the CDNs and their offerings and the video delivery platforms, a background on mobile streaming technologies is imperative.
I recently gave a presentation at the local Mobile Monday meeting that provides an overview of mobile streaming technologies, mobile platform specific requirements and the challenges. Click Here to download the presentation.

32 comments

Earlier this week, I jailbroke my iPhone4 iOS4.3.5 device. The jailbreak solution that is currently available for iOS4.3.5 is tethered jailbreak. If you are not familiar with “Tethered Jailbreak”, it essentially means that rebooting the jailbroken device would require it to be connected /tethered to the PC/MAC. This is of course not ideal but under the circumstances, this was my only option (And no-I couldn’t downgrade to iOS 4.3.3 for various reasons which are not directly relevant to this post).
 

Installing the jailbreak Software

I used Redsn0w V0.9.8b3 jailbreak tool. Follow the instructions provided here. The process is very straightforward.
 

Cydia Crashing Issue

Although the jailbreak completed successfully, the Cydia icon was white and it crashed as soon as I clicked on it. To get around it, I rebooted the device by running Redsn0w in tethered mode. Be sure to check the “Just boot tethered right now” option on Redsn0w . Once the device rebooted, the Cydia app started working. No more crashes. I was able to download and install apps.  Unfortunately, some of them required a reboot and I had to go through the tethered reboot process again
The  MobileTerminal, OpenSSH and Aptupdate for SBSettings were among the packages that I installed. These packages will come in handy as you will see below.
 

Installing third party apps directly

Next, I wanted to install a third party app directly to the phone. The third party app was not available through Cydia sources or the AppStore.
For this, I copied the .app file corresponding to my app into the /Applications folder on the iPhone , created the /var/mobile/Documents folder and updated the file permissions by running the commands listed below from a terminal window on my MAC. Ofcourse,  I substituted "IPhoneIPAddress" with the IPAddress of my jailbroken phone while executing the commands

Note: Creation of the Documents folder is required only the first time (unless you delete it between installations)
I rebooted the device in tethered mode. When the device rebooted, the app was ready. I could launch it and run it.
So far, so good until..

I tried to launch Cydia app, it crashed. All the other apps on the phone worked as normal.
 

Cydia Crashing Issue..Again.

So I rebooted the phone again in tethered mode.  This time the reboot had no effect. The other option was to re-jailbreak but I did not want to do that just yet.
Instead, I uninstalled and re-install the Cydia app by running the following commands from the terminal window of my MAC.  I substituted "IPhoneIPAddress" with the IPAddress of my jailbroken phone while executing the commands
 

 
Note: The AptUpdate for SBSettings that I installed earlier automatically installed the apt tools .
Once I did that, cydia was back up and running again. I currently have version 1.1.1 of Cydia on the phone. Everything else continues to work as expected.
Now, its appears that installing the third party app caused Cydia to crash but it is unclear to me why that was the case because Cydia started working again after re-installation and the third party app continues to work as well. In any case, now I know what I should do to resolve the problem should it resurface but its less than ideal.
 

In Conclusion..

With the number of reboots that I had to do, the tethering is especially tedious. If you are considering jailbreaking your iOS device, I would recommend that you refrain from updating it to 3.4.5. for now and wait for an untethered release of jailbreaking software if possible.