Skip to content

Instantly share code, notes, and snippets.

View theoknock's full-sized avatar

James Alan Bush theoknock

View GitHub Profile
@theoknock
theoknock / gist:2cb68efbf899773a274f2b7d7392f66a
Created June 7, 2021 14:06
Adding blocks with persistent arguments to an array
// This is similar to using callback blocks with three key differences:
// 1. Blocks stored in an array retain their arguments outside of the context in whicn they were created
// 2. Blocks can be called in combination or in a variance of succession
// 3. The number of blocks to be executed is known up-front
// The same effect could be achieved via regular callback blocks; however, the argument values would not be persistent
typedef int(^BlockObject)(void);
- (void)test {
@theoknock
theoknock / GlobalQueue.c
Last active June 12, 2021 09:03
Global dispatch queue (single instance) in C. Set a global queue once and use it anywhere the header file is imported.
#include "GlobalQueue.h"
dispatch_queue_t queue;
dispatch_queue_t queue_ref(void) {
if (!queue) {
queue = dispatch_queue_create_with_target("GlobalDispatchQueue", DISPATCH_QUEUE_SERIAL, dispatch_get_main_queue());
}
return queue;
@theoknock
theoknock / ViewController.m
Last active June 15, 2021 02:49
Unix-style pipe function composition block design pattern that accepts class properties as parameters without triggering a retain cycle warning from the compiler: "Block implicitly retains 'self'...").
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic) int a;
@property (nonatomic) int b;
@property (nonatomic) int c;
@property (nonatomic) int d;
@property (nonatomic) int e;
//
// ViewController.m
// TargetActionCustomPayloadsDemo
//
// Created by James Alan Bush on 9/18/21.
//
#import "ViewController.h"
@interface ViewController ()
@theoknock
theoknock / CollectionViewCoverFlowLayout.m
Created October 12, 2021 00:09
Performing a selector on objects in a copy of an autoreleasing array
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
__autoreleasing NSArray<UICollectionViewLayoutAttributes *> * collectionViewLayoutAttributes;
[self performSelector:@selector(changeLayoutAttributes:) withObject:[collectionViewLayoutAttributes = [[NSArray alloc] initWithArray:[super layoutAttributesForElementsInRect:rect] copyItems:TRUE] self]];
return (NSArray<UICollectionViewLayoutAttributes *> *)collectionViewLayoutAttributes;
}
- (void)changeLayoutAttributes:(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributes {
for (UICollectionViewLayoutAttributes * attribute in layoutAttributes) {
// change attribute code
@theoknock
theoknock / UICollectionViewFlowLayout.m
Last active October 15, 2021 19:17
Enumerating objects using enumeration block with local scope property returned by an initializer block
- (NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
__autoreleasing NSArray<UICollectionViewLayoutAttributes *> * collectionViewLayoutAttributes;
[[collectionViewLayoutAttributes = [[NSArray alloc] initWithArray:[super layoutAttributesForElementsInRect:rect] copyItems:TRUE] self] enumerateObjectsUsingBlock:^ (UICollectionViewLayoutAttributes * selected_attributes) {
return ^(UICollectionViewLayoutAttributes * _Nonnull attributes, NSUInteger idx, BOOL * _Nonnull stop) {
// Configure each attributes object in the collection individually
// based on the configuration of a single attributes object in that same collection
};
}(^ UICollectionViewLayoutAttributes * (NSArray<NSIndexPath *> * visible_index_paths) {
UICollectionViewLayoutAttributes * selectedAttributes = nil;
for (NSIndexPath * indexPath in visible_index_paths) {
@theoknock
theoknock / struct_type_default_initializer.h
Created November 4, 2021 23:16
Block Computed Property Design Pattern. Defines a type of struct and initializes an instance that passes a pointer to the instance to its block member.
typedef struct __attribute__((objc_boxable)) ArcDegreesMeasurements ArcDegreesMeasurements;
typedef NSUInteger (^(^ArcDegreesMeasurementsEnd)(void))(void);
struct __attribute__((objc_boxable)) ArcDegreesMeasurements
{
NSUInteger start;
NSUInteger length;
__unsafe_unretained ArcDegreesMeasurementsEnd end;
NSUInteger sectors;
} arcDegreesMeasurements = {
.start = 0,
@theoknock
theoknock / touch_resizing_arc.m
Last active November 10, 2021 17:21
Matching arc, ellipses or circular path to a touch location
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
^ (UITouch * touch) {
CGPoint center = CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(rect));
CGPoint tp = [touch preciseLocationInView:touch.view];
CGFloat radius = sqrt(pow(tp.x - center.x, 2.0) + pow(tp.y - center.y, 2.0));
UIBezierPath * bezier_quad_curve = [UIBezierPath bezierPathWithArcCenter:center
radius:radius
startAngle:degreesToRadians(270.0)
endAngle:degreesToRadians(180.0)
clockwise:FALSE];
@theoknock
theoknock / block_for_action_selector.m
Last active January 5, 2022 09:38
Blocks as target/action selectors for UIControlEvents (see my other gist, button_group.m, for an example implementation). Insert this code into any UIButton initializer, whether subclassing or otherwise, to add this event handler.
void (^eventHandlerBlock)(void) = ^{
printf("\nHandling event for button %lu\n", some_local_variable);
};
objc_setAssociatedObject(button, @selector(invoke), eventHandlerBlock, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[button addTarget:eventHandlerBlock action:@selector(invoke) forControlEvents:UIControlEventAllEvents];
@theoknock
theoknock / keepalive_process
Last active December 24, 2021 16:33
A keepalive script for Mac OS X apps, which takes the process name of the app as its only argument; recursively executes every one second to ensure the target app is still running (it also sets the input volume of the device to maximum)
# Continuously monitor the run state of an app
# identified by the specified name and
# launches the app if not running
while (true); do
ps_out=`ps -ef | grep $1 | grep -v 'grep' | grep -v $0`
result=$(echo $ps_out | grep "$1")
if [[ "$result" == "" ]]; then
open -a /Applications/AVS\ Server.app/
osascript -e "set volume input volume 100"