NSOperation – Basics

NSOperation and NSOperationQueue are built on top of GCD and provide additional features built-in that are very hard to achieve using just GCD. This post will provide basic introduction of NSOperation and how to create a simple custom NSOperation and execute it. In my next post on this series, I will delve into NSOperationQueue and how to use your custom NSOperation in conjunction with NSOperationQueue to satisfy your different scheduling requirements.

NSOperation

NSOperation is an abstract class that provides a way to consolidate the data required and the code associated with a task. In order to create a custom operation, we should derive from the NSOperation class and add the data and code associated with our custom operation. Alternatively we can use one of the 2 Apple-provided subclasses of NSOperation: NSBlockOperation and NSInvocationOperation. I will not go into details of these specific subclasses of NSOperation here.

Features of NSOperation

NSOperation, in spite of being an abstract class, provides wealth of features associated with executing a task. The following are the two most important features which , though not impossible, are very messy to implement with GCD:

  • Tracking state of an task 
    •  The states that a task wrapped in NSOperation can take are “Ready”, “Executing” and “Finished”
  • Ability to cancel an operation.
    • NSOperation provides the ability to cancel an operation by cancel() method.
    • At the core, the  cancel() method just sets a boolean cancelled = true. For any of the custom subclasses of NSOperation, the onus is on us to ensure that we account for the value of the cancelled boolean and gracefully exit our task.
    • Will go into more details further in the blog

Below I will list the steps that go into encompassing a task into an NSOperation. For simplicity, the example I am going to describe below will execute synchronously ( i.e When the code execution finishes the task finishes (or) task does not launch any asynchronous code as part of its logic)

custom NSOperation Example 

Let’s say our gazelle(or deer) is in the forest grazing. A single unit of task that the gazelle needs to perform is checkForPredators(). In short, the gazelle looks up, checks its surrounding and will be done with the task.

In this scenario,

  • the data associated with the task would be the gazelle itself and
  • the logic associated with the task would be the call to “checkForPredators()”

In this most straightforward scenario, the new task only needs to override the main() method of the NSOperation abstract class. Below are the 3 things to remember when overriding main():

  • Ensure you are setting self.executing = true before starting task logic in main()
  • Ensure you are setting self.executing = false after task logic execution completes
  • Check if the operation has been cancelled and exit gracefully

Below is how the code will look for this new Custom NSOperation

The simplest way to start the execution of a custom subclass of NSOperation is to call the start() method. When we look at the open source code for NSOperation ( in Swift Yay!!) here, we notice that the start() method is as below

Hence, when we call GazelleCheckPredatorsOperation.start(), our custom implementation of the main() is called and then finish(), which cleans up the state of the Operation as soon as the main() function call returns.

CONGRATULATIONS !!!! you now have successfully created the basic NSOperation and started it to perform a pre-defined task!!!

NSOperation – Basics

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

Core Data Violations – AllThatIsLeftToUsIsHonor

Core Data is a framework the provides us with the ability to represent the model layer of iOS app along with persistence features.

The 2 essential CoreData framework classes to know are:

  • NSManagedObjectContext
    • Apple describes this as a scratchpad in-memory for app to perform core data operations. Users can later decide if they want to save ( commit) these changes to the disk
    • We are allowed to create multiple NSManagedObjectContext and specify child-parent relationship among them. So any changes made to parent are automatically propagated to the child. Any changes made to the child are propagated to the parent when child.save() is called
  • NSManagedObject
    • All the data stored in the Core Data database , when retrieved in memory is represented by Core Data framework in form of NSManagedObjects

In the most standard scenarios, we can get away with single NSManagedContextObject created with MainQueueConcurrencyType. In this case, all the Core Data operations happen on the main queue along with UI related actions. This setup is recommended only if the core data actions support the user actions ( Eg: A new TODO item has been created, an existing work item is marked completed etc).

But for certain apps, the core data operations do not have direct correlation with user’s scenario. Eg: Import operations, storing network data in background so that user’s can access it later, if necessary. As for any multi-threaded system  operations that do not directly correlate with user scenario should be performed on a background thread/queue. Core Data framework hence provides us with the option of creating a NSManagedContext with  PrivateQueueConcurrencyType. It goes a step further and also creates a private queue that is exclusively reserved for this NSManagedContext object.

