Forward Swift conference – Speaker opportunity

I have been working on Swift for little over a year now and I am thoroughly enjoying this foray into iOS . With the experience I have gained working on Bing iOS app, the 5th best iOS app of 2016  as per PCMag, I have learned some iOS goodness along the way. I submitted the proposal hoping to share my learning on “Asynchronous NSOperation and how I integrated this into our app”

I am really honored and thankful to the Forward Swift curators for giving me this chance. I will be working on  some blog posts on related topics in the upcoming week to get a jump start on what topics to present and how. Hoping to create some example playground similar to what was done at RWDevCon

Forward Swift conference – Speaker opportunity

RWDevCon 2016 – Summary

On March 10 and 11 of 2016, I attended http://rwdevcon.com conference at Alexandria Virginia. This is a tutorial conference where the speakers give us starter projects and do live coding while explaining the concepts.

Below is the list of the sessions I attended and the summary of my learnings

  • Design Patterns in Swift
    1. Prefer composition over inheritance. Use other objects instead of inheriting behavior.
    2. Limit how much classes know about their dependencies. Prefer polymorphism over concrete classes
    3. Structural patterns: define how objects are composed. Eg: MVVM, MVC, FAcade
    4. Behavioral patterns:  define how objects communicate with each other : Eg: Strategy, Delegation
    5. Creational patterns: instantiate or creates objects for you
    6. When deciding to use Singleton, try for other alternatives. Make sure you are not using a singleton to pass state around.
    7. https://github.com/ochococo/Design-Patterns-In-Swift – great resource for design patterns examples in Swift
  • Advanced Debugging
    1. Cmd + K to empty the debug console
    2. Command to list all view controllers in the project that have viewDidLoad   ( image lookup –rn viewDidLoad <projectname>)
    3. In order to set breakpoints only on the  Objc version of a method syntax of breakpoints. To set breakpoint on setTitle of UIViewController b –[UIViewController setTitle:]
    4. How to attach debugger to any app and play around with the code and assembly registers
    5. https://github.com/facebook/chisel – lldb extensions used by facebook to debug iOS apps ( I am yet to look around)
    6. I will need to rewatch the video for this advanced session as I feel I havent completely grasped  a lot of the goodness presented.
  • Custom Controls
    1. If we want to create a custom controls that can be reused across app, “Add a New file” and select iOS\Source\CocoaTouch class ‘
    2. Override the init (frame: ) and init(coder aDecoder: NSCoder) to call super and prepareView() method ( where the necessary views are initialized, added to super view and constraints are defined)
    3. In iOS 9, we have NSAutoLayourAnchor. framework class introduced, that makes creating constraints a lot simpler in code
    4. Will present the changes necessary to ensure this custom view class to be used in the Interface Builder
    5. Sam Davies taught some very fancy animations that ability to manipulate them from outside custom control.
    6. 3 part Core Graphics tutorial resource for follow up: https://www.raywenderlich.com/90690/modern-core-graphics-with-swift-part-1
  • App Architecture
    1. How to create an Asynchronous NSOperation
    2. Use Dependency injection (with Swinject in the tutorial) to be able to easily swap underlying functionalities
    3. Recommended to use a “FlowController”  instead of Segues which makes changing the flow of the app simple to change in future.
    4. WWDC 2015 session 226: Advanced NSOperations
  • MVVM in practice
    1. MVVM is considered as an alternative design pattern to counter MVC ( Massive View Controller) . Here we separate out the model ( that converts data into UX – consumable  format into separate class)
    2. Explained how to create listener between model and the view controller using a generic object Box<T> ( Boxing concept where an object and its listeners are maintained in a single class and any changes in object are reported out to the listeners)
  • Xcode UI testing
    1. We can add a “iOS UI Testing Bundle” from “Add New File” Xcode menu that will create XCUI Test templates
    2. We can use XCUITesting recording behavior in order to record the actions we peform on the app
    3. We need to use XCTAssert*() methods when validating your test conditions
    4. In the app, we have “accessibility identifiers” and “accessibility labels” that we can set for every UI element. The labels are used when we turn on narrator. But the accessibility identifiers are used for the sole purpose of automation and hence set it to any value
    5. It is recommended to centralize the AccessibilityIdentifiers into a single enum
    6. WWDC 2015 Session 406
  • Core Data and Online service synchronization ( I unfortunately had to leave in between to catch an early flight – my poor decision – so I am looking forward to the video)
    1. This talk dealt with how to synchronize local data with internet backend
    2. Here instead of View controllers maintain both the local and remote service information, the recommendation is to have the local service wrap the remote service calls (similar to Opal’s personalization manager ) .
    3. The recommendation to synchronization is to get all local changes and send them to the server. Have the server return back the entire current state. The local layer then does a diff of server’s response with its current state and then decide if local data wins or server data wins
    4. It is explicitly recommended not to use a timestamp as a synchronization point between server and local, but instead use a pre-determined version number that the server will send back when sending the data
    5. Need to be careful to test the different scenarios:
      1. Conflicts
      2. Missing entities ( local or remote)
      3. Connection failure
  • Other sessions that I very much looking forward to watch the videos are:
    • Protocol Oriented Programming.
    • Advanced Autolayout
    • Beginning UIStackView
    • Beginning App Search

