DTRichTextEditor – Cocoanetics https://www.cocoanetics.com Our DNA is written in Swift Thu, 19 Nov 2015 08:41:44 +0000 en-US hourly 1 https://wordpress.org/?v=6.4.3 39982308 DTRichTextEditor 1.6.12 + DTLoupe 1.5.8 https://www.cocoanetics.com/2015/11/dtrichtexteditor-1-6-12-dtloupe-1-5-8/ https://www.cocoanetics.com/2015/11/dtrichtexteditor-1-6-12-dtloupe-1-5-8/#respond Thu, 19 Nov 2015 08:41:44 +0000 https://www.cocoanetics.com/?p=9990 These updates to DTRichTextEditor and DTLoupe address some tenacious crashes occurring from invalid geometry of sublayers.

Changes

  • FIXED: Invalid Geometry Crash fix
  • FIXED: Orientation problems under iOS 9

Thanks to Hirad Motamed, Amro Mousa and Dominik Pich. They came together on GitHub to work out the fixes in concert.

The update is tagged on GitHub and also published on Cocoapods.

]]>
https://www.cocoanetics.com/2015/11/dtrichtexteditor-1-6-12-dtloupe-1-5-8/feed/ 0 9990
DTRichTextEditor 1.6.11 https://www.cocoanetics.com/2015/07/dtrichtexteditor-1-6-11/ https://www.cocoanetics.com/2015/07/dtrichtexteditor-1-6-11/#respond Mon, 27 Jul 2015 14:31:36 +0000 http://www.cocoanetics.com/?p=9825 I had moved DTRichTextEditor to be Open Source because I wanted bright individuals to be able to contribute to this complex component. I had hatched the plan to ask people who are using the component commercially to set a bounty for fixed issues. This is the second release where a bounty was successfully captured.

Changes

  • FIXED: Problems with dictation placeholder leading to crash or double text insertion
  • CHANGED: Updated DTLoupe to 1.5.7 – to support bundle in iOS framework

The bounty for this release was captured by Brian Lundgren. He did so by adjusting the way the dictation placeholder is handled. Congratulations!

I also set up a continuous integration build on Travis-CI, but found an issue in implicit dependency building, which I filed a Radar for. This is the reason why so many builds failed. I also tried the Xcode 6.4 image Travis-CI is providing for testing, but this does nothing to address the issue. Rather it has a different issue: the travis.yml script line calling appledoc does not appear to be working there, it just silently fails the build. So I reverted back to the standard settings.

I later found that DTRichTextEditor.framework for iOS was missing DTCoreText as explicit dependency. Once all dependencies are explicitly defined, Xcode does not seem to try to find the dependencies by itself.

The update is available on CocoaPods as well as tagged on GitHub.

]]>
https://www.cocoanetics.com/2015/07/dtrichtexteditor-1-6-11/feed/ 0 9825
DTRichTextEditor 1.6.10 https://www.cocoanetics.com/2015/07/dtrichtexteditor-1-6-10/ https://www.cocoanetics.com/2015/07/dtrichtexteditor-1-6-10/#respond Tue, 07 Jul 2015 11:39:54 +0000 https://www.cocoanetics.com/?p=9769 This is the first update since the project has been open-sourced. Together with the updates in all sub-modules it now supports Cocoapods frameworks and modules.

Changes

  • FIXED: Crash in DTLoupe
  • FIXED: Crash on iOS <= 5.1.1
  • ADDED: iOS Framework
  • ADDED: Support for CocoaPods frameworks and Modules

The most valuable contribution came from Amro Mousa who fixed an iOS 8 issue where rendering a snapshot of a layer with invalid dimensions would cause a crash.

This bug had been unfixed for a long time while the framework was still private. After the switch to Open Source and putting out a bounty on the swatting of this bug, it got fixed within a few days.

So I am cautionsly optimistic that the approach of publicly offering bounties seems to work. If only because issues get more exposure because of this.

The update is available on CocoaPods and tagged on GitHub.

]]>
https://www.cocoanetics.com/2015/07/dtrichtexteditor-1-6-10/feed/ 0 9769
DTRichTextEditor Goes Open Source https://www.cocoanetics.com/2015/06/dtrichtexteditor-goes-open-source/ https://www.cocoanetics.com/2015/06/dtrichtexteditor-goes-open-source/#comments Mon, 22 Jun 2015 16:07:09 +0000 http://www.cocoanetics.com/?p=9737 Development on DTRichTextEditor had started in 2011, several years before Apple revamped the internals of UITextView to TextKit. I based it on DTCoreText – which had been open source from the start – and added a custom magnifying glass to mimic the one provided by the system. As of today, I am making it Open Source.

Back in 2011, I saw a market for a rich text editing component as there was nothing anywhere to be found to achieve that. With every passing WWDC we could be anxious to see if Apple had finally made it obsolete. But Apple only slightly revamped UITextView in iOS 6 (2012) and more thoroughly replaced the text view innards with TextKit in iOS 7 (2013). But little has changed about rich text in UIKit since then, it is still is missing important features like support for lists and floating images.

A Mild Success

When I started my component business in January 2008 I was doing pretty well selling specialized components. But for the last several years the income from components has all but subsided. DTRichTextEditor was the only component that kept selling a few licenses every now and then. I attribute this to the above mentioned shortcomings of UITextView.

Over it’s lifetime so far, 86 clients bought commercial licenses for using the rich text editor component in their app store apps, some to get support for lists, some for inline graphics. The most famous being Mailchimp who used it in their iPad app. But even those occasionally sold licenses were far in between.

Even though this number of sold licenses might sound much it is nowhere near enough to pay for the endless hours of work I spend on it. Let alone the work that came from several volunteers who received free licenses for the editor in exchange for their contributions.

The Support Problem

Supporting such a complex component would probably be enough work for a full time developer. The one-off license model for components only works if there is no ongoing support cost. Or if you have enough new sales to pay for ongoing development. Unfortunately I did never have the chutzpah to charge a support subscription, as many other vendors of commercial components do. But this apparently is the only sustainable model.

