Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to set watchpoints on Swift properties?

In Objective-C, I would sometimes set watchpoints in LLDB to let me know when instance variables had changed. Can I do this with Swift properties too?

Right now, the only way I can achieve this is:

  • adding a didSet handler to the property and setting a breakpoint inside (but this requires stopping the program and recompiling, which kind of defeats the purpose)
  • adding a symbolic breakpoint on [setPropertyName:] but this only works if the class happens to support Objective-C bridging

Do I have any other options?

like image 712
Bill Avatar asked Jan 23 '15 00:01

Bill


People also ask

How to watch variables in Xcode?

When you find your variable, right-click on it and choose “Watch”. Once that's done you can continue your program as normal, and anywhere the variable is read from or written to Xcode will pause and you can use the debug navigator to step through the call stack to figure out what happened.

What are watchpoints?

Similarly, a watchpoint is a type of breakpoint that indicates an area of memory associated with a data item that you want to watch, pausing your application when that memory is updated. These types of breakpoint are set on a data item, as opposed to a particular line of code.


1 Answers

The answer was much simpler than I imagined. The easiest way to do this is to simply add a breakpoint on the property declaration. The debugger will break whenever the property is either read or written.

If, like me, you want to break only when the property is changed and ignore fetches, set a breakpoint on the property declaration, then go into the LLDB console and type "br list" to see a list of all your breakpoints:

(lldb) br list
Current breakpoints:
1: file = '/Users/testuser/Desktop/TestFoo/Test.swift', line = 12, locations = 3, resolved = 3, hit count = 1

  1.1: where = TestFoo`TestFoo.Test.x.getter : Swift.Int + 12 at Test.swift:12, address = 0x00000001084cfefc, resolved, hit count = 1 
  1.2: where = TestFoo`TestFoo.Test.x.setter : Swift.Int + 16 at Test.swift:12, address = 0x00000001084cff80, resolved, hit count = 0 
  1.3: where = TestFoo`TestFoo.Test.x.materializeForSet : Swift.Int + 16 at Test.swift:12, address = 0x00000001084d00f0, resolved, hit count = 0 

As you can see, there's a master breakpoint "1" with three sub-breakpoints. Disable the sub-breakpoint for the getter:

(lldb) br disable 1.1
1 breakpoints disabled.

and you're all set. The debugger will break only when that property is modified.

like image 122
Bill Avatar answered Sep 30 '22 05:09

Bill