A faster and more flexible label view for iOS

Overview

CircleCI TravisCI Swift 4.2 Version Platform License Twitter

STULabel is an open source iOS framework for Swift and Objective-C that provides a label view (STULabel), a label layer (STULabelLayer) and a flexible API for thread-safe text layout and rendering (STUShapedString, STUTextFrame). The framework is implemented in Objective-C++ on top of the lower-level parts of the Core Text API. STULabel has a Swift overlay framework (STULabelSwift) that provides a convenient Swift API.

Table of Contents

STULabel features

  • Faster than UILabel and UITextView
  • Optional asynchronous layout and rendering
  • Support for prerendering (useful e.g. in a collection view prefetch handler)
  • Automatic switching to efficient tiled rendering for very large labels
  • Text highlighting with color or decorations that doesn't require a text relayout
  • Fast auto scaling of text ("shrink to fit size")
  • Interactive hyperlinks with full UIDragInteraction support
  • Very flexible text truncation, including support for truncation tokens with embedded links and for multiple vertically stacked truncation scopes
  • Auto Layout support
  • Dynamic Type support
  • UIAccessibility support
  • Comprehensive support for right-to-left text
  • Configurable vertical alignment and content insets
  • Fine control over text layout, including support for fixed baseline distances and first baseline offsets
  • Customizable automatic hyphenation
  • Text attachments (inline images)
  • Underlines with accurate descender gaps
  • Flexible background decorations, e.g. with rounded corners
  • Rich text layout information that is easy to query

The source code contains a demo app that you can build with the included Xcode project. The demo app contains:

  • A viewer for the Universal Declaration of Human Rights that lets you view the document in languages with 39 different scripts (writing systems). You can experiment with fonts, spacings, text decorations, links, truncations, etc. and compare the text rendered by STULabel with the text rendered by UITextView.
  • A UITableView scrolling stress test that lets you compare the performance of STULabel, UILabel and UITextView and observe the effect of enabling or disabling Auto Layout, async rendering or prefetch layout/rendering.
  • A micro benchmark that lets you measure and compare the layout and render performance of STULabel, UILabel and UITextView for various test cases.
  • A micro benchmark that lets you measure and compare the layout and render performance of STUTextFrame, NSStringDrawing and Text Kit for various test cases.
  • A view that implements a "tap to read more" feature with STULabel.

Status

STULabel is pre-release ("beta") software. It has bugs, it needs more tests and it needs more documentation, yet it might already be good enough for your purposes. If you want to use it for anything serious, please subscribe to the bug tracker and update frequently.

The API and behaviour should be mostly stable now before the 1.0 release. (Binary interface (ABI) stability is an explicit non-goal of this open source library.)

License

Except where noted otherwise, everything in this repository is distributed under the terms of the 2-clause BSD license in LICENSE.txt.

The STULabel library incorporates data derived from the Unicode Character Database, which is distributed under the Unicode, Inc. License Agreement.

Integration

CocoaPods integration

If you want to use STULabel from Objective-C code, add the following to your Podfile:

pod 'STULabel', '~> 0.8.7'

If you want to use STULabel from Swift code, add the following to your Podfile:

pod 'STULabelSwift', '~> 0.8.7'

STULabel is a dependency of STULabelSwift.

Manual integration

  • The STULabel project contains separate schemes for building STULabel and STULabelSwift both as dynamic and as static frameworks.
  • You should only link STULabelSwift if you want to use STULabel from Swift code.
  • If you want to use the static framework(s), you need to manually add the STULabelResources.bundle product to your app or framework target. (The resources bundle contains the localized strings for the default link action sheets.)
  • One way to manually integrate STULabel into your Xcode project is as follows:
    1. Close the STULabel project in Xcode if it is open.

    2. Open your project in Xcode if it isn't already open.

    3. Drag the STULabel project from Finder into the project navigator pane of the Xcode window of your project.

    4. Reveal the subtree below STULabel.xcodeproj in the project navigator and reveal the items in the Products group. You should now see two STULabel.framework items, two STULabelSwift.framework items, a STULabelResources.bundle and some other items. The identically named framework items are the dynamic and static builds of the respective frameworks. You can identify the static frameworks by their full paths in the Xcode file inspector (in the right Xcode pane). For example, the full path of the static STULabel.framework ends with ' -static/STULabel.framework'.

    5. Select your project at the top of the Xcode project navigator pane.

    6. Select your app or framework target in the center view (the standard editor view in the middle of the window).

    7. Select the 'General' tab in the center view.

    8. If you want to use the dynamic framework(s):

      • Drag the non-static STULabel.framework from the Products group of the STULabel.xcodeproj in the project navigator pane to the 'Embedded Binaries' section in the center view. When you drop it there, the framework will also be added below below in the 'Linked Frameworks and Libraries' list.
      • Do the same with the non-static STULabelSwift.framework if you want to use Swift.

      If you want to use the static framework(s) instead:

      • Add the following items to the 'Linked Frameworks and Libraries' section, e.g. by clicking on the '+' button and selecting the respective items:
        • STULabel.framework from the static target,
        • STULabelSwift.framework from the static target, if you want to use Swift,
        • libc++.tbd, unless that library was already added before.
      • Select the 'Build Phases' tab in the center view.
      • Add the static STULabel(Swift) framework(s) that you just added to the list of linked frameworks also to the list of 'Target dependencies'.
      • Add STULabelResources to the 'Target dependencies'.
      • Reveal the 'Copy Bundle Resources' section.
      • Drag the STULabelResources.bundle from the Products group of the STULabel.xcodeproj to the 'Copy Bundle Resources' section.
      • Select the 'Build Settings' tab in the center view.
      • Add $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)-static to the 'Framework Search Paths'.

LLDB formatters

The STULabel source contains an LLDB Python script that defines data formatters for various types defined by the library. If you find yourself stepping through STULabel code in Xcode, importing this script will improve your debugging experience.

Support

If you've found a bug, please create a GitHub issue. If possible, please provide sample code that reproduces the issue.

If you have a question regarding the use of STULabel, e.g. how to accomplish a certain text layout, please ask the question on Stack Overflow and tag it with 'STULabel'.

Some features in detail

Performance

Synchronous layout and rendering with STULabel is faster than UILabel and UITextView, sometimes several times faster. How much faster STULabel is depends both on the specific use case and on the device and iOS version. The Demo app contains a micro benchmark for label views that lets you compare the performance of STULabel, UILabel and UITextView for various test cases on your own devices.

STULabel is faster than UILabel mainly because it caches text layout data more aggressively. In part this is due to UILabel using NSStringDrawing for layout and rendering purposes, which doesn't support persisting the calculated text layout, while STULabel is using the STUTextFrame API (implemented on top of Core Text's CTTypesetter), which makes it very easy to separate the text shaping and layout from the text rendering.

UITextView seems to be primarily designed for lazily typesetting large mutable texts and supporting fine-grained customization of the layout process, not for displaying smallish static strings.

The automatic text scaling implementation in STULabel is particularly fast because instead of scaling down the font sizes it scales up the layout width and then scales down content during drawing. This has the advantage that the attributed string doesn't have to be recreated, font object caches are less loaded and most of the text shaping only has to be done once. The Core Graphics render quality on iOS should be equal for both approaches.

Async rendering

Text layout and rendering can constitute a large part of the total time that the main thread spends on layout and rendering, particularly if the text is written in languages using complex scripts, like e.g. Hindi or Arabic. The asynchronous layout and rendering support in STULabel makes it easy to move at least part of this work to a background thread. (Image decoding and drawing can be another main-thread performance bottleneck on iOS, but that is usually much simpler to move to a background thread than text layout and rendering).