For a long time I have been wrangling with myself, going back and forth over what to do with this favorite project of mine. It does have some value still, but not enough to be viable commercially. I spent months on it, but I would never make enough to warrant any more investment into it.

So I decided to draw the line here, one week after WWDC 2015. I decided to move DTRichTextEditor and DTLoupe onto GitHub. My top component there is DTCoreText: it is getting contributions and much usage. I am hoping that the Open Source community there will also love to use and contribute to the editor.

The Logistics

Earlier today I cloned the two repos from my private GitLab server onto public GitHub repos: DTRichTextEditor, DTLoupe. The URLs for the git submodules as well as the podspecs were updated to point to the new locations.

The license was changed from a specialized commercial one to my standard 2-clause BSD license. You can use it for free in your apps with attribution, or buy a non-attribution license from me. Or you can contribute and then you can use it for free without attributing it to me. How does that sound?

There are a few pressing issues inherent in the project. DTLoupe has a crashing bug that – I think – comes from an internal racing condition in UIKit using the old-style renderInContext: methods for taking snapshots of view. It is my hope that somebody can figure this out and provide a fix. Or better yet, modernize it to use the newer, faster view snapshotting methods.

I am hoping that people whose app’s value proposition depends on the editor are willing to provide a bounty for the person who provides a fix.

]]>
https://www.cocoanetics.com/2015/06/dtrichtexteditor-goes-open-source/feed/ 3 9737
DTRichTextEditor 1.6.9 https://www.cocoanetics.com/2015/02/dtrichtexteditor-1-6-9/ https://www.cocoanetics.com/2015/02/dtrichtexteditor-1-6-9/#respond Fri, 20 Feb 2015 16:40:42 +0000 http://www.cocoanetics.com/?p=9472 This update to DTRichTextEditor contains several pressing fixes.

Changes

  • FIXED: Dictation failure would lead to subsequent crash
  • FIXED: Loss of attachment attributes causes retina attachments to double in size
  • FIXED: Scroll indicator inset should be zero for left and right sides
  • FIXED: Static Framework missing DTCoreTextMacros.h
  • FIXED: Rotation of editor view controller causes too big bottom content inset
  • FIXED: Content inset was incorrect with hidden keyboard but input view still showing (i.e. hardware keyboard)
  • CHANGED: Updated DTCoreText to 1.6.15

The update is available for customers on the private repository and also via Cocoapods (private spec repo).

]]>
https://www.cocoanetics.com/2015/02/dtrichtexteditor-1-6-9/feed/ 0 9472
DTRichTextEditor 1.6.8 + DTLoupe 1.5.5 https://www.cocoanetics.com/2014/09/dtrichtexteditor-1-6-8-dtloupe-1-5-5/ https://www.cocoanetics.com/2014/09/dtrichtexteditor-1-6-8-dtloupe-1-5-5/#respond Thu, 18 Sep 2014 12:36:13 +0000 http://www.cocoanetics.com/?p=9274 This update for DTRichTextEditor and DTLoupe hot fixes an issue with loupe rotation under iOS 8.

DTLoupe 1.5.5 Changes

  • FIXED: Rotation problem on iOS 8

DTRichTextEditor 1.6.8 Changes

  • CHANGED: Update to DTLoupe 1.5.5

The root cause of the problem is that iOS no longer sets the transform on the root view because Apple generally wants to do away with the concept of interface orientation. DTLoupeView was updated to use the status bar orientation, root view controller’s interfaceOrientation, or if all fails calculates it from the main window aspect ration and device orientation. We might have to revisit this for iOS 9.

Known issue: DTLoupeView adds a custom UIWindow so that it is not part of the main view hierarchy. This causes the status bar to reappear if you had it hidden. Dealing with this would take some work and architectural changes. I believe that most users of DTRichTextEditor would leave the status bar visible anyway, so I won’t do anything about that.

The update is available via the private Cococapods Spec to existing customers and in the private GitLab repository.

]]>
https://www.cocoanetics.com/2014/09/dtrichtexteditor-1-6-8-dtloupe-1-5-5/feed/ 0 9274
DTRichTextEditor 1.6.7 https://www.cocoanetics.com/2014/07/dtrichtexteditor-1-6-7/ https://www.cocoanetics.com/2014/07/dtrichtexteditor-1-6-7/#respond Mon, 07 Jul 2014 09:46:34 +0000 http://www.cocoanetics.com/?p=9219 This maintenance release for DTRichTextEditor brings together various fixes from recent DTCoreText and DTFoundation updates and adds support for tint color.

Changes

  • ADDED: Support for tintColor on >= iOS 7
  • FIXED: iOS 8 crash
  • FIXED: Image text attachments missing from HTML output
  • CHANGED: Updated DTCoreText to 1.6.13

Where were a few settings changes suggested by Xcode 6 that required some project tweaks. Instead of always using the default blue color for cursors and selection areas, on iOS 7 and above the component now obeys the tint color. This allows you to customize the editor view to match your tint color requirements.

RichTextEditor tintColor support

The update is tagged on the private repository and also released via the private Cocoapods specs repository.

]]>
https://www.cocoanetics.com/2014/07/dtrichtexteditor-1-6-7/feed/ 0 9219
DTRichTextEditor 1.6.6 https://www.cocoanetics.com/2013/12/dtrichtexteditor-1-6-6/ https://www.cocoanetics.com/2013/12/dtrichtexteditor-1-6-6/#respond Wed, 18 Dec 2013 13:49:55 +0000 http://www.cocoanetics.com/?p=8893 This is a maintenance release for DTRichTextEditor. It contains only updates for the involved submodules.

DTRichTextEditor 1.6.6

  • CHANGED: Updated DTLoupe to 1.5.4
  • CHANGED: Updated DTCoreText to 1.6.10
  • CHANGED: Updated DTFoundation to 1.6.1

DTLoupe 1.5.4

  • FIXED: iOS 6 compatibility issue workaround by moving loupe content delegate into separate class
  • FIXED: Warning about incorrect animation option
  • CHANGED: Improved loupe content update by using layer display method as opposed to drawing the layer
  • CHANGED: Reverted fix for status bar content mode from 1.5.2