It has been  a very well organized, well thought out conference and speeches where we could see the speakers were experts in thier areas and very well prepared. I really enjoyed the conference and will definitely be attending the next one.

PS: If interested this is a conference post-mortem post by the main organizer https://www.raywenderlich.com/128351/rwdevcon-2016-post-mortem

I have blogged about my personal experience here http://swiftgazelle.com/2016/03/rwdevcon-2016-my-thoughts/

Screen Shot 2016-03-16 at 4.42.29 PM

RWDevCon 2016 – Summary

RWDevCon 2016 – My thoughts

This post is to summarize my personal experience with one of the most amazing conferences I have ever been to
The awesome team behind the world-famous Ray Wenderlich tutorials have organized a unique iOS conference for the first time in 2015. It has been such a hit, that I had to buy conference ticket 4 months in advance to get in 2016. Among others, the most distinguishing aspect of this event is the “Hands on tutorials”. The awesome speakers at the Ray Wenderlich will not just preach ( like other conferences) but also make the attendees get their hands dirty with code. I want your to understand how big of a deal this is. As any good  software engineer knows, the only way to internalize any software concept is by actually coding it out. It took me years for me to come to terms that we need to implement (code) concepts without theory, just to understand them ( as opposed to the exams where you study, understand and apply concepts in exam, but I digress).

I am going to repeat the single most important fact of being a software engineer ( in blocks now)

As any good  software engineer knows, the only way to internalize any software concept is by actually coding it out

In my opinion, people attend conferences for learning important and most relevant concepts in their field of study. Thus for a software engineer, the best way to understand a new concept presented at conference is to code it out. As far as I am aware, RWDevCon is the only conference that has been able to incorporate coding into the teaching process and are extremely successful, while they are at it.

I have been working as an iOS developer for less than a year and I have gained a lot of knowledge and tons of additional research to do.

The keynote speech by the great Ray Wenderlich himself, inspiration talks by those who made big in the mobile development space, gave me some thoughtful reflection opportunities after a grueling coding sessions.

The RWDevCon platinum sponser, CouchDB, organized an amazing party after the first day of conference with open bar 0317

After which I got to play the board game , “Bohnanza”pic69366

