iOS, Objective-C, Swift, Design and Whatever Comes in Mind

Overlooked API of the Day: NSOrderedSet

As you know, an Array stores elements while preserving the order of their addition. You also may have learned that Sets are perfect for storing a collection of data where every element is unique. Because of its implementation it is also easy to perform boolean operations on two Sets (like computing the intersection or difference of two Sets). However, Sets will not preserve the order of their elements. What is more, they gain their efficiency only from not remembering information about the order.

This is where NSOrderedSet comes into play. According to Apples documentation, it acts as a Set (containing an element only once) whilst preserving the order of their additions.

Its counterpart NSMutableOrderedSet is the mutable addition to the datatype.

"Overlooked API of the Day: NSOrderedSet".

Overlooked API of the Day: NSCountedSet

Have you ever encountered the issue where you had a sequence of things, you needed the elements only once and must know what elements are duplicates? And how often they occure?

Take a look as NSCountedSet! For example when combining multiple collections (Sets), you can determine which elements are contained multiple times. That technique can be used to calculate the intersection of collections in a straight foreward way 🙃

Apples documentation can be found here.

"Overlooked API of the Day: NSCountedSet".

Advanced Debugging with Xcode and LLDB – Sharing my Notes

I watched the WWDC talk and I would like to share my notes with you. You can find the recording as well as the mentioned script over here.

  • Xcode debug tab can be opened when a breaktpoint is hit via settings > Running > Pauses > check “Show tab named: Debug”
  • po <variable> to get the value of a variable
  • expression <expression> (eg. expression didReachSelectedHeight = true) to execute code at the breaktpoint, useful to always take one branch of an if-else-statement
  • Breakpoints can execute a LLDB command and then continue running. When double-clicked, one can enter the command via “Add Action”. Enabling “Automatically continue after Evaluation” tells the debugger to execute the command and continue to run the program. Combined with the aforementioned point it is possible to (always) take one branch of an if-else-statement whilst debugging.
  • Shortcut the "change>compile>run" workflow by injecting the change directly through LLDB to your running code. Just add another breakpoint and add the code you just inserted to your source file here, too. expression <code you just updated> does the trick that helps to tighten the workflow.
  • Debug navigator > add symbol > "add symbolic breakpoint" to add breakpoints to framework's code. For example [UILabel setText:] to add a breakpoint that hits every time a labels text is changed. Resolving the methods name succeeded when a text like “in UIKitCore” appears beside your new breakpoint. When this breakpoint hits, one can
    • po $arg1 to print the receiver of the Objective-C message (the UILabel in this case).
    • po (SEL)$arg2 to print the selector that is sent to the object.
    • po $arg3 to print the first argument passed into the method.
  • In a breakpoint, another breakpoint can be set dynamically with breakpoint set --one-shot true -name [UILabel setText:] (one shot breakpoint: only exists until it is triggered and then removed). Useful to “enable” a breakpoint only after a given part of code is executed, for example when the text of a label is updated in the following code.
  • Change the instruction pointer while the execution is paused by grabbing the grab-handle left besides “Thread 1: breakpoint…” in the green bar.
  • thread jump --by 1 tells the debugger to jump one code line ahead when the breakpoint is hit. Useful to skip code or execute different code by adding another action to the breakpoint.
  • Adding a breakpoint to a variable declaration will pause execution every time the variable is accessed.
  • po <variable> uses the debugDescription method of an object, p <variable> is more verbose in some cases.
  • Watchpoints pause the execution every time the value of a variable is changed. They can be added by right-clicking on the variable in the left side of the debugger pane. They appear below regular breakpoints in Xcode's navigator.
  • expression -l objc -O -- [’self.view' recursiveDescription] will print the description of the view as well as all contained subviews. It is an internal Objective-C method and can not be called using Swift. “’“ around self.view will tell the debugger to evaluate this expression first.
  • Printing the content of memory addresses like po 0x67aef7891 will not work using swift. One must use expression -l objc -O -- po 0x67aef7891​. A handy way to create a shortcut is by typing command alias poc expression -l objc -O --. Now it is possible to type poc 0x67aef7891.
  • In Swift, you can also use po unsafeBitcast(0x2d34bd25, to: YourView.self) instead of using Objective-C evaluation. You can even chain expressions together, like po unsafeBitcast(0x2d34bd25, to: YourView.self).center.y = 300. When a UIView property is changed in this way, one need to tell CoreAnimation to update its frame buffer, as the execution is currently paused: expression CATransaction.flush()
  • A python script that changes properties of the view using the debugger is presented. To use commands provided by this script, open ~/.lldbinit in you home directory and add command script import ~/nudge.py. You can also define your previously created aliases there.
  • Using the nudge tool, one can live update positions of views by using the debugger.

"Advanced Debugging with Xcode and LLDB – Sharing my Notes".