The update is tagged on the private GitLab repo as well as available via podspec on the private Cocoanetics CocoaPods repo. 

]]>
https://www.cocoanetics.com/2013/12/dtrichtexteditor-1-6-6/feed/ 0 8893
DTRichTextEditor 1.6.5 https://www.cocoanetics.com/2013/11/dtrichtexteditor-1-6-5/ https://www.cocoanetics.com/2013/11/dtrichtexteditor-1-6-5/#respond Thu, 21 Nov 2013 15:04:42 +0000 http://www.cocoanetics.com/?p=8854 The update for DTRichTextEditor adds support for building for arm64 and fixes two bugs.

DTRichTextEditor 1.6.5

  • ADDED: support for arm64
  • FIXED: Hyperlink would continue to be extended when typing right of it
  • FIXED: Text get corrupted during Dictation on iOS 7
  • FIXED: Setting the attributed text to nil would not remove selection
  • CHANGED: Updated DTCoreText to 1.6.9
  • CHANGED: Updated DTFoundation to 1.6.0

DTLoupe 1.5.3

  • FIXED: Potential crash when presenting the editor in a modal view controller
  • CHANGED: Improved loupe smoothness when panning
  • CHANGED: Modernized method of getting loupe contents
  • ADDED: Support for arm64

Previously I had a roundf in place when setting the loupe’s frame, which caused it to be moved 2 pixels at a time on Retina displays. There was a quite noticeable difference in smoothness when I changed this round to consider the content scale. Support for arm64 was added which meant that I had to fix a few related warnings.

There were some stability issues when using the editor in some special circumstances where some changes in iOS 7 were wreaking havoc. I hope that this is now resolved by making some changes and cleaning up the way the magnified loupe content is being generated.

Curiously with iOS 7 UITextInput has started to insert 10 spaces ahead of a dictation result. This caused the positions to be off and cause the inserted dictation text to overwrite previously existing text. I also updated the way the dictation result is inserted. I don’t rely on the default calling of insertText: but instead assemble the text myself, which consists of multiple words. Only if the last character is a punctuation character I will add a space now.

Finally I also added a workaround for the reported issue that if you have a hyperlink in your text and type to the right of it it would extend the hyperlink. Now typing inside the hyperlink extends it, otherwise the hyperlink attributes are removed from the typing attributes. The text color and underline style are copied from the default text attributes.

The update is available for customers via tag on the GitLab repo and via private Cocoapod.

]]>
https://www.cocoanetics.com/2013/11/dtrichtexteditor-1-6-5/feed/ 0 8854
DTCoreText 1.6.6 + DTRichTextEditor 1.6.3 https://www.cocoanetics.com/2013/08/dtcoretext-1-6-6/ https://www.cocoanetics.com/2013/08/dtcoretext-1-6-6/#comments Fri, 30 Aug 2013 14:20:55 +0000 http://www.cocoanetics.com/?p=8600 Again, another maintenance release for DTCoreText and DTRichTextEditorwhich mostly addresses issues introduced by the recent CSS handling rewrite. It also further enhances support for CSS style cascading.

DTCoreText 1.6.6

  • FIXED: Out of Memory crash on certain HTML documents extensively using CSS cascading
  • FIXED: CSS Cascading by element name performance problem
  • FIXED: Issue with font-size doubling in some situations due to CSS selector being applied
  • FIXED: Last line in a list might lose the tab stops
  • FIXED: glyph run has wrong stringRange for hyphenated lines
  • FIXED: all failing unit tests
  • ADDED: Single Selector Cascading
  • ADDED: Many unit tests for CSS Cascading
  • ADDED: Travis-CI for automated testing of pull requests
  • CHANGED: CSS selector matching now evaluates specificity

DTRichTextEditor 1.6.3

  • FIXED: Pasting from Google Drive might yield empty content
  • CHANGED: Updated DTCoreText to 1.6.6

This release’s MVP is again Amro Mousa who fixed and enhanced all that was related to CSS Cascading. Amro rewrote the matching engine and this improved parsing performance several orders of magnitude. Specifically the specificity is a very complex topic but apparently Amro has mastered that as well.

I would also like to highlight the tab stop issue. This was a great catch by Thomas Torp. This caused a funny issue for some people building for platforms which allow zeroing-weak-references. I am using DT_WEAK_VARIABLE to denote variables as weak where the deployment target permits that (>= iOS 5). Strangely there seemed to be a situation where a weak CFArrayRef would become nil and thus the array would be assigned as nil.

weak issue

On the left you see the corrected code, on the right the original. Honestly I don’t quite understand why it would do that. If you have an answer to this riddle please let me know in the comments.

The new version is tagged on GitHub as well as available via CocoaPods.

]]>
https://www.cocoanetics.com/2013/08/dtcoretext-1-6-6/feed/ 6 8600
DTCoreText 1.6.3 + DTRichTextEditor 1.6.2 https://www.cocoanetics.com/2013/08/dtcoretext-1-6-3-dtrichtexteditor-1-6-2/ https://www.cocoanetics.com/2013/08/dtcoretext-1-6-3-dtrichtexteditor-1-6-2/#comments Thu, 08 Aug 2013 16:11:42 +0000 http://www.cocoanetics.com/?p=8543 Two minor version updates are fixing issues in DTCoreText and DTRichTextEditor.

Update: If you have trouble building via CocoaPods please make sure that you have version 0.23 and also refresh your pod specs. I had to – once more – modify the spec to fix a build problem. Sorry for the inconvenience.

DTCoreText 1.6.3

  • FIXED: Some UIKit calls might be occurring on background thread in DTLazyImageView
  • FIXED: Performance problem parsing HTML that had many encoded entities
  • FIXED: Typo in DTAttributedTextView’s contentViewDidLayout
  • FIXED: DTAttributedTextCell Crash on future iOS version
  • CHANGED: CSS Attribute Parser improved to better deal with multi-value attributes
  • CHANGED: Updated DTFoundation to 1.5.1
  • CHANGED: Updated pod spec for CocoaPods 0.23