Below are some of the rules that must be followed if you do not want your app that uses CoreData to crash (or) corrupt the database:

  • A NSManagedObjectContext should be used only on the queue that is associated with it.
    • If initialized with .PrivateQueueConcurrencyType, a private, internal queue is created that is associated with the object. This queue can be accessed by instance methods .performBlockAndWait (for sync ops) and .performBlock (for async ops)
    • If initialized with .MainQueueConcurrencyType, the object can be used only on the main queue. The same instance methods ( performBlock and performBlockAndQueue) can be used here as well.
  • An NSManagedObject should not be used outside the thread in which it is initialized

In order to stress the importance of these rules, Apple has associated a scary name when these rules are not followed – “Core Data Violations”.  In fact, Apple considered these violations so important, that they decided to start crashing when a CoreData violation is present, starting iOS 6. But there were already so many apps in App Store and most of them would start crashing and so Apple to turn it OFF.

Today it is still possible to get your app into AppStore with Core Data Violations in it. Refer to this blog post to understand how to enable this detection when developing your app. When this Core Data Violations detection is enabled, all violations of Core Data threading rules will cause debugger to stop with stack trace ending at

[NSManagedObjectContext __Multithreading_Violation_AllThatIsLeftToUsIsHonor__]

and hence the title of this blog post

Core Data Violations – AllThatIsLeftToUsIsHonor

Core Data Debugging Nugget

iOS developers seem to be split about Core Data framework. I have seen people who feel like Core Data “just makes sense” for them to those who consider Core Data is very hard to comprehend. I definitely belonged to those in the latter.

Due to a crash in Core Data code at work, I had to take a closer look at Core Data framework ( Original author the core data code left team and I am the one who drew the short straw for ownership). This code has been working , sans crashes, for a few releases now, but since iOS 9.3 it has started randomly crashing in production ( with of course no reliable repro steps). The exact code that has crashed has not been touched for a few releases.

Due to apparent lack of explanation, I dove deep into how to debug Core data code and found this debugging nugget.

Core data debugging nugget

  • Create a new Xcode scheme by selecting the tab in top left corner right before the simulator/device type and selecting “New Scheme”. Name it something eay to understand like “TestCoreData” (Using Ray Wenderlich video tutorial project as example here) Screen Shot 2016-04-17 at 10.32.02 AMScreen Shot 2016-04-17 at 10.32.49 AM
  • This new scheme will not be the default selected scheme. Click on the “Scheme” tab again and this time select “Edit scheme” as shown below

Screen Shot 2016-04-17 at 10.38.24 AM

  • Select the “Run” option from the left menu and select the “Arguments” tab from the right side wizard. Here click on the “+” sign under the “Arguments passed on launch” tab. Here enter the text                                                                            “-com.apple.CoreData.ConcurrencyDebug 1” and hit “Close” at the right bottom corner of the wizard.

Screen Shot 2016-04-17 at 10.33.15 AM

The next time you launch you app with this scheme selected and if you are using your CoreData layer incorrectly, you will get a crash that is similar to the below with the entry at end of your stack trace pointing to “NSManagedObjectContext_Multithreading_Violation_AllThatIsLeftToUsIsHonor__ ” providing you the indication that you are creating your NSManagedObjectContext object (or) NSManagedObject object in one thread and using it in an another ( which is CoreData violation). temporaryCoreData

An interesting side note is that, as per Marcus Zarra, this was enabled by default in iOS 6 but then was removed because this would too many production apps to crash.

I personally think that this is a very vital part of Core Data development as it would avoid random crashes due to  CoreData  threading violations that are virtually impossible to root cause.

I have redesigned our app’s Core data infrastructure to take advantage of specifying parent-child relationship among NSManagedObjectContext objects while also fixing the CoreData violations across our app.  I have also created a new scheme that will be shared across the team for Core Data debugging and which will also be enabled by default in Jenkins when buiding “dogfood” version of our app.

 

Resources where I discovered this nugget

http://oleb.net/blog/2014/06/core-data-concurrency-debugging/

http://nshipster.com/launch-arguments-and-environment-variables/

 

 

Core Data Debugging Nugget

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

Asynchronous NSOperation: Why and how?

why-so-asynchronous

Asynchronous is a usually a scary concept for beginners. When I initially started my foray into iOS development ( my first development experience actually), I was very much intimidated about the prospect of me having to do asynchronous programming. But as I started to familiarize myself with iOS concepts and Swift language, I have increasingly noticed Apple has made it very easy for iOS app developers to use Asynchronous programming.

