Hello Spencer,
I am doing the same thing. Each time the solver changes variables for height or width on a textview I asynchronously flag those calculations and dirty. Then I calculate what I call intrinsicHeight and intrinsicWidth for that textview. Some variables may depend on this and cause some textviews width and height to change causing a second pass on dirty flags. Etc etc.
Example
Create model and autocreate constraints for auto maintained variables
auto add: text.intrinsicHeight == 0
auto add: text.intrinsicWidth == 0
Set text
text.label == "foo bar"
text.label changed => mark text.intrinsicHeight dirty
text.label changed => mark text.intrinsicWidth dirty
Parse constraints
add: text.height == text.intrinsicHeight
add: text.width == 200
text.width changed => mark text.intrinsicHeight dirty
add: text.top == 0
add: text.left == 0
Check for dirty flags
auto remove: text.intrinsicHeight == 0
add: text.intrinsicHeight == 48 (calculated)
text.height changed => mark text.intrinsicWidth dirty
Check for dirty flags
auto remove: text.intrinsicWidth == 0
add: text.intrinsicWidth == 103 (calculated)
Check for dirty flags
none => end
Håvard