This release’s MVP is Amro Mousa for contributing the new CSS Attribute parsing.

DTRichTextEditor 1.6.2

  • FIXED: Removed unnecessary test that would prevent redrawing for “empty” contents
  • FIXED: Tapping on editor would cause incorrect scrolling on long documents if the editor was not first responder
  • CHANGED: Updated DTCoreText to 1.6.3

Both releases are tagged on their respective repositories and are also available via CocoaPods. Please note that a change in the DTCoreText pod spec requires that you updated to CocoaPods 0.23, which also was just released.

CocoaPods Update

DTCoreText builds a C-code-version of the default.css file. Before CocoaPods 0.23 this is how we did that:

spec.pre_install do |pod_representation, library_representation|
  Dir.chdir(pod_representation.root + 'Core/Source/') do
    Dir.glob('*.css') do |css_file|
      system '/usr/bin/xxd', '-i', css_file, css_file + '.c'
    end
  end
end

As of 0.23 there is no pre_install any more, instead you need to use prepare_command which runs any script or terminal command from the pod root:

spec.prepare_command = '/usr/bin/xxd -i Core/Source/default.css Core/Source/default.css.c'

Granted the previous version would compile all css files, but since there is only one in the current project, we could simplify this as shown.

Update: The above prepare command had a problem that I only saw when Russ Wetmore reported it to me. xxd uses the entire path for the symbol which caused compiling issues. So I had to fix it such:

spec.prepare_command = <<-CMD
   cd Core/Source
   /usr/bin/xxd -i default.css default.css.c
CMD

There is also change coming that will affect the way how resource bundles (used by DTLoupe) are built. But since the CocoaPods developers are still working out the edge cases I didn’t need to fix anything there for now.

Future iOS Version

There is a known crashing bug for which I have filed Radar rdar://14684188 – you see that if you activate drawing of debug frames. I have a workaround for this, but I am holding off putting it into the master branch because with this in there Apple engineers can use DTCoreText for seeing the exception occur.

One critical bug related to DTAttributedTextCell resulted from an internal change of view hierarchy. That is fixed in this release.

Apart from this there are the usual necessary adjustments to be made in the demo app for some alignment issues being the result from some changes in UIKit. But those are limited to the demo and are therefore not critical.

If somebody wants to help out and fix these for exercise then contact me by mail and I’ll specify the places where some screws need to be tightened.

Shout Outs

We like to mention apps which are using DTCoreText.

KyBook (FREE)

An extremely versatile eBook reader.

KyBook using DTCoreText KyBook using DTCoreText

]]>
https://www.cocoanetics.com/2013/08/dtcoretext-1-6-3-dtrichtexteditor-1-6-2/feed/ 8 8543
DTRichTextEditor 1.6.1 https://www.cocoanetics.com/2013/07/dtrichtexteditor-1-6-1/ https://www.cocoanetics.com/2013/07/dtrichtexteditor-1-6-1/#comments Thu, 11 Jul 2013 13:48:14 +0000 http://www.cocoanetics.com/?p=8473 This is a maintenance update for DTRichTextEditor, for the most part bringing the changes in DTCoreText 1.6.1 into the editor plus a small fix.

Changes

  • FIXED: Pasted plain text missing typing attributes
  • ADDED: DTProcessCustomHTMLAttributes in Demo App parsing options
  • CHANGED: Processing of Custom HTML Attributes is now optional and defaults to off.
  • CHANGED: Updated DTCoreText to 1.6.1

On iOS it is quite rare to have only plain text on the pasteboard. UITextView and UITextField generally add text in two formats to the pasteboard: Web Archive and Plain Text. If there is a Web Archive on the pasteboard then the editor will parse that and insert the resulting attributed string.

However if the developer added only a plain text string to the pasteboard then this would reach this rarely used branch in the paste: function. This was a problem because the editor needs to have a font attribute present for all characters of the edited attributed string. Plain text is now treated as if you entered it with the keyboard, taking on the attributes from the surrounding text.

The update is tagged in the private repo and also available via private CocoaPods spec.

]]>
https://www.cocoanetics.com/2013/07/dtrichtexteditor-1-6-1/feed/ 3 8473
DTRichTextEditor 1.6.0 https://www.cocoanetics.com/2013/07/dtrichtexteditor-1-6-0/ https://www.cocoanetics.com/2013/07/dtrichtexteditor-1-6-0/#comments Fri, 05 Jul 2013 06:56:07 +0000 http://www.cocoanetics.com/?p=8444 This update brings the new features and fixes from DTCoreText 1.6 to the editor component.

Changes

  • FIXED: Multi-stage text input had issues with input delegate messaging
  • ADDED [SPONSORED]: Support for custom HTML attributes
  • ADDED: Delegate method for finer control over pasted content.
  • ADDED: More formatting options in Demo app
  • CHANGED: Updated DTCoreText to 1.6.0

Many thanks to Lee and Daniel for contributing most of the improvements in the private component. Thanks to our generous sponsor for funding some of my efforts. It is sponsored enhancements and sales of this component that enable me to dedicate some of my time to work on DTRichTextEditor and DTCoreText.

The update is tagged on the repository and also available via private CocoaPod.

]]>
https://www.cocoanetics.com/2013/07/dtrichtexteditor-1-6-0/feed/ 3 8444
DTRichTextEditor 1.5.1 https://www.cocoanetics.com/2013/06/dtrichtexteditor-1-5-1/ https://www.cocoanetics.com/2013/06/dtrichtexteditor-1-5-1/#comments Thu, 06 Jun 2013 14:53:07 +0000 http://www.cocoanetics.com/?p=8355 This maintenance release for DTRichTextEditor fixes several crucial bugs. It is the last release before WWDC 2013.

Changes

  • FIXED: Crash on hitting enter key on empty list item right after parsing
  • FIXED: Scroll Indicator inset incorrectly
  • FIXED: Changing typing attributes inside a list would not be preserved on Enter key
  • FIXED: Pasting an image attribute now uses registered DTTextAttachment subclass for IMG tag
  • ADDED: Support for Define context menu option to show dictionary
  • CHANGED: Updated DTCoreText to 1.5.3

