Skip to content

Instantly share code, notes, and snippets.

@loganmoseley
Forked from cdzombak/CDZIdioms.h
Last active May 18, 2017 15:53
Show Gist options
  • Save loganmoseley/3373d094e9426af0febf168d31b7b83e to your computer and use it in GitHub Desktop.
Save loganmoseley/3373d094e9426af0febf168d31b7b83e to your computer and use it in GitHub Desktop.
//
// CDZIdioms.h
// https://www.dzombak.com/blog/2015/02/Tiny-Swift-idioms-in-ObjC.html
//
// Created by Chris Dzombak on 3/21/15.
// Copyright (c) 2015 Chris Dzombak. All rights reserved.
//
#ifndef CDZIdioms_h
#define CDZIdioms_h
// assigns LHS = RHS iff RHS is non-nil and the right "kind" of class
#define if_let(CLASS, LHS, RHS) \
for (id obj_ = as_option(RHS, CLASS); obj_ != nil;) \
for (CLASS *const _Nonnull LHS = obj_; obj_ != nil; obj_ = nil)
// Treat this like a Swift guard: return from ELSE.
#define guard_let_else(CLASS, LHS, RHS, ELSE) \
{ \
let(CLASS) maybeRHS = as_option(RHS, CLASS); \
for (BOOL cont = YES; cont; cont = NO) { \
for (id ignoreMe = maybeRHS; cont && maybeRHS == nil; cont = NO) { \
(void)ignoreMe; \
ELSE \
} \
} \
} \
CLASS *const _Nonnull LHS = (CLASS *)(RHS);
#define as_checked(EXPR, KLASS) ({ id _obj = EXPR; NSCAssert([_obj isKindOfClass:[KLASS class]], @"Cannot cast %@ to %@", NSStringFromClass([_obj class]), NSStringFromClass([KLASS class])); _obj; })
#define as_option(EXPR, KLASS) ({ id _obj = EXPR; if (![_obj isKindOfClass:[KLASS class]]) _obj = nil; _obj; })
#define lazy_get(TYPE, NAME, VALUE) \
@synthesize NAME = _##NAME; \
- (TYPE)NAME { if (!_##NAME) _##NAME = (VALUE); return _##NAME; }
// FINAL added 2016-01-08; see:
// https://twitter.com/jesse_squires/status/664588682997964800
// https://twitter.com/cdzombak/status/685475439804977152
#define FINAL __attribute__((objc_subclassing_restricted))
// let added 2016-02-24; see:
// https://twitter.com/smileyborg/status/702377742617190400
#define let const
// nob_defer added 2016-01-09; see: http://nshipster.com/new-years-2016/
// some helper declarations
#define _nob_macro_concat(a, b) a##b
#define nob_macro_concat(a, b) _nob_macro_concat(a, b)
typedef void(^nob_defer_block_t)();
NS_INLINE void nob_deferFunc(__strong nob_defer_block_t *blockRef)
{
nob_defer_block_t actualBlock = *blockRef;
actualBlock();
}
// the core macro:
#define nob_defer(deferBlock) \
__strong nob_defer_block_t nob_macro_concat(__nob_stack_defer_block_, __LINE__) __attribute__((cleanup(nob_deferFunc), unused)) = deferBlock
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment