Xcode instruments

The two columns worth noting in Instruments are # Persistent and # Transient. The Persistent column keeps a count of the number of objects of each type that currently exist in memory. The Transient column shows the number of objects that have existed but have since been deallocated. Persistent objects are using up memory, transient objects have had their memory released.

Posted in iOS, Mobile | Tagged | Leave a comment

Views vs. layers

A layer is a simple model class that exposes a number of properties to represents some image-based content. Every UIView is backed by a layer, so you can think of layers as the lower-level behind the scenes class behind your content.
A layer is different from a view (with respect to animations) for the following reasons:
A layer is a model object – it exposes data properties and implements no logic. It has no complex Auto Layout dependencies nor does it handle user interactions.
It has pre-defined visible traits – these traits are a number of data properties that affect how the contents is rendered on screen, such as border line, border color, position and shadow.
Finally, Core Animation optimizes the caching of layer contents and fast drawing directly on the GPU.
To compare views and layers side by side:


  • Complex view hierarchy layouts, Auto Layout, etc.
  • User interactions.
  • Often have custom logic or custom drawing code that executes on the main thread on the CPU.
  • Very flexible, powerful, lots of classes to subclass.


  • Simpler hierarchy, faster to resolve layout, faster to draw.
  • No responder chain overhead.
  • No custom logic by default. and drawn directly on the GPU.
  • Not as flexible, fewer classes to subclass.

If you need to choose between views and layers here is tip: choose view animations any time you can to do the job; you will know when you need more performance or flexibility and have to switch to layer animations instead.

Posted in iOS, Mobile | Tagged | Leave a comment

Xcode tips and ticks

Faster Testing

When using TDD you can work more quickly by running a subset of tests – press ⌃⌥⌘G to re-run only your last test, or ⌘-click several tests to run only them.

Opening Xcode

If you’re in a folder that has both a workspace and a project, use xed . to open the workspace in Xcode. If there were only a project, that would have been opened instead.

Generated interfaces

If you're looking at a Swift data type and just want a summary of what it does, press ⌃⌘↑ to have Xcode generate an interface showing only its external properties and methods.

Filtering the jump bar

If you find Xcode's jump bar a little long, try filtering it. After pressing ⌃6 to bring up the jump bar, you can start typing a few letters to filter all your properties and methods using a fuzzy search.

Clearing up space

If you’ve been using Xcode for a few years, you should run xcrun simctl delete unavailable to remove any old simulators that are no longer supported. It's common to save 20-60GB with that one command!


When your program is paused, right-click on a variable and choose Watch. The next time that variable changes, you can step back one frame to see where it happened.

Identifying constraints

It’s common to see lots of output in Xcode’s log when you have an Auto Layout problem, but if you add identifiers to your constraint you’ll get more helpful messages – easy to do in both Interface Builder and code!

Measuring build time

If you've ever wondered how long it takes for Xcode to build your project, you can find out with one Terminal command.

defaults write com.apple.dt.Xcode ShowBuildOperationDuration -bool YES

Show build time

defaults write com.apple.dt.Xcode ShowBuildOperationDuration -bool YES
Posted in iOS, Mobile | Tagged | Leave a comment

gitsubree usage

Basic commands about subtree

git subtree add   --prefix=<prefix> <commit>
git subtree add   --prefix=<prefix> <repository> <ref>
git subtree pull  --prefix=<prefix> <repository> <ref>
git subtree push  --prefix=<prefix> <repository> <ref>
git subtree merge --prefix=<prefix> <commit>
git subtree split --prefix=<prefix> [OPTIONS] [<commit>]

1. Add subtree

For example

git remote add -f ios git@github.com:zhihuitang/stockholm-rail-ios.git

-f: Pull immediately after adding
Add the library’s remote as if it was my own. This will significantly simplify the commands, so that you don’t have to specify the repository’s address all the time

git subtree add --prefix=ios ios master

Use subtree add to add that repo’s code into a path in the parent’s project, specified by prefix. The last parameter, master, is the branch you are pulling code from (my-subtree/master).

2. Pull sub-repo from remote

git subtree pull —prefix=ios ios master [—-squash]

Pull master branch of sub-repo from remote.

3. Push sub-repo to remote

If you changed something in sub-repo folder and want to push the changes to remote sub-repo, you can do as follows:

git subtree push --prefix=ios ios master [--squash]
Posted in git | Tagged | Leave a comment

CommentPlus for Swift Func


reference: https://zhihuitang.github.io/2019/01/13/CommentPlus-for-Swift-Func.html

  • Download the Xcode extension from here
  • Unzip and double click the extension CommentPlus.app to install the extension
  • In Xcode, put the cursor on the upper line of func, then select Xcode menu bar:
    Editor -> CommentGenerator -> Generate Func Comment:


Posted in iOS, Mac | Tagged | Leave a comment

Charles Proxy in Android

1. SSL Proxy/Charles + Android trouble


2. Enable SSL Proxy for Nougat+

Update your AndroidManifest.xml application section with networkSecurityConfig.xml

<application android:name=”AppName” 

Add network_security_config.xml file to your xml resource folder app/src/main/res/xml/network_security_config.xml

<?xml version="1.0" encoding="utf-8"?>
      <certificates src="system" />
      <certificates src="user" />

  <!-- For debug only -->
      <certificates src="system" />
      <certificates src="user" />
Posted in Android | Tagged | 1 Comment

Intermediate iOS Debugging

1. Stop when exception

1.1 Open Breakpoint navigator (Cmd + 8)
1.2 Add Exception Breakpoint

1.3 Keep default values

1.4 Move breakpoint to User level

2. Edit breakpoint

  • Edit Breakpoint

  • Add Debugger Command:

    We will see the following output:

  • or Add Log Message

ScreensFromBottom: @screensFromBottom@ Threshold: @screensFromBottomToLoadMoreCats@

We will see the logs in output window:

ScreensFromBottom: 8.5084718344868104 Threshold: 2.5
ScreensFromBottom: 8.5034899504288379 Threshold: 2.5
ScreensFromBottom: 8.499866762023041 Threshold: 2.5
ScreensFromBottom: 8.4966964721679688 Threshold: 2.5
ScreensFromBottom: 8.4948848779650703 Threshold: 2.5
ScreensFromBottom: 8.4921674866607226 Threshold: 2.5
ScreensFromBottom: 8.4899029939070996 Threshold: 2.5
ScreensFromBottom: 8.4880913997042011 Threshold: 2.5

3. Symbolic breakpoint – Condition

For example, check if some specified UIViewController is released properly.

  1. Add Symbolic Breakpoint...

  2. (Optional) Add Condition:

Check if it is UIViewController:

(BOOL)[$arg1 isKindOfClass: isKindOfClass: [UIViewController class]]

Check if it is user's custom CatDetailViewController:

(BOOL)[$arg1 isKindOfClass: (id)NSClassFromString(@"Catstagram.CatDetailViewController")]

3. Symbolic breakpoint – Action

Print the class name when UIView released:

We will see the following output:

<_UIVisualEffectSubview: 0x7f9e6e41aea0; frame = (0 0; 414 64); autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x60000003e300>>
<UIImageView: 0x7f9e70334b60; frame = (0 64; 414 0.333333); userInteractionEnabled = NO; layer = <CALayer: 0x604000030f60>>
<UIView: 0x7f9e7030f210; frame = (0 0; 414 0); layer = <CALayer: 0x6040000312a0>>
<UIImageView: 0x7f9e70334930; frame = (0 0; 414 64); userInteractionEnabled = NO; layer = <CALayer: 0x604000031140>>
<UINavigationTransitionView: 0x7f9e6e41ddc0; frame = (0 0; 414 736); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x60000003c340>>
<UIViewControllerWrapperView: 0x7f9e70004550; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x60000003e8c0>>
<UIView: 0x7f9e6e51c850; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x60c00003b040>>


LLDB is Apple’s “from the ground up” replacement for GDB, developed in close coordination with the LLVM compilers to bring you state-of-the-art debugging with extensive capabilities in flow control and data inspection. Starting with Xcode 5, all new and preexisting development projects are automatically reconfigured to use LLDB.

reference: http://lldb.llvm.org/lldb-gdb.html

4.1 p/po

4.2 frame variable(fr v)

frame variable is only for printing the contents of variables, no side effect to variable

(lldb) frame var global
(int32_t) global = 5


(lldb) p screensFromBottom
(CGFloat) $R1 = 9.3780370518781133
(lldb) po screensFromBottom

(lldb) frame variable screensFromBottom
(CGFloat) screensFromBottom = 9.3780370518781133
(lldb) fr v screensFromBottom
(CGFloat) screensFromBottom = 9.3780370518781133

4.3 Variable out of scope

Create a variable out of debug session scope by using $:

(lldb) p let $label = cell.titleLabel
(lldb) p print($label.text!)

5. Changing UI when debugging

run CATransaction.flush(), flush pending changing to the UI:

(lldb) p titleLabel.text = "Hello lldb"
(lldb) p CATransaction.flush()

6. Get memory address of return value of a function:

(lldb) register read $rax
rax = 0x000062401232eb99a

Print out the memory in LLDB:

(lldb) po unsafeBitCast(0x000062401232eb99a, to UIImage.self)
<UIImage: 0x000062401232eb99a>, {40, 40}

Posted in iOS, Mobile | Tagged | Leave a comment