The update is available on the private git repo or via CocoaPods podspec. If you update via git please don’t forget to recursively update your submodules as well:

git checkout master
git pull origin master
git submodule update --recursive

This insures that you have all dependencies uptodate.

]]>
https://www.cocoanetics.com/2013/06/dtrichtexteditor-1-5-1/feed/ 3 8355
DTRichTextEditor Framework Demo Updated https://www.cocoanetics.com/2013/05/dtrichtexteditor-framework-demo-updated/ https://www.cocoanetics.com/2013/05/dtrichtexteditor-framework-demo-updated/#comments Tue, 28 May 2013 14:33:12 +0000 http://www.cocoanetics.com/?p=8228 I finally got around to updating the DTRichTextEditor time-limited Demo for Version 1.5. The new version broke a few items in the Demo because of the introduction of the text attachments class cluster.

The Demo is available on GitHub, the only other ingredient you need is a time-limited binary build of the DTRichTextEditor.framework.

Using a framework is a bit a pain because there seems to be an issue with how the individual static libraries are merged. DTRichTextEditor.framework contains some compiled code plus merged-in versions of DTCoreText, DTFoundation, DTLoupe and DTWebArchive.

Somehow during the build process the debug symbols for the i386 architecture are lost. This results in warnings like this:

Dsymutil Warning

I’ve spend several hours on this trying to figure out how to fix this warning, but I am slowly coming to the conclusion that this might be a bug in Xcode’s libtool that it loses the debug symbols for one architecture. What’s even odder is that you can still link the static library inside the framework with i386, armv7 and arm7s code. The only other method I see is to try a manual method of building a framework, but if the bug is in libtool itself then this should have the same outcome.

For now you have to either ignore the warnings or disable generation of debug symbols for the host app:

Disable Debug Symbols

If you know how how to fix that properly PLEASE let me know!

This is one of several reasons why I don’t recommend using the static framework version of DTRichTextEditor for deployment in apps. But a binary build is the only convenient way I know how to provide a demo version. All other integration variants have the source code; for obvious reasons I only want to grant access to code to people who paid for a license.

Personally I prefer to add this via git sub-module and Xcode sub-project. Integration via CocoaPods is also supported.

While I was fixing the build I also updated the demo itself to the latest version in the master branch. Daniel Phillips is working on polishing the UI for setting text formatting. I was always focussing on the editor itself and left the formatting up to the clients, but Daniel is doing a great job in building something that looks more like a serious demo.

DTRichTextEditor 1.5

The new format popover already replaces some of the test buttons on the input accessory view riding on top of the keyboard. The next major update there – which I have already seen on Daniel’s development branch also folds the paragraph and list formatting options into the format popover.

Sorry for taking so long to get it working again. I hope you enjoy the updates.

]]>
https://www.cocoanetics.com/2013/05/dtrichtexteditor-framework-demo-updated/feed/ 5 8228
Rich Text Update 1.5 https://www.cocoanetics.com/2013/05/rich-text-update-1-5/ https://www.cocoanetics.com/2013/05/rich-text-update-1-5/#comments Wed, 08 May 2013 16:22:41 +0000 http://www.cocoanetics.com/?p=8145 Today we are releasing the 1.5 version of our rich text components. This marks the second unified release where several parts of our rich text eco system are maturing in lock-step.

For the most part these improvements and enhancements were funded from exceptional sales of DTRichTextEditor as well as several sponsors who stepped forward to allow me to finally get support for lists implemented.

From what I can tell the clients who licensed the editor are way more willing to contribute funds to something they have already paid for, than for enhancing the – otherwise free with attribution – DTCoreText.

Here are the collected release notes:

DTRichTextEditor 1.5

  • ADDED: Implemented Support for Ordered and Unordered Lists, editable 1 level
  • CHANGED: Improved handling of nested lists
  • ADDED: Method to set text color for range
  • ADDED: Method to set strikethrough style for range
  • ADDED: HTMLStringWithOptions methods
  • ADDED: Ability to animate between input views (custom keyboards)
  • FIXED: style information would not obey custom CSS stylesheet in textDefaults
  • CHANGED: editing delegate now uses editorView:shouldChangeTextInRange:replacementText: for image pasting
  • ADDED: [DEMO] Formatting View Controller, shown as popover on iPad and input view on iPhone

Online Documentation

DTCoreText 1.5

  • ADDED: Methods for getting glyph path for glyph runs and lines
  • CHANGED: DTTextAttachment is now a class cluster
  • ADDED: Custom text attachments can now opt to participate in inline drawing and/or HTML output
  • FIXED: Loading of font table made asynchronously
  • FIXED: Fonts that have a synthetic slant matrix cause text to disappear
  • FIXED: Shadow:none causes text to disappear
  • FIXED: CSS Attributes were not case-sensitive
  • FIXED: Issue with setting color of HR
  • FIXED: Problems with nested list parsing and DTHTMLWriter output
  • FIXED: HTTPS URLS in web video view where treated as external URLs
  • FIXED: Bug where text attributes would “bleed” into the paragraph break

Online Documentation

DTLoupe 1.5

  • ADDED: sanity check to avoid rare NAN crash

Online Documentation

There is also now a Programming Guide for DTRichTextEditor where I’m collecting guides how to implement frequently asked about things.

I especially would like to thank Lee Hericks for his work on the backend and help with polishing, as well as Daniel Phillips who helped implement the format picker in the Editor demo. Here’s a screenshot.

DTRichTextEditor 1.5

 

Of course work has already begun on the next version. If you need something specific implemented please get in touch.

]]>
https://www.cocoanetics.com/2013/05/rich-text-update-1-5/feed/ 6 8145
Private Pods https://www.cocoanetics.com/2013/04/private-pods/ https://www.cocoanetics.com/2013/04/private-pods/#comments Thu, 18 Apr 2013 09:08:10 +0000 http://www.cocoanetics.com/?p=8020 You probably have looked at CocoaPods by now and found it to be a great way to quickly pull together all your favorite Open Source components for an app. After our recent move to Git I researched some more and found that it is exceptionally easy to also provide specs for your closed source private code.

