Skip to content

Commit

Permalink
Remove Problematic CATransaction, Assert Overlapping Layout
Browse files Browse the repository at this point in the history
  • Loading branch information
thecoolwinter committed Oct 12, 2024
1 parent 6fa44d6 commit 24365ba
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 25 deletions.
25 changes: 8 additions & 17 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -1,48 +1,39 @@
{
"pins" : [
{
"identity" : "mainoffender",
"kind" : "remoteSourceControl",
"location" : "https://github.com/mattmassicotte/MainOffender",
"state" : {
"revision" : "343cc3797618c29b48b037b4e2beea0664e75315",
"version" : "0.1.0"
}
},
{
"identity" : "rearrange",
"kind" : "remoteSourceControl",
"location" : "https://github.com/ChimeHQ/Rearrange",
"state" : {
"revision" : "8f97f721d8a08c6e01ab9f7460e53819bef72dfa",
"version" : "1.5.3"
"revision" : "5ff7f3363f7a08f77e0d761e38e6add31c2136e1",
"version" : "1.8.1"
}
},
{
"identity" : "swift-collections",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-collections.git",
"state" : {
"revision" : "937e904258d22af6e447a0b72c0bc67583ef64a2",
"version" : "1.0.4"
"revision" : "9bf03ff58ce34478e66aaee630e491823326fd06",
"version" : "1.1.3"
}
},
{
"identity" : "swiftlintplugin",
"kind" : "remoteSourceControl",
"location" : "https://github.com/lukepistrol/SwiftLintPlugin",
"state" : {
"revision" : "f69b412a765396d44dc9f4788a5b79919c1ca9e3",
"version" : "0.2.2"
"revision" : "5a65f4074975f811da666dfe31a19850950b1ea4",
"version" : "0.56.2"
}
},
{
"identity" : "textstory",
"kind" : "remoteSourceControl",
"location" : "https://github.com/ChimeHQ/TextStory",
"state" : {
"revision" : "8883fa739aa213e70e6cb109bfbf0a0b551e4cb5",
"version" : "0.8.0"
"revision" : "8dc9148b46fcf93b08ea9d4ef9bdb5e4f700e008",
"version" : "0.9.0"
}
}
],
Expand Down
4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ let package = Package(
// Text mutation, storage helpers
.package(
url: "https://github.com/ChimeHQ/TextStory",
from: "0.8.0"
from: "0.9.0"
),
// Useful data structures
.package(
Expand All @@ -27,7 +27,7 @@ let package = Package(
// SwiftLint
.package(
url: "https://github.com/lukepistrol/SwiftLintPlugin",
from: "0.2.2"
from: "0.52.2"
)
],
targets: [
Expand Down
29 changes: 24 additions & 5 deletions Sources/CodeEditTextView/TextLayoutManager/TextLayoutManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ public class TextLayoutManager: NSObject {
public var isInTransaction: Bool {
transactionCounter > 0
}
#if DEBUG
/// Guard variable for an assertion check in debug builds.
/// Ensures that layout calls are not overlapping, potentially causing layout issues.
/// This is used over a lock, as locks in performant code such as this would be detrimental to performance.
/// Also only included in debug builds. DO NOT USE for checking if layout is active or not. That is an anti-pattern.
private var isInLayout: Bool = false
#endif

weak var layoutView: NSView?

Expand Down Expand Up @@ -188,15 +195,26 @@ public class TextLayoutManager: NSObject {

// MARK: - Layout

/// Asserts that the caller is not in an active layout pass.
/// See docs on ``isInLayout`` for more details.
private func assertNotInLayout() {
#if DEBUG // This is redundant, but it keeps the flag debug-only too which helps prevent misuse.
assert(!isInLayout, "layoutLines called while already in a layout pass. This is a programmer error.")
#endif
}

/// Lays out all visible lines
func layoutLines(in rect: NSRect? = nil) { // swiftlint:disable:this function_body_length
assertNotInLayout()
guard layoutView?.superview != nil,
let visibleRect = rect ?? delegate?.visibleRect,
!isInTransaction,
let textStorage else {
return
}
CATransaction.begin()
#if DEBUG
isInLayout = true
#endif
let minY = max(visibleRect.minY - verticalLayoutPadding, 0)
let maxY = max(visibleRect.maxY + verticalLayoutPadding, 0)
let originalHeight = lineStorage.height
Expand Down Expand Up @@ -237,13 +255,11 @@ public class TextLayoutManager: NSObject {
}
} else {
// Make sure the used fragment views aren't dequeued.
usedFragmentIDs.formUnion(linePosition.data.typesetter.lineFragments.map(\.data.id))
usedFragmentIDs.formUnion(linePosition.data.lineFragments.map(\.data.id))
}
newVisibleLines.insert(linePosition.data.id)
}

CATransaction.commit()

// Enqueue any lines not used in this layout pass.
viewReuseQueue.enqueueViews(notInSet: usedFragmentIDs)

Expand All @@ -262,6 +278,9 @@ public class TextLayoutManager: NSObject {
delegate?.layoutManagerYAdjustment(yContentAdjustment)
}

#if DEBUG
isInLayout = false
#endif
needsLayout = false
}

Expand Down Expand Up @@ -302,7 +321,7 @@ public class TextLayoutManager: NSObject {
let relativeMinY = max(layoutData.minY - position.yPos, 0)
let relativeMaxY = max(layoutData.maxY - position.yPos, relativeMinY)

for lineFragmentPosition in line.typesetter.lineFragments.linesStartingAt(
for lineFragmentPosition in line.lineFragments.linesStartingAt(
relativeMinY,
until: relativeMaxY
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ extension TextView {
delegate?.textView(self, didReplaceContentsIn: range, with: string)
}

layoutManager.endTransaction()
textStorage.endEditing()
layoutManager.endTransaction()
selectionManager.notifyAfterEdit()
NotificationCenter.default.post(name: Self.textDidChangeNotification, object: self)
}
Expand Down

0 comments on commit 24365ba

Please sign in to comment.