Adding Force Touch Features to macOS Apps with a Custom Gesture Recognizer [Open Source]

I created a simple subclass of NSGestureRecognizer, ATForceTouchGesture, to simplify the process of adding Force Touch features to macOS apps. You can use this gesture recognizer to add a feature like force clicking to start editing a label (see the screenshot below).

Image captures 'force click' to edit using ATForceTouchGesture.

There is a sample project available on Github here.

Exporting NSTableView to HTML [Open Source]

I needed to export the contents of a NSTableView to HTML, so I wrote a little NSTableView subclass in Objective-C to do this.

ATHyperTextTableView is a simple NSTableView subclass that makes exporting a table view to HTML easy. You can customize the look of the exported HTML table with your own CSS too.

Screenshots Below:
Screenshot of NSTableView.
Screenshot of exported HTML from a the tableView, loaded into a WebView.
Screenshot of the exported HTML loaded into a WebView.

Screenshot of exported HTML from a the tableView, loaded into a WebView with custom CSS set.
Screenshot of the exported HTML loaded into a WebView, styled with custom CSS.

There is a sample project available on Github here.

How to Disable NSScrollView Scrolling

Unlike UIScrollView on iOS, NSScrollView on Mac does not have a handy scrollEnabled property for you to set to NO if you need to temporarily disable scrolling in your app.

If you Google around, you can find several posts on websites like stackoverflow that ask questions like How can I disable the vertical scrolling of a NSScrollView? Some have suggested setting the hasVerticalScroller property to NO as the answer. However, the hasVerticalScroller property only effects the visibility of the scroller, a value of NO does not actually prevent scrolling.

There are also ways to constrain scrolling from an NSView subclass, as described in Apple’s documentation here. Constraining scrolling from a view subclass can be useful, but what if you want to just temporarily disable scrolling?

The easiest way to disable scrolling it seems is to subclass NSScrollView and add a BOOL property with a name like scrollingEnabled. Then you can simply override the designated initializers (initWithFrame: and initWithCoder:) and set the ivar of the property to YES as the default value:

   self = [super initWithFrame:frameRect]; 
   if (self) 
       [self setUpOnInit]; 
   return self; 
- (instancetype)initWithCoder:(NSCoder *)coder 
    self = [super initWithCoder:coder]; 
    if (self) 
         [self setUpOnInit]; 
    return self; 
   //Set all default values. 
   _scrollingEnabled = YES; 

Now you can just override the scrollWheel: method and check the property:

-(void)scrollWheel:(NSEvent *)theEvent 
    if (self.scrollingEnabled) {  
      [super scrollWheel:theEvent];  
    else {  
       //scrolling is disabled. 

This technique will work in most cases, but there may be times when a view inside of a scroll view implements autoscrolling behavior (perhaps if the view is a dragging destination). If you need to temporarily disable scrolling in such a case, you may want to subclass NSClipView and block scrolling from the appropriate methods there. It would probably be better if Apple just added a scrollingEnabled property on NSScrollView.

Visual Attributed String: An Essential Tool for iOS and Mac Developers Released on the Mac App Store!


Visual Attributed String has been released on the Mac App Store! Visual Attributed String is the most advanced WYSIWYG (what you see is what you get) editor for attributed strings, providing rich features including:

-Platform Specific Code: generate code to create NSAttributedStrings for both iOS and OS X.
-Generates both Swift AND Objective-C code!
-Get the code for your entire document by clicking “Code” in the toolbar!
-Get the code for only selected portions of text by right-clicking and selecting the “Code for Selection” menu item! This allows you to get code for individual words/paragraphs as you need them on a long document with many different text styles!
-Save your text as an image to use for the web! You can also generate images for only selected portions of text by right-clicking and selecting the “Image for Selection” menu item! Supported image formats include: .png, .bmp, .tiff, and .jpeg!
-Smart Code Generation: Visual Attributed String is smart enough to generate code for non-mutable attributed strings (NSAttributedString) and mutable attributed strings (NSMutableAttributedString) based on your typed text!
-Easily add emoji and special characters to your attributed strings by clicking the “Special Characters” toolbar item to bring up the characters palette!
-Change the background of the entire document to see how your text looks against different background colors. If you want to get the code for your document’s background color, you can simply right click and select the “Background Color Code” menu item!
-Add images to your attributed strings! Just drag and drop an image from Finder onto the window to add images to the document! Did you know NSAttributedString is capable of displaying images?
-Custom Font Warning: Visual Attributed String will warn you if your document uses a custom font that is not included in the iOS SDK!
-Visual Attributed String is a document-based application and supports features such as autosaving, duplicating documents, renaming documents, and reverting document versions!
-Powerful yet simple interface for styling text! Visual Attributed String provides an interface for editing many attributes including:
       ∙Font (NSFontAttributeName)
       ∙Font Color (NSForegroundColorAttributeName)
       ∙Font Background Color (NSBackgroundColorAttributeName)
       ∙Kern (NSKernAttributeName)
       ∙Skew (NSObliquenessAttributeName)
       ∙Shadow (NSShadowAttributeName)
       ∙Underline (NSUnderlineStyleAttributeName)
       ∙Underline Color (NSUnderlineColorAttributeName)
       ∙Strikethrough (NSStrikethroughStyleAttributeName)
       ∙Strikethrough Color (NSStrikethroughColorAttributeName)
       ∙Link (NSLinkAttributeName)
       ∙Stroke (NSStrokeWidthAttributeName)
       ∙Stroke Color (NSStrokeColorAttributeName)
       ∙Paragraph Style (NSParagraphStyleAttributeName)
       ∙Tool Tip (NSToolTipAttributeName)
       ∙Attaching Images (NSAttachmentAttributeName)

For more information on Visual Attributed String you can go to the Mac App Store or the official Visual Attributed String website.


Visual Attributed String Mac app screenshot of document window showing some editable attributes. Visual Attributed String Mac app screenshot showing mocked up iOS application user interface. Visual Attributed String Mac screenshot showing generated code for a document in Swift. Visual Attributed String Mac app screenshot showing code for selection popover in document. Visual Attributed String Mac App screenshot showing Emoji characters in document.

How to Deprecate your Own API in Objective-C

To mark some of your own API as deprecated in Objective-C, you simply can add the following attribute to your method declaration (as seen in the snippet below):

-(void)myOldMethod __attribute((deprecated("Use the myNewMethod instead.")));

Now when you call myOldMethod in your code, the compiler will warn you that: “myOldMethod is deprecated. Use the myNewMethod instead”. You can also add the deprecated attribute to property declarations.

But what if you wanted to be more specific? For instance, if there is a better way to handle something in the iOS 8 SDK, you can mark an old method as deprecated only for projects that have iOS 8.0 or later as the deployment target.

-(void)myOldMethod NS_DEPRECATED_IOS(3_0, 8_0,"Use myNewMethod instead.");

Using the code snippet above, if you call myOldMethod the compiler will only warn you that the method is deprecated if your project’s deployment target is set to iOS 8 or later.

Deprecating your own methods can come in handy especially if you have written your own framework that is used across multiple projects. You may choose to deprecate some of your own API rather than removing the methods entirely until you get around to adapting your existing projects to use your new API.