Update: Updated Resource Bundle generation use the new syntax of CocoaPods 0.18.

CocoaPods has a number of repositories that it derives its specs from, for a default install this number is 1. But it doesn’t have to be, any other git repository can also serve spec files, as long as it obeys the standard layout. You have a folder by component and inside this you have one folder per version which contains a lonely podspec file.

Resource Bundles and Pods

Before I could get started in manufacturing spec files for my components I needed first to solve a problem. If a component requires some resources I always put them in a resource bundle target. I hate it when Open Source components have a static bundle as a workaround for CocoaPods approach of copying files. Those don’t get the proper processing they deserve, images get processed, strings files get converted into binary plists and more.

Fortunately other people are thinking the same and so I quickly got an answer on the CocoaPods Google Group, Fabio Pelosin came to my rescue and pointed me towards the spec of CoconutKit 2.0.2 which also builds a resource bundle, written by none other than famous Cédric Luthi aka @0xced. In the company of Giants…

Cedric has a bit weird structure in my opinion having a separate xcodeproj just for the resources, so my approach is a variation and simplification of his.

First you need to tell CocoaPods to preserve the xcodeproj and the resource folders because without that it deletes these and only keeps the source code files.

Then you need to build the resource bundle into the common Resources folder and add the file to the resource install script. Here is the complete spec for DTLoupe:

Pod::Spec.new do |spec|
  spec.name         = 'DTLoupe'
  spec.version      = '1.3.0'
  spec.platform     = :ios, '4.3'
  spec.license      = 'COMMERCIAL'
  spec.source       = { :git => 'git@git.cocoanetics.com:parts/dtloupe.git', :tag => spec.version.to_s }
  spec.source_files = 'Core/Source/*.{h,m}'
  spec.frameworks   = 'QuartzCore'
  spec.requires_arc = true
  spec.homepage     = 'http://www.cocoanetics.com/parts/dtloupeview/'
  spec.summary      = 'A Loupe as used for text selection.'
  spec.author       = { 'Oliver Drobnik' => 'oliver@cocoanetics.com' }
  spec.preserve_paths = 'DTLoupe.xcodeproj', 'Core/Resources'
 
def spec.post_install(target_installer)
    puts "\nGenerating DTLoupe resources bundle\n".yellow if config.verbose?
    Dir.chdir File.join(config.project_pods_root, 'DTLoupe') do
      command = "xcodebuild -project DTLoupe.xcodeproj -target 'Resource Bundle' CONFIGURATION_BUILD_DIR=../Resources"
      command << " 2>&1 > /dev/null" unless config.verbose?
      unless system(command)
        raise ::Pod::Informative, "Failed to generate DTLoupe resources bundle"
      end
    end
    if Version.new(Pod::VERSION) >= Version.new('0.16.999')
      script_path = target_installer.target_definition.copy_resources_script_name
    else
      script_path = File.join(config.project_pods_root, target_installer.target_definition.copy_resources_script_name)
    end
    File.open(script_path, 'a') do |file|
      file.puts "install_resource 'Resources/DTLoupe.bundle'"
    end
  end
end

Note the single quotes which are necessary for the target since I have a space in there.

I later found that I had version 0.16 of CocoaPods on the machine where I put together the spec. People using the latest version (presently 0.18.1) would get quite a few warnings on pod install and update. 3 problems to be exact.

The first problem was that I thought I was smart by removing the preserved folders after the install. Turns out that these are still needed even for an update.

The second problem came from target_installer.target_definition.copy_resources_script_name being deprecated, instead some people (e.g. HockeyKit) switched to target_installer.copy_resources_script_path instead.

However – problem number three – was that access to the global config singleton was deprecated as well. So each access to it causes a nasty yellow warning to appear. Eloy Durán explained to me that it was a “chicken and egg thing”. He also – wisely – suggested that I should totally drop support for older CocoaPods versions.

Bonus problem number four is that as of 0.18 there is a built in post_install hook and so there’s an occasional warning the the def of it.

People get a warning if they have an old CocoaPods version if they do anything and updating is simple with a sudo gem update cocoapods. I am a Ruby NOOB so I am thankful for Eloy helping to rewrite the spec as follows. I proceeded to removed all references to the config singleton.

Pod::Spec.new do |spec|
  spec.name         = 'DTLoupe'
  spec.version      = '1.3.0'
  spec.platform     = :ios, '4.3'
  spec.license      = 'COMMERCIAL'
  spec.source       = { :git => 'git@git.cocoanetics.com:parts/dtloupe.git', :tag => spec.version.to_s }
  spec.source_files = 'Core/Source/*.{h,m}'
  spec.frameworks   = 'QuartzCore'
  spec.requires_arc = true
  spec.homepage     = 'http://www.cocoanetics.com/parts/dtloupeview/'
  spec.summary      = 'A Loupe as used for text selection.'
  spec.author       = { 'Oliver Drobnik' => 'oliver@cocoanetics.com' }
  spec.preserve_paths = 'DTLoupe.xcodeproj', 'Core/Resources'
 
  spec.post_install do |library_representation|
    Dir.chdir File.join(library_representation.sandbox_dir, 'DTLoupe') do
      command = "xcodebuild -project DTLoupe.xcodeproj -target 'Resource Bundle' CONFIGURATION_BUILD_DIR=../Resources"
      command << " 2>&1 > /dev/null"
      unless system(command)
        raise ::Pod::Informative, "Failed to generate DTLoupe resources bundle"
      end
    end
    File.open(library_representation.copy_resources_script_path, 'a') do |file|
      file.puts "install_resource 'Resources/DTLoupe.bundle'"
    end
  end
end

In summary: use the second approach if you don’t want warnings and don’t need to support older CocoaPods versions.

Spec’ing it Out