The UITableView example in the Demo app lets you enable or disable async and prefetch rendering for the STULabel views and thus allows you to observe the effect that these features can have on scrolling performance. (If you're using a fast device, you may have to increase the auto scroll speed to make the difference obvious.)

You can enable asynchronous rendering for STULabel views simply by setting the displaysAsynchronously property to true.

Doing the full text layout asynchronously is a bit more complicated, since you'll have to do it e.g. in a collection view prefetch handler and you need to know all the relevant layout parameters in advance in order to configure the STULabelPrerenderer object.

However, often you don't need to do the full layout on a background thread to achieve absolutely smooth scrolling with 60 or 120 FPS. Doing just the text shaping in advance, by constructing STUShapedString instances for the attributed strings that you want to display, and then configuring the label views the with the shaped strings instead of the attributed strings will already improve layout performance considerably.

In certain situation asynchronous rendering can be detrimental to the user experience, e.g. when it leads to visible flickering or breaks animations. STULabel will automatically switch to synchronous rendering when it can easily detect such a situation, e.g. when the layout was initiated in a UIView animation block. When this automatic behaviour isn't sufficient, you can e.g. temporarily disable async rendering through the delegate interface.

Flexible text truncation

  • STULabel lets you specify the attributed string that should be used as the truncation token. This way you can e.g. use "……" for ellipsizing Chinese text. Or you can implement a 'tap to read more' feature by setting the string "… more" with a link attribute as the truncation token and then setting maximumNumberOfLines to 0 when the link is tapped.

  • STULabel lets you customize the possible truncation points in the text. If you e.g. want to prevent truncations in the middle of certain words or after whitespace, you can do so by setting a truncationRangeAdjuster function that doesn't accept such positions.

  • STULabel lets you specify multiple truncation scopes within the same attributed string. This way you can display multiple paragraphs of text in the same label that you otherwise might have to split into multiple labels, which simplifies your layout code and improves performance.

    For example, you can display the full text of a Twitter message in a single STULabel by designating the first line of text with the user name as a separate truncation scope, so that the user name gets truncated if necessary, but the timestamp and the following paragraphs are left intact. The UITableView in the Demo app does exactly this for the "Social media" test cases.

Limitations and differences compared to UILabel and UITextView

No Interface Builder support

Xcode's Interface Builder doesn't support UIFont, NSAttributedString, UIEdgeInsets or any enum type as the type of an IBInspectable property, so there's currently no way to make STULabel work in IB like UILabel or UITextView.

If you can live with the IBInspectable limitations, e.g. because your application only uses a fixed set of "styles", you can of course subclass STULabel and make the subclass IBDesignable .

Auto Layout support

The Auto Layout support for UILabel and UITextView in UIKit makes extensive use of private APIs. Consequently, the Auto Layout support in STULabel has certain limitations:

  • Auto Layout does not natively support views whose intrinsic content height depends (non-linearly) on the layout width. In order to support multi-line text views in Auto Layout, UIKit has a private API that allows UILabel and UITextView to opt into a special two-pass layout process. In complex situations the results of this undocumented two-pass layout are sometimes unsatisfying.

    Since STULabel cannot take part in the two-pass layout, it uses a different approach: It calculates the intrinsic content size by calculating the size of the text both for an unlimited width and for the current view width and then taking the maximum width and height from both sizes. When the view width changes, the intrinsic content size is marked as invalidated and the UIKit layout algorithm is forced to update the layout for the changed intrinsic content size. This approach seems to work reliably even in complex situations.

  • The UIView.systemLayoutsSizeFitting(...) methods calculate a view's size purely based on the subview constraints. They don't call any layoutSubviews method and hence generally can't determine the correct view size if any view in the subview hierarchy depends on manual layout code. Since STULabel's Auto Layout support depends on a full UIKit layout pass, including calls to layoutSubviews, systemLayoutsSizeFitting will not calculate the correct size for a view that contains a multi-line STULabel subview, unless the label already has the correct width. ( UILabel and UITextView don't have this problem because they get the special two-pass layout treatment mentioned before.)

    If you call systemLayoutsSizeFitting in your own code, you can probably replace it with a layoutIfNeeded call on the superview (if necessary, by temporarily adding the view as a child to a superview).

    UITableView and UICollectionView use systemLayoutsSizeFitting for self-sizing cells. A simple way to make this work for cells containing STULabel views is to subclass UITableViewCell/ UICollectionViewCell and override systemLayoutSizeFitting as follows:

    public override 
    func systemLayoutSizeFitting(_ targetSize: CGSize,
           withHorizontalFittingPriority hp: UILayoutPriority,
           verticalFittingPriority vp: UILayoutPriority) -> CGSize
    {
     self.layoutIfNeeded()
     return super.systemLayoutSizeFitting(targetSize, 
                    withHorizontalFittingPriority: hp,
                    verticalFittingPriority: vp)
    }
    

    The layoutIfNeeded() call ensures that all labels already have the correct width when systemLayoutSizeFitting is called. (When UITableView calls this method, the cell's width already matches targetSize.width. If it didn't, you could just adjust the cell's bounds before calling self.layoutIfNeeded.)

  • Returning a STULabel from an viewForFirstBaselineLayout or viewForFirstBaselineLayout property will not have the desired effect due to UIKit private API limitations. However, if you override firstBaselineAnchor and lastBaselineAnchor instead and pass on the respective anchors from the label subview, baseline constraints should work as expected.

  • The system spacing contraints introduced in iOS 11 that you can create e.g. with constraint(equalToSystemSpacingBelow:multiplier:) will not work properly with STULabel views, because they rely on private UIKit APIs. (The exact behaviour of these constraints is undocumented. The iOS 12 implementation calculates a spacing that depends only on the font of the first character of any involved label. Any other font and any paragraph style is ignored.)

    As a replacement for the vertical system spacing constraints, STULabel provides NSLayoutYAxisAnchor extension methods that allow you to create constraints relative to the exact line heights of the involved STULabel views, see NSLayoutAnchor+STULabelSpacing.overlay.swift or NSLayoutAnchor+STULabelSpacing.h.

  • On iOS 9 creating a baseline constraint directly with NSLayoutConstraint.init will not work properly if it involves a STULabel view. You can work around this limitation by creating the constraint with the help of a layout anchor instead. iOS 10 and later iOS versions don't have this issue because the NSLayoutConstraint initializer automatically fetches the respective layout anchors.

Line height

  • UILabel ignores the font leading ('line gap') property when computing the line height and spacing, while UITextView and STULabel do not. This will lead to differences in the default line height and layout bounds if a font has a positive leading.

    Unless compensated by e.g. an appropriate lineSpacing paragraph style property, ignoring a positive leading will generally lead to inadequate line spacing, especially when typesetting e.g. Arabic or Thai text. Note that while the default label font and the fonts returned by UIFont.systemFont have a zero leading, the fonts returned by UIFont.preferredFont usually have a positive leading. (Some preferred fonts also have a negative leading, like e.g. the 'caption2' style fonts for size categories ≤ 'large', but STULabel currently ignores negative leadings.)

  • UILabel and UITextView calculate the line height only based on the typographic metrics of the original fonts, while STULabel in the default text layout mode will also take into account the metrics of fallback fonts that were substituted for the original fonts during typesetting.

    Unless compensated through the paragraph style, ignoring the metrics of the substituted fonts will generally lead to inadequate line heights when typesetting e.g. Asian language texts using the system font. If you prefer the Text Kit behaviour anyway, you can set the STULabel.textLayoutMode to .textKit.

    (The current Text Kit behaviour is probably the reason why the ascent and descent metrics of the fonts returned by UIFont.preferredFont depend on the application locale and are e.g. larger in the Thai locale even when only displaying English text.)

  • The STULabel.textLayoutMode also affects the exact line height and baseline placement in other ways, as described in the documentation for STUTextLayoutMode. If you prefer the Text Kit behaviour, set the textLayoutMode to .textKit.

  • If a UILabel only has a single line, the paragraph style's line spacing is added to the bottom of the content. If the label has more than a single line, it doesn't add any line spacing after the last line. STULabel and UITextView don't imitate this inconsistency and never add any paragraph style line spacing after the last line.

Display scale rounding

When Core Graphics draws non-emoji glyphs into a bitmap context, it will round up the vertical glyph position (assuming an upper-left origin) such that the baseline Y-coordinate falls on a pixel boundary, except if the text is rotated or the context has been configured to allow vertical subpixel positioning by explicitly setting both setShouldSubpixelPositionFonts(true) and setShouldSubpixelQuantizeFonts(false). (The precise font rendering behaviour of Core Graphics and Core Text is completely undocumented and there are no public API functions for reading the current configuration of a CGContext.)

UILabel, UITextView and STULabel all first calculate the text layout ignoring any display scale rounding.

When UILabel draws text, it adjusts the origin of the drawn text rectangle such that the Y-coordinate of the last baseline is rounded to the nearest pixel boundary. Thus, the exact position of the first baseline depends on the position of the last baseline.

UITextView and STULabel don't adjust the vertical text position like UILabel does.

UITextView leaves the baseline display scale rounding to Core Graphics.

STULabel anticipates the display scale rounding by Core Graphics. When it draws a line of text it adjusts the text matrix of the Core Graphics context such that the baseline falls on the next pixel boundary. This approach has the advantage that the rendered emoji and non-emoji glyphs always have the correct relative vertical alignment.

Probably due to these display scale rounding issues, the intrinsic content height or sizeThatFits of a UILabel or UITextView can in certain situations be 1 pixel too short. Similarly, the vertical position of an UILabel or UITextView baseline anchor can be off by 1 pixel. STULabel doesn't have these issues.

Alignment and layout bounds

  • UILabel always displays the content vertically centered within its bounds, while UITextView always uses top-aligmnent. STULabel lets you chose between top, bottom and 3 types of vertical center alignments (centered around the midpoint of the layout bounds, the x-height bounds or the cap-height bounds).

  • UITextView and STULabel both have customizable content insets, i.e. padding around the text. The UITextView.textContainerInset is non-zero by default, while the STULabel.contentInsets are zero by default.

    STULabel also supports setting the insets based on the UI layout direction (via the STULabel.directionalContentInsets) and exposes a UILayoutGuide that is pinned to bounds of the label without the insets (STULabel.contentLayoutGuide).

    UILabel does not have built-in support for content insets. It is possible to subclass UILabel and override UILabel.textRect(forBounds:limitedToNumberOfLines:) in order to implement such insets, but this can break e.g. parts of the Auto Layout support, particularly for attributed strings.

  • Content insets can be important for ensuring that diacritics or other text features that exceed the typographic layout bounds do not get clipped during the rendering. Since UILabel doesn't have insets, it uses a different approach: When it displays text, it calculates outsets for the text that depend on the text content and the used fonts. These outsets are usually conservative and appear to be based on whether the text contains code points from certain Unicode ranges. If the layout bounds plus the calculated outsets do not fit the label view bounds and the view's clipsToBounds property is false (the default), the text is displayed in a sublayer whose frame exceeds the labels bounds. If it wasn't for this feature, e.g. Arabic or Thai text using the system font would regularly get clipped when being displayed in a UILabel view.

    Even though STULabel does support insets, it doesn't rely on the insets for ensuring that diacritics and text decorations do not get clipped. Like UILabel it will switch to displaying the text in a sublayer if necessary (unless clipsContentToBounds is set to true). However, in contrast to UILabel, STULabel uses the exact image bounds of the rendered text, not some inaccurate estimates, to determine whether it needs to use a sublayer. This only costs a few percent performance overhead because STULabel uses a very fast custom glyph bounds cache.

Line breaking and truncation

  • The line breaks that STULabel chooses for a given layout width and font size may slightly differ from those chosen by UILabel and UITextView, particularly for complex scripts.

  • The STULabel.sizeThatFits(_ maxSize:) method will calculate the size that fits the specified size, even if it means truncating or scaling the text, as specified by the truncation and scaling settings. If you want a size that doesn't involve truncation, pass a sufficiently large maximum size. This behaviour differs from the behaviour of UILabel and UITextView.

  • STULabel, UILabel and UITextView all handle a NSParagraphStyle.lineBreakMode that is not equal to byWordWrapping differently. The STULabel behaviour is hopefully consistent and intuitive.

  • In contrast to UILabel and UITextView, STULabel doesn't allow "head" or "middle" truncation of the first paragraph in a multiple-paragraph truncation, because that could mislead the reader as to which part of the text was truncated. It will automatically switch to "tail" truncation instead. Similarly, STULabel will not omit the truncation token after a paragraph if the paragraph itself fully fits but not a single line of the following text.

  • STULabel does not support NSLineBreakMode.byClipping at the paragraph level, but you can specify .clip as the STULabel.lastLineTruncationMode to allow clipping at the end of a label.

  • STULabel does not support "text tightening", i.e. negative kerning, as an alternative to truncation, like UILabel does through the allowsDefaultTighteningForTruncation and NSParagraphStyle.allowsDefaultTighteningForTruncation properties.

    If you want to avoid truncation, consider allowing the text to scale by specifiying a minimumTextScaleFactor less than 1.

Text attributes and decorations

  • If you set an attributed string that contains text ranges without a font property to the attributedText or shapedText property of a STULabel, the Core Text default font (Helvetica 12pt) will be used for those text ranges. Since that is probably not the font that you want, you should make sure that all ranges in the attributed string have an explicitly specified font. UILabel and UITextView use UIFont.systemFont(size: 17) as the default font in that situation.

  • STULabel will generally draw text decorations slightly different from UILabel and UITextView. For example, the underline thickness is calculated based both on the original font and the substituted font (which leads to a more consistent thickness) and the descender gaps are more accurate.

  • STULabel does not support NSUnderlineStyle.byWord.

  • STULabel does not support the .obliqueness, .expansion and .textEffect string attributes. Instead of using these attributes, you could use a different font (possibly one with a nonstandard font matrix).

  • STULabel does not support NSTextBlock, NSTextList, NSTextTable and other Text Kit attributes.

Links

  • STULabel has no built-in support for automatically detecting URLs, telephone numbers, etc. like UITextView does through the dataDetectorTypes property.

    Instead of letting the label detect the links, you could implement a helper function that uses NSDataDetector to find the relevant text ranges and construct an attributed string containing the appropriate links. Doing it this way makes it obvious in your code when this potentially expensive operation runs and simplifies moving the work into a background thread.

  • STULabel has no built-in support for 3D touch or "Peek and Pop" link preview.

  • The way links embedded in the text are announced by Voice Over and the way links are navigable via Voice Over differ between STULabel, UILabel and UITextView and depend on the iOS version. Some of the relevant UIAccessibility API is private, which complicates the support in STULabel.

Other limitations

  • STULabel currently does not support text selection. (The infrastructure for mapping points to characters already exists, but the selection logic, gesture recognition, etc. still needs to be implemented.)

  • STULabel and STUTextFrame don't support specifying an exclusion path, in contrast to UITextView and NSTextContainer.

    In some situations, horizontal paragraph indentations may be a sufficient alternative to a general exclusion path. STUParagraphStyle lets you specify the number of lines in a paragraph to which the initialLinesHeadIndent and a initialLinesTailIndent apply (similar to what you can do with Android's LeadingMarginSpan2), which make the indentations a little more flexible than in UILabel and UITextView.

  • STULabel does not support vertical text.

(This list is not complete.)

Comments
  • macOS Catalyst Support

    macOS Catalyst Support

    So this diff is kinda massive, but it does work. I split up the type collision and the Catalyst gating separately.

    This also just cuts out the STU_USE_SAFARI_SERVICES gating and what not since TARGET_OS_MACCATALYST is better

    tbh I totally understand if you don't want to do the type collision changes since they add namespaces everywhere and it's kinda gigantic of a refactor

    I tried running the tests but there were a bunch of failures (on iOS simulator) for like font references and stuff but didn't see anything really these changes would've caused

    opened by b3ll 12
  • STULabelSuperlayerObserver -dealloc Race / Crash

    STULabelSuperlayerObserver -dealloc Race / Crash

    So I've been messing about with things a bunch recently, specifically using STULabel with both Texture (AsyncDisplayKit) and SwiftUI, and I've noticed there's a pretty wonky crash happening with the KVO stuff as part of STULabelSuperlayerObserver.

    Basically, it's getting into a state where STULabelLayer's -dealloc is being invoked, which is causing STULabelSuperlayerObserver's -dealloc to be invoked, which'll crash since it's trying to remove observers on an object that's already been deallocated (rather than having the STULabelSuperlayerObserver explicitly torn down / removed beforehand).

    What's the purpose of STULabelSuperlayerObserver / does it need to be used?

    I've been messing a bunch with this trying to fix it, and it seems to only happen once I present a View Controller (containing an STULabel wrapped in a ScrollView), and then later dismiss it. Changing the _layer to not be __unsafe_unretained mitigates the issue, but then also causes all STULabels to never release lol

    opened by b3ll 6
  • build fails

    build fails

    Using the cocoa pod, the project wont build, i get this error:

    In file included from /Volumes/data/dev/nativescript/nativescript-label/dev_demo/platforms/ios/Pods/STULabel/STULabel/STUTextHighlightStyle-Internal.hpp:5:
    /Volumes/data/dev/nativescript/nativescript-label/dev_demo/platforms/ios/Pods/STULabel/STULabel/Internal/TextStyle.hpp:178:12: error: no matching constructor for initialization of
          'stu_label::UnderlineStyle'
        return {static_cast<UInt16>(style_ & ~underlineMinYIsStrictBit)};
               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /Volumes/data/dev/nativescript/nativescript-label/dev_demo/platforms/ios/Pods/STULabel/STULabel/Internal/TextStyle.hpp:86:8: note: candidate constructor (the implicit move constructor)
          not viable: no known conversion from 'stu::UInt16' (aka 'unsigned short') to 'stu_label::UnderlineStyle' for 1st argument
    struct UnderlineStyle : Parameter<UnderlineStyle, UInt16> {
           ^
    /Volumes/data/dev/nativescript/nativescript-label/dev_demo/platforms/ios/Pods/STULabel/STULabel/Internal/TextStyle.hpp:86:8: note: candidate constructor (the implicit copy constructor)
          not viable: no known conversion from 'stu::UInt16' (aka 'unsigned short') to 'const stu_label::UnderlineStyle' for 1st argument
    struct UnderlineStyle : Parameter<UnderlineStyle, UInt16> {
           ^
    /Volumes/data/dev/nativescript/nativescript-label/dev_demo/platforms/ios/Pods/STULabel/STULabel/Internal/TextStyle.hpp:88:3: note: candidate constructor not viable: no known conversion
          from 'stu::UInt16' (aka 'unsigned short') to 'NSUnderlineStyle' for 1st argument
      UnderlineStyle(NSUnderlineStyle underlineStyle = {})
      ^
    

    Can you help?

    Xcode compatibility 
    opened by farfromrefug 6
  • Reference to 'Byte' is ambiguous compiler error under Xcode 12

    Reference to 'Byte' is ambiguous compiler error under Xcode 12

    Compiler error on Xcode 12:

    Reference to 'Byte' is ambiguous

    in 5 places.

    Pods/STULabel/STULabel/Internal/TextStyle.hpp:432:59: Reference to 'Byte' is ambiguous Pods/STULabel/STULabel/Internal/TextStyle.hpp:433:55: Reference to 'Byte' is ambiguous Pods/STULabel/STULabel/Internal/TextStyle.hpp:327:71: Reference to 'Byte' is ambiguous Pods/STULabel/STULabel/Internal/TextStyle.hpp:335:71: Reference to 'Byte' is ambiguous Pods/STULabel/STULabel/Internal/TextStyle.hpp:448:50: Reference to 'Byte' is ambiguous

    opened by tkirby 5
  • Fails to build on Xcode 10.2 beta 1

    Fails to build on Xcode 10.2 beta 1

    Some new C++ stuff seems to have been changed but I don't really understand a lot of the template stuff you wrote :P

    Any chance you could take a look?

    Thanks!

    STULabel/STULabel/Internal/NSStringRef.hpp:105:41: note: in instantiation of exception specification for 'operator _NSRange<_NSRange, unsigned long, 0>' requested here
            copyUTF16Chars_slowPath(NSRange(utf16IndexRange), out.begin());
    
    opened by b3ll 4
  • Declaration of 'atomic' must be imported from module 'std.atomic' before it is required

    Declaration of 'atomic' must be imported from module 'std.atomic' before it is required

    I m not able to my code because it gives me an error "Declaration of 'atomic' must be imported from module 'std.atomic' before it is required" X code version 13.3.1 Pod "STULabelSwift', '~> 0.8.7'" Min Deployment target 13.0 Screenshot 2022-06-15 at 12 23 20 PM

    opened by rakesh6932 2
  • OSTypes.h UInt Collision

    OSTypes.h UInt Collision

    When compiling for Catalyst (iOSMac) it seems to import OSTypes.h (which also imports MacTypes.h) and OSTypes.h defines UInt which collides with the one used in Config.hpp.

    I'm not sure what the easy fix for this is, we could codemod everything to use the stu:: prefix, but that'd make things look super verbose. I don't know enough C++ to do anything otherwise tho :/

    opened by b3ll 2
  • Fix Incorrect Resources Bundle Configuration

    Fix Incorrect Resources Bundle Configuration

    In order to submit to the App Store, some plist configurations needed to be fixed.

    Firstly, Apple requires a project version so I just supplied that via an xcconfig to be updated if need be.

    Second, the resources bundle was referencing an executable that didn't exist so the archive utility would complain.

    opened by b3ll 2
  • Declaration of 'atomic' must be imported from module 'std.atomic' before it is required

    Declaration of 'atomic' must be imported from module 'std.atomic' before it is required

    I'm using Xcode 13.4 and this Error Occurs :

    Pods/STULabel/STULabel/STUTextLink.mm:443:8: Declaration of 'atomic' must be imported from module 'std.atomic' before it is required

    opened by areejsadaqa66 1
  • Fix Building for Xcode 11.4

    Fix Building for Xcode 11.4

    This fixes some issues with building for Xcode 11.4:

    1. Rect gets confused with MacTypes (yay) so it needs to be marked explicitly as stu_label::Rect
    2. There's loads of duplicate symbols for minValue / maxValue, so this just makes them inline… I don't know why they're being compiled as duplicates tho
    opened by b3ll 1
  • Migrate to Swift version 5.0

    Migrate to Swift version 5.0

    • Migrated with Xcode 11.1, no code changes required
    • Updated swift_version in podspec to 5.0 so that the pod now works with supports_swift_versions in Podfile, which is officially introduced in cocoapods 1.7.0
    opened by akisute 1
  • Building using Xcodebuild on m1 Mac fails

    Building using Xcodebuild on m1 Mac fails

    M1 iMac XCode 13.4

    Always throws error during build. Removing derived data doesn't fix it. Building directly in Xcode works fine, only happens in Xcodebuild. Removing STULabel lets build succeed.

    /Users/MyUser/Library/Developer/Xcode/DerivedData/bb-iphone-gxoeyvvbhtizhsemkonoptlbnczq/Build/Intermediates.noindex/ArchiveIntermediates/bb-iphone/IntermediateBuildFilesPath/Pods.build/Release-iphoneos/STULabel.build/Objects-normal/arm64/STUTextFrameLine.dia:1:1: warning: Could not read serialized diagnostics file: error("Failed to open diagnostics file") (in target 'STULabel' from project 'Pods')

    opened by tkirby 0
  • setText bug, unable to update text to blank

    setText bug, unable to update text to blank

    Wonder library for sure :)

    I've been bumping into an issue since day one with STULabel. Seems you can't set a label with a text (like: "abc") And then update with a blank text (like: " ") or ("") or even multiple spaces But the text simply won't update.

    My work-around, after trying so many different options: Create your own update function of STULabel, in an extension. And then call that function, everytime you want to update a text. What it does: it makes the text invisible, when-ever it is empty, and visible, when it has a text.

    extension STULabel {

    public func update(_ text: String) { // fix: empty text doesn't update field!
        self.text = text
        self.isHidden = text.isEmpty // <- fix 
    }
    

    }

    Hope this helps someone, who's still using this amazing library. This is of course a temporary fix, but it works really good.

    opened by vanesca88 0
  • EXC_BREAKPOINT - stu_label::FontFaceGlyphBoundsCache::boundingRect

    EXC_BREAKPOINT - stu_label::FontFaceGlyphBoundsCache::boundingRect

    Faced such an error. It would be nice to find a solution to this problem. It is not possible to determine the case, I have never shown it. However, users get it quite often (on different versions of iOS and smartphone models)

    Crashed: Thread EXC_BREAKPOINT 0x0000000000000001 0 STULabel stu_label::FontFaceGlyphBoundsCache::boundingRect(double, stu::ArrayRef, CGPoint const*) + 3684 (Font.mm) 1 STULabel ThreadLocalAllocatorRef + 4 [inlined] (ThreadLocalAllocator.hpp:68) 2 STULabel ThreadLocalAllocatorRef + 4 [inlined] (ThreadLocalAllocator.hpp:69) 3 STULabel TempVector + 28 [inlined] (ThreadLocalAllocator.hpp:119) 4 STULabel TempVector + 28 [inlined] (ThreadLocalAllocator.hpp:122) 5 STULabel stu_label::FontFaceGlyphBoundsCache::boundingRect(double, stu::ArrayRef, CGPoint const*) + 96 (Font.mm:522) 6 STULabel stu_label::GlyphSpan::imageBoundsImpl(stu_label::GlyphRunRef, CFRange, stu_label::LocalGlyphBoundsCache&) + 64 (GlyphSpan.mm:47) 7 STULabel isEmpty + 0 [inlined] (Rect.hpp:339) 8 STULabel operator() + 48 [inlined] (TextFrameLine-ImageBounds.mm:185) 9 STULabel call<(lambda at /STULabel/Internal/TextFrameLine-ImageBounds.mm:180:5)> + 88 (FunctionRef.hpp:209) 10 STULabel stu_label::TextFrameLine::forEachCTLineSegment(stu_label::FlagsRequiringIndividualRunIteration, stu::FunctionRef<stu_label::ShouldStop (stu_label::TextLinePart, stu_label::CTLineXOffset, __CTLine const&, stu::Optional<stu_label::GlyphSpan>)>) const + 520 (TextFrameLine-GlyphSpanIteration.mm:37) 11 STULabel calculateLineGlyphPathBoundsLLO + 44 [inlined] (TextFrameLine-ImageBounds.mm:191) 12 STULabel calculateLineImageBoundsLLO + 108 [inlined] (TextFrameLine-ImageBounds.mm:219) 13 STULabel stu_label::TextFrameLine::calculateImageBoundsLLO(stu_label::ImageBoundsContext const&) const + 392 (TextFrameLine-ImageBounds.mm:472) 14 STULabel stu_label::TextFrame::calculateImageBounds(stu_label::TextFrameOrigin, stu_label::ImageBoundsContext const&) const + 352 (TextFrame.mm:380) 15 STULabel STUTextFrameGetImageBoundsForRange(STUTextFrame const*, STUTextFrameRange, CGPoint, double, STUTextFrameDrawingOptions const*, STUCancellationFlag const*) + 568 (STUTextFrame.mm) 16 STULabel inverseValue_f64 + 0 [inlined] (DisplayScaleRounding.hpp:68) 17 STULabel inverseValue + 0 [inlined] (DisplayScaleRounding.hpp:54) 18 STULabel stu_label::labelTextFrameRenderInfo(STUTextFrame const*, stu_label::LabelTextFrameInfo const&, CGPoint const&, stu_label::LabelParameters const&, bool, bool, STUCancellationFlag const*) + 224 (LabelRendering.mm:130) 19 STULabel stu_label::LabelLayer::display() + 588 (STULabelLayer.mm:1155) 20 QuartzCore CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 416 21 QuartzCore CA::Context::commit_transaction(CA::Transaction*, double, double*) + 416 22 QuartzCore CA::Transaction::commit() + 728 23 QuartzCore CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 92 24 CoreFoundation CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION + 32 25 CoreFoundation __CFRunLoopDoObservers + 604 26 CoreFoundation __CFRunLoopRun + 960 27 CoreFoundation CFRunLoopRunSpecific + 572 28 GraphicsServices GSEventRunModal + 160 29 UIKitCore -[UIApplication _run] + 1052 30 UIKitCore UIApplicationMain + 164 31 MyApplication main + 88 (main.m:14) 32 libdyld.dylib start + 4

    opened by oMystique 0
  • Arabic Language not supported getting error please help me

    Arabic Language not supported getting error please help me

    Arabic Language is not supported in STULabel I am facing some error.

    Error is => 'Condition not satisfied: false && "The key must be less than maxValue"'

    I am used below text.

    "‏والسونا مروحين يوم نسمع"

    Please Help

    Screenshot 2021-03-06 at 12 37 21 PM

    opened by ApurvSpaceo 0
  • Changing the color of the read more or less link.

    Changing the color of the read more or less link.

    Attached is the demo project with the changed TapToReadMoreVC class in an attempt to change the link color. Is there any way we can change link colors? STULabel-master.zip

    opened by dawood-Khalid 0
Owner
Stephan Tolksdorf
Stephan Tolksdorf
A triangle shaped corner label view for iOS written in Swift.

A triangle shaped corner label view for iOS written in Swift. This view is a subclass of UIView. It can be created and customized from the Storyboard

Mukesh Thawani 167 Nov 30, 2022
NumberMorphView a view like label for displaying numbers which animate with transition using a technique called number tweening or number morphing.

NumberMorphView a view like label for displaying numbers which animate with transition using a technique called number tweening or num

Abhinav Chauhan 1.6k Dec 21, 2022
Configurable morphing transitions between text values of a label.

TOMSMorphingLabel Configurable morphing transitions between text values of a label. Triggering the animation is as easy as setting the labels text pro

Tom König 1.9k Nov 20, 2022
Custom Label to apply animations on whole text or letters.

Ophiuchus Custom Label to apply animations on whole text or letters. Check an article on our blog Inspired by this project on Dribble Installation Coc

Yalantis 885 Dec 2, 2022
Animate numeric value while setting new value to label

NumericAnimatedLabel Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements Installati

Javal Nanda 28 Oct 11, 2021
OdometerLabel - SwiftUI number label with odometer animation

Пример Simulator.Screen.Recording.-.L.iPhone.12.-.2022-01-30.at.16.26.53.mp4

Misnikov Roman 2 Jun 13, 2022
A drop-in replacement for UILabel that supports attributes, data detectors, links, and more

TTTAttributedLabel A drop-in replacement for UILabel that supports attributes, data detectors, links, and more TTTAttributedLabel is a drop-in replace

TTTAttributedLabel 8.8k Dec 30, 2022
Incrementable UILabel for iOS and tvOS

IncrementableLabel IncrementableLabel is the easiest way to have incrementable numbers in an UILabel! Usage let myIncrementableLabel = IncrementableLa

Tom Baranes 81 Feb 4, 2022
Simple countdown UILabel with morphing animation, and some useful function.

CountdownLabel Simple countdown UILabel with morphing animation, and some useful function. features Simple creation Easily get status of countdown fro

keishi suzuki 903 Dec 29, 2022
UILabel subclass, which additionally allows shadow blur, inner shadow, stroke text and fill gradient.

THLabel THLabel is a subclass of UILabel, which additionally allows shadow blur, inner shadow, stroke text and fill gradient. Requirements iOS 4.0 or

Tobias Hagemann 654 Nov 27, 2022
A simple designable subclass on UILabel with extra IBDesignable and Blinking features.

JSLabel Demo pod try JSLabel ...or clone this repo and build and run/test the JSLabel project in Xcode to see JSLabel in action. If you don't have Coc

Jogendra 6 May 9, 2022
Glitching UILabel for iOS 📺

Glitching UILabel for iOS ?? Created by Lee Sun-Hyoup. Try the sample $ pod try GlitchLabel Requirements iOS 8.0+ Swift 3 Xcode 8 Installation CocoaP

Lee Sun-Hyoup 1k Dec 14, 2022
A handy class for iOS to use UILabel as a countdown timer or stopwatch just like in Apple Clock App.

MZTimerLabel Purpose MZTimerLabel is a UILabel subclass, which is a handy way to use UILabel as a countdown timer or stopwatch just like that in Apple

Mines Chan 1.6k Dec 14, 2022
Animated, customizable, and flexible pull-to-refresh framework for faster and easier iOS development.

KafkaRefresh Animated, customizable, and flexible pull-to-refresh framework for faster and easier iOS development. Report bug · Request feature · 中文文档

H. H. Hsiang 1.2k Dec 11, 2022
Animated Mask Label is a nice gradient animated label.

Animated Mask Label Demo Screen Screenshot Demo/Example For demo: $ pod try AnimatedMaskLabel To run the example project, clone the repo, and run pod

Jogendra 19 Dec 13, 2022
A handy collection of Swift method and Tools to build project faster and more efficient.

SwifterKnife is a collection of Swift extension method and some tools that often use in develop project, with them you might build project faster and

李阳 4 Dec 29, 2022
A beautiful and flexible text field control implementation of "Float Label Pattern". Written in Swift.

SkyFloatingLabelTextField SkyFloatingLabelTextField is a beautiful, flexible and customizable implementation of the space saving "Float Label Pattern"

Skyscanner 4k Jan 1, 2023
A beautiful and flexible text field control implementation of "Float Label Pattern". Written in Swift.

SkyFloatingLabelTextField SkyFloatingLabelTextField is a beautiful, flexible and customizable implementation of the space saving "Float Label Pattern"

Skyscanner 4k Jan 3, 2023
More powerful label, attributed string builder and text parser.

DDText More powerful label, attributed string builder and text parser. DDLabel More powerful label than UILabel, using TextKit. It supports features b

Daniel 16 Nov 8, 2022
PagingKit provides customizable menu UI. It has more flexible layout and design than the other libraries.

PagingKit provides customizable menu & content UI. It has more flexible layout and design than the other libraries. What's this? There are many librar

Kazuhiro Hayashi 1.3k Jan 9, 2023