with some of the most amazing, intelligent people, including couple of the speakers. I have made some very good friends out of the 2 hours negotiation-roller coaster of Bohnanza game (which I highly recommend you try). I think this board game is the single most brilliant ice-breaker for an introvert like me to network in conferences. I really made some good friends (https://twitter.com/zombietreats, https://twitter.com/matt_luedke) that I hope to foster.

Thanks to the amazing organizers, tech editors, speakers and Ray himself for deciding to have the conference in 2016 as well and helping me become a better iOS developer and a better person.

Below is the picture of our “board game team extraordinaire” who played for atleast couple of hours at party.

boardGame

PS: I will create another post with the summary of the conference tutorials I attended as this is more of my personal experience of the conference.

 

RWDevCon 2016 – My thoughts

Swift Summit Conference report

This is the first Swift conference I have attended since starting Swift development 6 months ago. Below are some of my key takeaways from the conference:

  • Protocol-oriented programming and value semantics are the recommended paradigms to follow in Swift programming.
  • ReactiveCocoa
    • A library that, allegedly, provides a very logical way to deal with the event sequence ( synchronously and asynchronously)
    • This open source library brings the paradigm “Functional Reactive Programming” to ios. This paradigm is a new concept to me which I look to explore further.
  • Beyond the block based API: Building a simple Future
  • How to build a compelling Watch App
    • Introduction to what makes sense in a Watch app – A very simple use case
    • Basic features to build in a Watch app to make it compelling
      • Animations
      • Dictation
      • Device-to-device communication
  • Protocol MVVM
    • An example using UITableViewController with a custom tableview cell to provide a use-case of Protocol MVVM to View Controllers
    • Talk derived from the speaker’s blog posts here and here
  • Compile time guaranteed.
    • The talk started off with the importance of why we need to test our code.
    • This talk then focused on how we should approach Swift coding to ensure that most of the errors happen at compile time.
  • 55 Swift standard library protocols
    • The speaker classified the standard library protocols into 3 different categories and recommends us to identify similar scenarios in our coding:
      • Can do (end in Able)
        • Hashable, Equatable, Comparable, CustomPlaygroundQuickLookable
      • Is a (end in Type)
        • CollectionType, SequenceType, GeneratorType
      • Can be (end in Convertible)
        • FloatLiteralConvertible,CustomStringConvertible

The other talks dealt with the following:

  • Example of compiler time optimizations done by the Swift
  • Introduction to error handling, Swift 2.0 style (guard/defer, do-try-catch, throws)
  • Lyft’s high-level experience in re-writing their Obj C app completely in Swift.
  • Introduction on how to do Apple Pay
  • Introduction on starting tvOS coding

Once the videos and slides of the conference are out, I will share them

Overall it was a great experience to see what the most-discussed topics are in the Swift world and to interact with the great speakers and organizers of the conference.

Picture1

Picture of the Regency center, the venue at SFO

Swift Summit Conference report

Size your view for that “unknown” length string

There are many instances where one needs to obtain string at runtime ( For eg: An API output). This usually means we don’t have no idea how long the string can be ( assuming you don’t own API). Thus arises the predicament, “How do I size my view (uilabel) for a string size that I do not know assuming font size is fixed?”

This post will try to answer this question assuming the view in which you want to render the string as uilabel.

UILabel.lines property 

UILabel.lines is a property on the UILabel view that the users can specify, either via code or via storyboard

Screen Shot 2015-09-19 at 10.55.45 PM

In the above image, we have set a uilabel created on storyboard to have its .lines property value to be 2. This means, if the string assigned to the uilabel requires it, uilabel will wrap to render text in 2 lines. If the string exceeds 2 lines, uilabel truncates string after 2 lines are filled up and appends a triple-dot(…) at the end. Example of truncation is in the image below.

Screen Shot 2015-09-19 at 11.02.02 PM

If we specify 0 here, then the uilabel can take wrap into as many number of lines as required for rendering the string.

Setting UILabel.lines is enough if: 

  • If you know that you have enough space to render uilabel into 2 lines if necessary AND
  • If you don’t need to know the final height of the uilabel after rendering 2 lines for adjustments in your view.  ( If you have designed your constraints correctly the uilabel should just expand and gracefully push down the rest of your view).

If your app’s view requirements are above, then you should be set with the uilabel.lines property. The related property you might be interested in is called uilabel.linebreakmode providing user’s the facility to specify how the string should be truncated

If the above is not enough…

This is where things start getting interesting. Consider the following requirements for your app’s view layout:

  • You need to understand how high the uilabel is in order to adjust the surrounding ui elements accordingly.

In this case, we will make use of the nifty little nsstring method called “sizeWithAttributes” in conjunction with uiview’s “sizeThatFits” method that uilabel inherits from uiview.

sizeWithAttributes method.

This method runs on a string takes an NSDictionary input parameters and returns CGSize object with the recommended size of the uiview which will display the string.

For eg:

let str = “Lets use a very long string. Lets use a very long stringLets use a very long stringLets use a very long stringLets use a very long stringLets use a very long stringLets use a very long stringLets use a very long stringLets use a very long stringLets use a very long string

let size: CGSize = str.sizeWithAttributes([NSFontAttributeName: UIFont.systemFontOfSize(14.0)])

will return the following CGSize object.

Screen Shot 2015-09-20 at 2.29.35 PM

You can find the extensive list of attributes that can be passed into sizeWithAttributes in the Apple documentation here

sizeWithAttributes will return the recommended size that the uiview ( in this case uilabel) should be in order to render the specific string. Remember that this does not take into account the ui constraints and the restrictions applied to the uilabel.

sizeThatFits

In order to figure out the exact size the uiview can take while taking into account the constraints and restrictions present on uiview, we need to use sizeThatFits method. This method takes a CGSize attribute and tries to fit the existing uiview into that size while accounting for the restrictions. If it doesnt fit, this method recommends a new CGSize that the uiview(uilablel) should take. Remember this method does not actually change the frame of the uiview, but only recommends.

Add the below is the code in order to actually update the uilabel frame

        testLabel.frame.size = testLabel.sizeThatFits(size)

        testLabel.text = str

For my project setup of :

  • The storyboard only has one uilabel in it that is vertically and horizontally centered
  • The uilabel has width constraint set to a fixed 100 in the storyboard

The CGSize returned by sizeThatFits is belowScreen Shot 2015-09-20 at 2.43.12 PM

and my uilabel looked like this:

Screen Shot 2015-09-19 at 11.02.02 PMFor a slightly different project setup of  

  • The storyboard only has one uilabel in it that is vertically and horizontally centered
  • The UILabel only has height constraint specified

The uilabel looked like this:

Screen Shot 2015-09-20 at 2.46.08 PM

The UILabel in this case extended beyond the screen bounds, because the constraints did not have any width related restrictions and sizeThatFits tried to fit into the CGSize returned by sizeWithAttributes and hence the rendering.

Size your view for that “unknown” length string

WKWebView target=_blank quirks

My previous post deals with the different javascript-related WKWebView quirks . The first issue I mention is

WKWebView does not open any <a> links that have target=”_blank

In summary from the previous post, This issue can be resolved by implementing WKUIDelegate method as below to intercept links that request for a new webView ( new tab/window) and force them to render in the current instance of webView.

During my testing of our company’s app with the above fix, I found that clicking links inside any google plus site result in empty page rendering in WKWebView.

To summarize:

  • Clicking on SOME <a> links with attribute target=”_blank” result in empty page rendering

Upon debugging, I figured out that the WKUIDelegate method is indeed getting called as expected, but the navigationAction.request is empty ( Optional(“”))

After posting a stack over flow question here and trying out remote safari debugging as described here, I still could not figure out why the WKWebView delegate has an empty url passed in as request.

So, I used the fallback option of executing javascript code in the WKNavigationDelegate method of didFinishNavigation that gets called once the webPage is loaded

The javascript code does the following:

  • Get the list of all the links in the web Page
  • Loop through the list of links and do the following
    • If the link has a target attribute set AND the attribute value is “_blank” , we update the attribute value to be “_self”

_self indicates that the link referenced in <a> tag needs to be opened in the current instance of webView instead of new tab or new window ( target = “_blank” indicates that the browser should try and open the link in new window/tab)

Refer here for details on different values of  target attribute.

With this code, the links inside google plus posts open in the same WKWebView instance  ( Eg: tom cruise google plus posts and click on any link)

WKWebView continues to give me these quirks/headaches, though in all fairness this issue exists in UIWebView as well. UIWebView also does not have the fancy delegate method as WKWebView for intercepting calls to create new webViews, so if you are using UIWebView, javascript code is your only option

WKWebView target=_blank quirks

How to take UIWebView screenshot in Swift on iOS?

One of the more frequent questions on stack overflow is how to take a screenshot of a webView.

While working on our company’s app, I initially had to implement screenshot on UIWebView and recently had to port the code to use WKWebView and implement the same screenshot code. I initially started off to share code for wkwebview and uiwebview. But the post of UIWebView got so long that I decided to restrict this post to UIWebView full screenshot

For full screenshot in UIWebView

  1. Save the current frame of the uiwebview object
  2. Update frame to be same as uiwebView.scrollview height ( This step is necessary as you are taking a screenshot of the entire web Page content, including below the fold as well)
  3. Create a CGRect with ( height = uiwebview.scrollview.height , width = screen.width)

The next step is to generate a UIImage which contains the “snapshot” of the current state of the UIWebView. For this we need to draw the UIWebView’s snapshot into a graphics context , capture the screenshot and generate the UIImage object. For more details on graphics context, refer here

4. Call UIGraphicsBeginImageContext to create a new graphics context and to make it the default graphics context

5. Call function to render the webView.layer into the current graphics context

6. Call UIGraphicsGetImageFromCurrentContext to generate a UIImage object from the current context

7. Call UIGraphicsEndImageContext to uninitialize the  graphics context created in step 4

Below is the code to generate the uiwebview screenshot assuming you have the uiwebview object

Potential code modifications you might need to consider:

  1. renderInContext consumes a lot of memory ( potentially 150MB which can result in memory termination of the app) for rendering the entire webPage into the current graphics context. Refer to this link for potential work around. ( I personally find it hacky)
  2. You can play with the parameters to UIGraphicsBeginImageContextWithOptions depending on your requirement. Refer to this and this for more ideas
  3. If you want to take the screenshot of only visible portion of the UIWebView, the following modifications need to be made
    1. Ignore all changes to scrollView offset
    2. The webView frame is set to be of device’s height and width
    3. The size of the context also needs to be set to be same as the device’s screen size
  4. You can generate a JPG or PNG data from the UIImage  object using UIImageJPEGRepresentation and UIImagePNGRepresentation
  5. If your UIWebView can render any possible external website, test for different sites (use different technology) that render different content ( excel, pdf, ppt).
  6. Remember WKWebView is much more performant, albeit few features missing,  webView control . Make sure you analyze your requirements and see if you could take advantage of this control

Links

List of all the links referenced in this blog post

iOS Drawing Concepts

renderInContext consumes a lot of memory and eventually crashes

UIImageJPEGRepresentation

UIImagePNGRepresentation

UIGraphicsBeginImageContextWithOptions

WKWebView ( part of WebKit framework)

Captured screenshot is not of retina quality 

How to take UIWebView screenshot in Swift on iOS?

WKWebView – slice of Safari in your app

WKWebView was introduced in WWDC 2014 as an open source alternative to UIWebView for iOS and Mac apps.

WKWebView boasts of many advantages over UIWebView, some of which are included below:

  • WKWebView has very few/no memory leaks as opposed to UIWebView
  • WKWebView boasts Nitro javascript engine, same as used by Safari
  • Each WKWebView tab is opened in a new Process different than the app providing new and different resource pool that is separate from the app.
  • Some studies have shown that for some resource-intensive websites, the CPU usage is much lower
  • WKWebView provides key value observing (KVO) capability for web-related attributes ( change in title of webpage, estimated progress of loading of web page etc). For a detailed list of the WKWebView’s support KVO properties, refer here

Your next question should be, “What is the catch?”.

WKWebView was released without all the features of UIWebView.  Many of these are slowly being addressed over the last year. As of iOS 8.4 ( current greatest released iOS version), some of the cons are:

  • Requests made from WKWebView cannot be customized using NSURLProtocol
  • WKWebView does not have a good story defined around cookie-management ( should be fixed in iOS 9 to be released in October)
  • WKWebView cannot render content from local file unless it resides in /tmp folder.
  • As every WKWebView tab is opened in a new process, it is hard to visualize the memory consumption by WKWebView from Xcode

In my coming posts, I will focus on the gotchas related to WKWebView that I figured out while coding it up.

WKWebView – slice of Safari in your app