Because DTRichTextEditor and DTLoupe are closed source that I am selling access too it would not have made any sense to put their specs into the public CocoaPods. Also it would probably fail the CI checks they have for lint-ing the specs because their Continuous Integration server would not be able to clone the source.

So I added a specs repository on our private GitLab server and made it public. The next question was if you would reference components with the SSH or HTTPS URLs. I went with SSH because there authentication works nicely by the public SSH keys the users have added to their profiles. If you use HTTP then users have to enter their credentials.

The security of SSH also makes me not worry security for my components and which is why I am showing you the above spec. Please be nice, don’t hack me bro…

Before I could put together the DTRichTextEditor Spec I needed to know the minimum versions that all dependencies would need to have to be compatible. For this I tagged and published specs for DTFoundation 1.2 and DTCoreText 1.4.1. The final step was to change around some headers in the project so that it would pass pod spec lint.

CocoaPods ignores any headers you added to your PCH file, because at the time of building the pods there IS no Precompiled Header File. At least not the one you were using for building your static library. Running the spec lint with –no-clean proved invaluable because it quickly found the places where additional #import where necessary.

DTRichTextEditor Pods

I made this graphic to show how all fits together. DTLoupe and DTRichTextEditor are on our private GitLab server. They references DTWebArchive, DTCoreText and DTFoundation as dependencies.

Version Confusion aka The Pessimistic Operator

One thing that took me a while to wrap my head around was how to properly write the version requirement. At first I was pointed towards the CocoaPods Dependency Versioning document but that didn’t help clarify. French Developer Arnaud helped me out there.

~> 1.1.7 is >= 1.1.7 && < 1.2 And ~> 1.1 is >= 1.1 && < 2.0

What confused me is that the individual digits of the version are meaning something else. The rightmost digit means equal than or higher whereas all other digits are “locked”. This process is explained in the RubyGems User Guide. They call the tilde-greater the “pessimistic version constraint”.

If you are unsure how to increment your version numbers then I recommend you read the Semantic Versioning Specification authored by Tom Preston-Werner, one of the GitHub co-founders.

Conclusion

From my own experience I can tell you that it is a great feeling to have your dear-to-your-heart component successfully build via CocoaPods because it means that you don’t have a hidden dependency that you didn’t know about.

I will now make it standard practice to spec out private and public components because the process of getting it to pass lint alone shows you some places where you might have some build issues.

And the benefit for my customers is obvious as well. They can now have 3 options to add DTRichTextEditor to their apps:

  • CocoaPods
  • Static Library via git submodule and Xcode sub-project
  • Static Universal Framework
  • Of these I personally use the second most of the time since it allows me to add code to sub-modules while working on a component. But for future apps I am tempted to switch everything to using CocoaPods.

    ]]>
    https://www.cocoanetics.com/2013/04/private-pods/feed/ 23 8020
    Rich Text Update 1.4 https://www.cocoanetics.com/2013/04/rich-text-update-1-4/ https://www.cocoanetics.com/2013/04/rich-text-update-1-4/#respond Fri, 05 Apr 2013 17:22:26 +0000 https://www.cocoanetics.com/?p=7979 Beginning with version 1.4 we will advance the version tags on DTCoreText and DTRichTextEditor in sync. DTCoreText is in charge of HTML parsing, display and HTML generation inside the editor component and thus all the changes done there are indirectly benefitting editor users as well.

    I’ve begun to aggregate issues on both GitHub and our own private GitLab instance via milestones. These are the grouping unit collecting issues so that you can tell from which version onward these fixes or enhancements are available. Each milestone will become a tag, once it is completed and will represent a stable version.

    You can always get a picture of the original issues if you filter them by milestone, like in this GitHub issue list for version 1.4.0 of DTCoreText

    DTCoreText 1.4 Changes

    • ADDED: Support for including local CSS style sheet files
    • ADDED: DTHTMLWriter can now write HTML fragments with inline styles
    • CHANGED: Changed the way color-changing hyperlinks are drawn, code now unified in DTCoreTextLayoutFrame
    • CHANGED: You no longer need an override plist, all available system fonts now get loaded into the override table automatically
    • CHANGED: renamed the define for showing performance measurement so that they don’t show in normal DEBUG mode
    • CHANGED: strike-through and underline is now properly positioned and sized
    • FIXED: Dictation Placeholder not displayed if no text delegate set
    • FIXED: Line truncation problem going for longer than the paragraph
    • FIXED: RTL justified text too short to be justified would be left-aligned instead of being right-aligned
    • FIXED: Problem parsing CSS styles containing a !important tag
    • FIXED: Using Chinese characters would cause height problems in hyperlinks
    • FIXED: Having text with a shadow would cause bolder text due to it being drawn twice
    • FIXED: Images don’t keep aspect ratio on resize
    • FIXED: Element hyperlink URL did not get copied to DTTextAttachment
    • FIXED: code removed by accident would cause problem with custom views for links
    • FIXED: HTML encoding for Emoji Characters
    • FIXED: Static Framework was not linking in code from DTFoundation
    • FIXED: Static Framework building was missing embedded DTHTMLParser

    The changes to how hyperlinks are drawn are breaking the API since before the color changing of hyperlinks that are touched was done inside DTLinkButton. But it was next to impossible to have these line up perfectly with the text. Now there is a mode on drawing (via bit mask) that allows you to draw a frame either with normal or highlighted hyperlinks.

    The second big noticeable improvement relates to underlining. UIWebViews only do a nasty 1 px underline regardless of font size. The new method gets the line thickness and position from the CTFont. This causes underlines to look like in Pages. Also a great deal of effort was spent on having the lines always perfect pixel aligned, even on Retina displays.

    DTRichTextEditor 1.4 Changes

    • ADDED: A delegation protocol that gives it feature parity with UITextView.
    • FIXED: override typing attributes (like setting bold with no selection) would be reset on a new line
    • FIXED: Autocorrection was broken due to removal of input delegate notification
    • UPDATED: DTCoreText to 1.4

    At the time of this writing this version was not finalized and bug fixing still underway. But those are just finishing touches.

    The other big and important improvement is that now the code lives on a GitLab server instead of Subversion. This unifies our workflow tremendously since we no longer have to keep copies of sub-projects inside the SVN repo. Instead everything is included as git submodules. Those are always pointing to an exact commit in the submodule. This way we have control over which version of the submodule we want to use and can advance the pointer if there is a new release without having to keep updating a full copy of the source code.

    The other big advantage for all our clients comes from everybody having their own git user accounts. This way you can easily contribute enhancements in a project branch and create a merge request for them to be included in the master branch. Previously on Subversion I only had a single read-only user for everybody.

    I am hoping that the new structure and the help of fabulous GitLab will enable a new form of social coding that we see as standard on GitHub. And that seeing other users helping out and squashing bugs will inspire a greater belief in the quality of this component as well as inspire contributing for the greater good.

    The next version will finally implement proper list support. Two people have stepped forward to fund the development of this feature. This is a somewhat involved thing since we need to implement ability to protect certain parts of the text. You don’t want the user to be able to remove individual characters of a list item prefix. This can also benefit people who want to treat hyperlinks as a single unit.

    ]]>
    https://www.cocoanetics.com/2013/04/rich-text-update-1-4/feed/ 0 7979
    DTRichTextEditor 1.2 https://www.cocoanetics.com/2013/02/dtrichtexteditor-1-2/ https://www.cocoanetics.com/2013/02/dtrichtexteditor-1-2/#comments Mon, 18 Feb 2013 16:47:59 +0000 http://www.cocoanetics.com/?p=7632 It’s been a while since I last blogged about the progress we are making on DTRichTextEditor, my rich text editor component for iOS. January saw many more licensees that ever before, people are just fed up with not being able to integrate rich text editing into their apps.

    Selling many licenses also allows me to dedicate a great deal of time to improving and tuning the component. Now here is Version 1.2.

    Inside DTRichTextEditor you get the beating heart of DTCoreText, which is responsible for parsing HTML, generating attributed strings, correctly displaying the attributed strings as well as generating HTML output for persisting the changes. Because of this I am also doing a new release version of DTCoreText. That brings this component to version 1.3.

    I won’t bore you with the lengthly change log which can be browsed online. As development progresses in the source code repository I am frequently updating this log to document them. I also recently added a Known Issues file to document current limitations of the editor.

    Rick exclaimed excitedly:

    Not only did you fix this issue, look how nice all of these languages are displayed in the editor.  Now this, my friend, is one nice editor!

    Various Languages

    The major changes revolve around improving performance, keeping pace with improvements in DTCoreText, adding Retina-support for the selection loupe and fixing a plethora of problems.

    As a goodie for other editor developers I integrated a dictation placeholder view into DTCoreText. This is used if you tap the dictation button and dictate your rich text to Siri. Of course the purple dots animate!

    Dictation Placeholder

    For developers the amount of available APIs and related documentation has increased massively. The number of helpful methods for manipulating the attributed text is ever growing. All this development is driven by the client needs who often approach me with specific requests that I try to fulfill as broadly as possible so that all users of this component benefit.

    As a general rule I am adding appledoc-style comments to all new public APIs. Also – just today – I spent an entire day polishing up the APIs and adding documentation comments to all remaining classes. Because of this the complete documentation for DTRichTextEditor can be now be browsed online or installed in your Xcode Organizer via the Atom Feed URL.

    You can purchase a license for the DTRichTextEditor in our parts store. If you have a pro bono app in mind that would benefit from this, then please inquire about

    ]]>
    https://www.cocoanetics.com/2013/02/dtrichtexteditor-1-2/feed/ 6 7632
    DTRichTextEditor 1.1 https://www.cocoanetics.com/2012/12/dtrichtexteditor-1-1/ https://www.cocoanetics.com/2012/12/dtrichtexteditor-1-1/#comments Sun, 23 Dec 2012 20:00:13 +0000 http://www.cocoanetics.com/?p=7393 Over the past week I’ve been working on enhancing DTRichTextEditor and – by extension – some of the enhancements also went into DTCoreText, which is in charge of HTML parsing, generation and display of thusly generated NSAttributedStrings. Today I present version 1.1 which brings these fine enhancements:

    Changes

    • ADDED: Support for Undo/Redo
    • ADDED: Setting and changing font family and size for ranges
    • ADDED: Support for indenting
    • CHANGED: Lots of documentation added, refactoring and cleanup
    • FIXED: text scaling bug when pasting
    • UPDATED: DTCoreText + DTFoundation submodules

    This work was sponsored by Rick Meyers who is including DTRichTextEditor in his e-Sword HD iPad app.

    e-Sword HD is a Bible study app for iPad that allows the user to make his own rich text notes on any verse in the Bible and it is stored in a database as HTML. Rick found DTRichTextEditor to be the ideal component for that, especially because contrary to UITextView it also supports iOS versions before iOS 6.

    Rick has kindly permitted me to mention him as sponsor for this work that is to the benefit of all licensees existing and future. He also sent me these screenshots which show it in action. On the first one you can see how the user would annotate a Bible verse.

    editor800

    On the main reading view these annotations can be displayed in a popover, all rich formatting being preserved.

    e-sword800

    I find that having clients sponsor enhancements for components is a win:win scenario. With this extra funding I am more easily able to set aside time for working on them. Not just financially! Having somebody who is immediately testing changes I am making and providing good feedback is invaluable and highly motivational.

    Especially so if this somebody is including the component in an app he is working on because he is able to notice API problems that I probably wouldn’t see from my theoretical point of view. Also having a live app can provide a wealth of test data in case there is a bug because having the component right under your nose is highly conducive to finding problems. While integrating the component and working around it in his app he had great bug reports for me that I could quickly reproduce and fix.

    There are many more things that I’d love to do on DTRichTextEditor and DTCoreText. Get in touch if you’d like to sponsor some. You can license the component on the Cocoanetics Parts Store.

    ]]>
    https://www.cocoanetics.com/2012/12/dtrichtexteditor-1-1/feed/ 3 7393