dejalcategories

DejaUIKitCategories: an open source collection of UIKit-level categories for iOS

The final batch of open source categories: DejalUIKitCategories.

DejalUIKitCategories is a collection of categories for UIKit on iOS, to add useful methods to classes like UIBarButtonItem, UIColor, UIView, and others. The categories include:

  • UIApplication+Dejal: Adds methods to get the first responder and keyboard view of the app.
  • UIBarButtonItem+Dejal: Convenience initializers to make UIBarButton instances based on and image, title, system item, custom view, spacer, or segmented control.
  • UIButton+Dejal: A more convenient title property, and a method to add a gloss effect.
  • UIColor+Dejal: Convenience initializers for more standard colors, or based on a platform-specific image or hex value.
  • UIImage+Dejal: Convenience initializers for tinted images, methods to overlay images with colors, and scaling methods.
  • UIImageView+Dejal: Make a white-background image view, and adjust the background color based on the highlighted state.
  • UILabel+Dejal: Convenience initializers for labels with various text, font, width etc attributes, and sizing methods.
  • UISegmentedControl+Dejal: Convenience initializer for a segmented control with specified items, target, action, and initial selection.
  • UITextField+Dejal: A selected range property, and support for gestures to move the insertion point by swiping.
  • UITextView+Dejal: Attributes of the selection or insertion point, and support for the insertion point swiping gestures.
  • UIView+Dejal: Properties for frame and bounds components and an image representation, methods to hide, add to and remove from the superview with animation.

You can get the code and more information from the Dejal Open Source page.

(Looking for an iOS or Mac developer? I'm available for contract or full-time work. Learn more about me.)

DejalAppKitCategories change: methods for radio buttons

Another developer post.

I recently released my DejalAppKitCategories open source project, which includes categories for OS X UI classes.

I am currently working on Time Out 2, and wanted to modernize the radio buttons in the preferences. In the AppKit release notes for OS X 10.10, Apple wrote:

Use of NSMatrix is informally deprecated. We expect to add the formal deprecation macros in a subsequent release, but its use is discouraged in the mean time. The primary use of NSMatrix is for radio button groups, so recall that for applications linked on 10.8 or later, radio buttons that share the same parent view and action will operate as a group.

Which is all well and good, but managing a radio group is annoying when using standalone buttons, so I added some methods to help.

These methods are part of my DejalAppKitCategories open source project, in the NSButton+Dejal category.

Here's the header:

@interface NSButton (DejalRadios)

@property (nonatomic, setter=dejal_setRadiosEnabled:) BOOL dejal_radiosEnabled;

- (void)dejal_selectRadioWithTag:(NSInteger)tag;
- (NSInteger)dejal_selectedRadioTag;

- (NSButton *)dejal_radioPassingTest:(BOOL (^)(NSButton *radio, BOOL *stop))predicate;
- (void)dejal_enumerateRadiosUsingBlock:(void (^)(NSButton *radio, BOOL *stop))block;

@end

And the implementation:

@implementation NSButton (DejalRadios)

/**
Assuming the receiver is a radio button, finds other radio buttons in the group (i.e. in the same superview and with the same action) and selects the one with the specified tag.  Invoke this on any of the radios in the group.  A replacement for -[NSMatrix selectCellWithTag:].

@param tag The tag value to select.

@author DJS 2015-01.
*/

- (void)dejal_selectRadioWithTag:(NSInteger)tag;
{
    [self dejal_enumerateRadiosUsingBlock:^(NSButton *radio, BOOL *stop)
     {
         radio.state = radio.tag == tag;
     }];
}

/**
Assuming the receiver is a radio button, finds other radio buttons in the group (i.e. in the same superview and with the same action) and returns the tag value of the selected radio.  Invoke this on any of the radios in the group.  A replacement for -[NSMatrix selectedTag].

@returns A tag value integer.

@author DJS 2015-01.
*/

- (NSInteger)dejal_selectedRadioTag;
{
    NSButton *foundRadio = [self dejal_radioPassingTest:^BOOL(NSButton *radio, BOOL *stop)
     {
         return radio.state;
     }];
   
    return foundRadio.tag;
}

/**
Returns YES if the radio group is enabled, or NO if not.  Simply returns the state of the receiver; the others are assumed to be the same.  (If you want to know if they are all enabled or disabled, probably best to use -dejal_enumerateRadiosUsingBlock: to scan the group, and handle a mixed case as needed.)

@author DJS 2015-01.
*/

- (BOOL)dejal_radiosEnabled;
{
    return self.enabled;
}

/**
Sets all of the radios in the group to be enabled or disabled.  A replacement for -[NSMatrix setEnabled:].

@author DJS 2015-01.
*/

- (void)dejal_setRadiosEnabled:(BOOL)enabled;
{
    [self dejal_enumerateRadiosUsingBlock:^(NSButton *radio, BOOL *stop)
     {
         radio.enabled = enabled;
     }];
}

/**
Assuming the receiver is a radio button, finds other radio buttons in the group (i.e. in the same superview and with the same action) and performs the block for each of them, passing the radio to the block.  Returns the one that returns YES, or nil if the block requests to stop before completion, or it completes without the block returning YES.  Invoke this on any of the radios in the group.

@param block A block that takes a radio button and stop boolean reference as parameters and returns a boolean.
@returns The found radio button, or nil if none is found.

@author DJS 2015-01.
*/

- (NSButton *)dejal_radioPassingTest:(BOOL (^)(NSButton *radio, BOOL *stop))predicate;
{
    for (NSButton *radio in self.superview.subviews)
    {
        // There's no reliable way to determine if a button is actually a radio button, but it's reasonable to assume that no non-radio will have the same action (and having the same action is what makes it a member of the group):
        if ([radio isKindOfClass:[NSButton class]] && radio.action == self.action && predicate)
        {
            BOOL stop = NO;
           
            if (predicate(radio, &stop))
            {
                return radio;
            }
           
            if (stop)
            {
                return nil;
            }
        }
    }
   
    return nil;
}

/**
Assuming the receiver is a radio button, finds other radio buttons in the group (i.e. in the same superview and with the same action) and performs the block for each of them, passing the radio to the block.  Invoke this on any of the radios in the group.

@param block A block that takes a radio button and stop boolean reference as parameters and returns void.

@author DJS 2015-01.
*/

- (void)dejal_enumerateRadiosUsingBlock:(void (^)(NSButton *radio, BOOL *stop))block;
{
    for (NSButton *radio in self.superview.subviews)
    {
        // There's no reliable way to determine if a button is actually a radio button, but it's reasonable to assume that no non-radio will have the same action (and having the same action is what makes it a member of the group):
        if ([radio isKindOfClass:[NSButton class]] && radio.action == self.action && block)
        {
            BOOL stop = NO;
           
            block(radio, &stop);
           
            if (stop)
            {
                return;
            }
        }
    }
}

@end

To use these methods, simply invoke on any of the radios in the group, e.g.

    [self.iconNoneRadio dejal_selectRadioWithTag:self.statusIconKind];
    self.iconNoneRadio.dejal_radiosEnabled = use;

And:

- (IBAction)chooseIcon:(id)sender;
{
    self.statusIconKind = self.iconNoneRadio.dejal_selectedRadioTag;
   
    [self maintainControls];
}

I hope this helps others! And, of course, if I'm missing anything obvious, or you have any suggestions or comments, please let me know.

This look useful? Do check out my other open source projects, too.

(Looking for an iOS or Mac developer? I'm available for contract or full-time work. Learn more about me.)

DejalAppKitExtensionCategories: an open source collection of categories to extend Foundation classes for OS X

I just released another open source collection of categories: DejalAppKitExtensionCategories.

DejalAppKitExtensionCategories is a collection of categories to extend Foundation classes with methods specific to OS X. The categories include:

  • NSAttributedString+AppKit+Dejal: Adds convenience initializers to load from a bundle resource, image URL or RTF, and to return a RTF.
  • NSDictionary+AppKit+Dejal: Extends NSDictionary and NSMutableDictionary to support NSColor values.
  • NSFileManager+AppKit+Dejal: Adds a method to determine if a path is a directory but not a package, and to move a file to the Trash.
  • NSObject+AppKit+Dejal: Extends the NSObject base class with an old-style modal did-end perform selector, and modifier key detection.
  • NSSString+AppKit+Dejal: Adds methods that depend on fonts, points and colors.
  • NSUserDefaults+AppKit+Dejal: Adds support for points, sizes and colors in NSUserDefaults.

These categories depend on the previously-published DejalFoundationCategories.

You can get the code and more information from the Dejal Open Source page.

Next up: my UIKit categories.

(Looking for an iOS or Mac developer? I'm available for contract or full-time work. Learn more about me.)

DejaAppKitCategories: an open source collection of AppKit-level categories for OS X

I just released some more open source code: DejalAppKitCategories.

DejalAppKitCategories is a collection of categories for AppKit on OS X, to add useful methods to classes like NSMenu, NSTableView, NSTextView, and others. The categories include:

  • NSButton+Dejal: A text color property and a method to display a menu.
  • NSImage+Dejal: Methods to draw flipped images, apply a badge or tint, or get a PNG representation.
  • NSMenu+Dejal: Methods to add and remove items.
  • NSOutlineView+Dejal: Methods for selected items and displaying a menu.
  • NSPopUpButton+Dejal: Methods to add and select items.
  • NSScreen+Dejal: Screen name methods.
  • NSSplitView+Dejal: Methods for split positions and collapsing and expanding.
  • NSTableView+Dejal: Selection, column and copying methods.
  • NSTextField+Dejal: Methods to set values, synchronize with a slider, and resize the window (using autoresizing).
  • NSTextView+Dejal: Properties for string, attributed string and RTF values, methods for length, range, appending, and selection.
  • NSToolbar+Dejal: Methods for the toolbar height and finding an item by identifier.
  • NSView+Dejal: Add a view as a fully-constrained subview, adjust autoresizing, scale, and set the alpha opacity.
  • NSWindow+Dejal: Methods to force editing to end, fade in a window, and adjust the sizing of the window based on a view.

You can get the code and more information from the Dejal Open Source page.

Stay tuned for more OS X and iOS open source code, coming your way over the next week or so.

(Looking for an iOS or Mac developer? I'm available for contract or full-time work. Learn more about me.)

DejalFoundationCategories: an open source collection of Foundation-level categories

Today I released two new open source projects: a tiny one, DejalUtilities, and a significantly larger one, DejalFoundationCategories.

DejalFoundationCategories is a collection of Foundation-level categories, to add useful methods to classes like NSArray, NSDictionary, NSString, and others. They work on both OS X and iOS, and include:

  • NSArray+Dejal: 30+ methods extending NSArray and NSMutableArray, including object matching, reversal, sorting, deep copying, adding and removing.
  • NSAttributedString+Dejal: 10+ methods extending NSAttributedString and NSMutableAttributedString, including convenience initializers, RTF and font methods.
  • NSData+Dejal: A couple of methods to make archiving and unarchiving objects slightly more convenient.
  • NSDate+Dejal: 50+ methods extending NSDate, including convenience initializers, handy date component properties and calculators, JSON date support, string formatting, and relative date output.
  • NSDictionary+Dejal: 25+ methods extending NSDictionary and NSMutableDictionary, including object matching, scalar support, deep copying, and more.
  • NSFileManager+Dejal: 15+ methods extending NSFileManager, including convenient file attributes, file renaming, and path building.
  • NSObject+Dejal: 15+ methods extending the NSObject base class, including key-value conveniences, “equivalent” comparisons, and performSelector methods.
  • NSString+Dejal: 80+ methods extending NSString and NSMutableString, including scalar value formatting, contains evaluation, comparisons, substring and range utilities, reformatting, checksum and encoding utilities, internet utilities, file path methods, and appending and replacing methods.
  • NSUserDefaults+Dejal: 15+ methods extending NSUserDefaults, including support for default values, sanitizing values, time intervals, factory settings, and copying preferences.

DejalUtilities is a single header file with some useful #define macros and static functions, also for both OS X and iOS:

  • Adds DejalClassAvailable() and DejalClassSelectorAvailable() macros, to help determine available APIs.
  • Adds DejalIntervalFromMinutes(), DejalIntervalFromDays(), DejalMinutesFromInterval(), DejalMonthsFromInterval(), and similar macros, to convert seconds to and from other units.
  • Adds DEJAL_FILE_NAME and DEJAL_COMPILE_DATE_TIME macros, to help with debug information.
  • Adds a DejalWeakSelf macro to easily make a weak representation of self for use with blocks.
  • Plus several other handy macros and inline functions.

You can get the code and more information from the Dejal Open Source page.

(Looking for an iOS or Mac developer? I'm available for contract or full-time work. Learn more about me.)

Syndicate content