There are 3 kinds of asynchronous scenarios that you would want to build in your app (AS1, AS2  == Asynchronous operation 1, Asynchronous operation 2)

  1. Fire AS1, Wait for AS1 to return, If AS1 succeeds only then start AS2 potentially using data from AS1.
  2. Fire AS1, Fire AS2 (The firing of AS2 is independent of return value of AS1)
  3. Fire AS1, Wait for AS1 to return, fire AS2 ( Here too, the firing of AS2 is independent of AS1, but sometimes we want to restrict the number of active asynchronous operations)

We have many amazing open source libraries that simplifies coding for scenario 1. Eg: http://reactivecocoa.io/

For scenario 2, we can use the following steps ( this can be achieved in different ways. Describing one way briefly here, I believe this can be another blog post in itself)

  • Create a NSOperationQueue with appropriate specifications
  • Create NSURLSession with the delegate set to the operation queue created above
  • dataTask1 = NSURLSession.dataTaskWithRequest(NSURLRequest for of the AS1 task). dataTask1.start()
  • dataTask2 = NSURLSession.dataTaskWithRequest(NSURLRequest for of the AS2 task). dataTask2.start()

In the above scenario dataTask2 is kicked off even before dataTask1 returns.

Scenario 3 is what I will be focussing on in my post.

The Apple’s framework class I will be using for this are below:

  1. NSOperationQueue
  2. NSOperation

NSOperation basics

I can’t go about explaining how to implement an Asynchronous NSOperation without describing few basics about the built-in framework class NSOperation. Below are some of the important points we need to be aware of

  • NSOperation is an abstract class that provides a way to represent the data and the logic associated with a single task ( The task can be as simple/complex as you like)
  • It contains a lot of built-in logic that “coordinates the safe execution of your task” – as the Apple documentation puts it
  • So we can derive from NSOperation class, put the logic of the task by overriding main() of NSOperation, create an operation object and class start() to execute the code.
  • NSoperation keeps track of the state of the task. A task at any given time can be in 3 different states.
    • Ready
    • Executing
    • Finished ( Completed/Cancelled)
  • Below image is my attempt to create a flowchart of how the NSOperation works.

Screen Shot 2016-03-06 at 4.04.53 PM

Why doesnt this work for Asynchronous task logic?

The state tracking mechanism of nsoperation that I have described above works with the assumption that the custom task logic is complete as soon as the execution is out of main() function. In other words, the nsoperation is built under the assumption that the custom logic is NOT asynchronous.

Aysnchronous NSOperation

The NSOperation documentation guides us on what NSoperation functions/properties needs to be overriden if our task logic is asynchronous:

  • asynchronous (override to return true)
  • executing
  • finished
  • start

What this suggests is that we need manually keep track of the state of our subclass of NSOperation. We also need to ensure we are firing all the necessary KVO ( Key Value Observation) events associated with the state change. the Ray Wenderlich tutorial on “Asynchronous Operations” introduced me to the

Below is the code for the state and overriding of the suggested properties and methods

In the above code we create a custom variable state ( of the custom enum State type). This is initially set to .Ready as we use the in-built method calls willChangeKeyValue and the didChangekeyValue to fire the necessary KVO events whose utility we will explore shortly.

In the beginning of both the start() and main() method we check if the operation has been cancelled and prevent any further execution. In order to begin execution of operation, create an instance of AsynchronousOperation and call start() on it. This operation’s status will not be set to .Finished until the asynchronous operation completes and executes the callback block as specified in the code above.

Let’s re-write scenario 3 once again:

Fire asynchronous operation 1, Wait for asynchronous operation1 to return, fire asynchronous operation2

For achieving this, we need an “NSOperationQueue” which, as the name suggests, queues up NSOperation objects and schedules them depending on the queue specifications and the status of the objects. This NSOperationQueue makes use of the KVO of the operation state in determining the operation state and scheduling the next one in the queue.

In our case, we need only one operation to be scheduled at a time and the second one to be scheduled only of the first one finishes ( either successful or failed or cancelled).  So, when setting up the NSOperationQueue we set its maxConcurrentOperationCount to be 1 as below:

Due to the state management and KVO we have authored, we are guaranteed that the asyncOperation2 is executed only when the first operation is finished.

Summary

We have created a custom subclass of NSOperation to ensure that we can track an asynchronous operation status utilizing the existing NSOperation state concepts. This NSOperation is then scheduled on an NSOperationQueue with maxConcurrentOperationCount = 1, to ensure that we have only one active asynchronous operation at anytime.

Image

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