Instantly share code, notes, and snippets.
Last active
April 19, 2022 21:09
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save theoknock/cf6d8fbb1483128de0532a322cacdaaa to your computer and use it in GitHub Desktop.
Thread-safe NSObject array iteration/enumeration
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <objc/runtime.h> | |
static __strong id _Nonnull buttons[5]; | |
static __strong const id * _Nonnull (*buttons_t)[5] = &buttons; | |
static void (^(^map)(id * _Nonnull, const unsigned long))(const void *(^__strong)(const unsigned long)) = ^ (id * _Nonnull obj_collection, const unsigned long index_count) { | |
__block unsigned long (^recursive_block)(unsigned long); | |
return ^ (const void * (^enumeration)(const unsigned long)) { | |
(recursive_block = ^ unsigned long (unsigned long counter) { | |
obj_collection[counter] = (__bridge id)((__bridge const void * _Nonnull)CFBridgingRelease(enumeration(counter))); | |
return (unsigned long)((counter += 1) ^ index_count) && (unsigned long)(recursive_block)(counter); | |
})(0ul); | |
}; | |
}; | |
/* | |
Older versions (non-recursive) below | |
*/ | |
static __strong UIButton * _Nonnull buttons[5]; | |
static void (^(^populate_collection)(__strong UIButton * _Nonnull [_Nonnull 5]))(UIButton * (^__strong)(unsigned int)) = ^ (__strong UIButton * _Nonnull button_collection[5]) { | |
dispatch_queue_t enumerator_queue = dispatch_queue_create("enumerator_queue", DISPATCH_QUEUE_SERIAL); | |
return ^ (UIButton *(^enumeration)(unsigned int)) { | |
dispatch_apply(5, enumerator_queue, ^(size_t index) { | |
dispatch_barrier_async(dispatch_get_main_queue(), ^{ | |
button_collection[index] = enumeration((unsigned int)index); | |
}); | |
}); | |
}; | |
}; | |
static void (^(^enumerate_collection)(__strong UIButton * _Nonnull [_Nonnull 5]))(void (^__strong)(UIButton * _Nonnull, unsigned int)) = ^ (__strong UIButton * _Nonnull button_collection[5]) { | |
dispatch_queue_t enumerator_queue = dispatch_queue_create("enumerator_queue", DISPATCH_QUEUE_SERIAL); | |
return ^ (void(^enumeration)(UIButton * _Nonnull, unsigned int)) { | |
dispatch_barrier_async(dispatch_get_main_queue(), ^{ | |
dispatch_apply(5, enumerator_queue, ^(size_t index) { | |
for (int index = 0; index < 5; index++) | |
dispatch_barrier_async(dispatch_get_main_queue(), ^{ | |
enumeration(button_collection[index], (unsigned int)index); // no return value | |
}); | |
}); | |
}); | |
}; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
map(&buttons, 5)(^ const void * (const unsigned long index) { | |
printf("map button %lu\n", index); | |
__block UIButton * button; | |
[button = [UIButton new] setTag:index]; | |
[button setImage:[UIImage systemImageNamed:CaptureDeviceConfigurationControlPropertyImageValues[0][index] withConfiguration:CaptureDeviceConfigurationControlPropertySymbolImageConfiguration(CaptureDeviceConfigurationControlStateDeselected)] forState:UIControlStateNormal]; | |
[button setImage:[UIImage systemImageNamed:CaptureDeviceConfigurationControlPropertyImageValues[1][index] withConfiguration:CaptureDeviceConfigurationControlPropertySymbolImageConfiguration(CaptureDeviceConfigurationControlStateSelected)] forState:UIControlStateSelected]; | |
[button setImage:[UIImage systemImageNamed:CaptureDeviceConfigurationControlPropertyImageValues[1][index] withConfiguration:CaptureDeviceConfigurationControlPropertySymbolImageConfiguration(CaptureDeviceConfigurationControlStateHighlighted)] forState:UIControlStateHighlighted]; | |
NSMutableParagraphStyle *centerAlignedParagraphStyle = [[NSMutableParagraphStyle alloc] init]; | |
centerAlignedParagraphStyle.alignment = NSTextAlignmentCenter; | |
NSDictionary *centerAlignedTextAttributes = @{NSForegroundColorAttributeName:[UIColor systemYellowColor], | |
NSFontAttributeName:[UIFont systemFontOfSize:14.0], | |
NSParagraphStyleAttributeName:centerAlignedParagraphStyle}; | |
NSString *valueString = [NSString stringWithFormat:@"%.2f", 0.00]; | |
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:valueString attributes:centerAlignedTextAttributes]; | |
[button setAttributedTitle:attributedString forState:UIControlStateNormal]; | |
[button.titleLabel setFrame:UIScreen.mainScreen.bounds]; | |
[button sizeToFit]; | |
float angle = rescale(index, 0.0, 4.0, 180.0, 270.0); | |
NSNumber * button_angle = [NSNumber numberWithFloat:angle]; | |
objc_setAssociatedObject (button, | |
(void *)index, | |
button_angle, | |
OBJC_ASSOCIATION_RETAIN); | |
[button setUserInteractionEnabled:FALSE]; | |
void (^eventHandlerBlockTouchUpInside)(void) = ^{ | |
NSNumber * associatedObject = (NSNumber *)objc_getAssociatedObject (button, (void *)index); | |
// printf("%s\n", [[associatedObject stringValue] UTF8String]); | |
}; | |
objc_setAssociatedObject(button, @selector(invoke), eventHandlerBlockTouchUpInside, OBJC_ASSOCIATION_RETAIN_NONATOMIC); | |
[button addTarget:eventHandlerBlockTouchUpInside action:@selector(invoke) forControlEvents:UIControlEventTouchUpInside]; | |
CGPoint target_center = point_from_angle(angle); | |
[button setCenter:target_center]; | |
[self addSubview:button]; | |
return (const id *)CFBridgingRetain(button); | |
}); | |
/* | |
Older versions (non-recursive) below | |
*/ | |
populate_collection(buttons)(^ UIButton * (unsigned int index) { | |
UIButton * button; | |
[button = [UIButton new] setTag:index]; | |
[button setImage:[UIImage systemImageNamed:@"questionmark.circle" withConfiguration:[[UIImageSymbolConfiguration configurationWithPointSize:42] configurationByApplyingConfiguration:[UIImageSymbolConfiguration configurationPreferringMulticolor]]] forState:UIControlStateNormal]; | |
[button sizeToFit]; | |
void (^eventHandlerBlock)(void) = ^{ }; | |
objc_setAssociatedObject(button, @selector(invoke), eventHandlerBlock, OBJC_ASSOCIATION_RETAIN_NONATOMIC); | |
[button addTarget:eventHandlerBlock action:@selector(invoke) forControlEvents:UIControlEventTouchUpInside]; | |
[self.view addSubview:button]; | |
float angle = 270.0 - ((90.0 / 4.0) * button.tag); | |
[button setCenter:[[UIBezierPath bezierPathWithArcCenter:CGPointMake(CGRectGetMaxX(self.view.bounds), CGRectGetMaxY(self.view.bounds)) radius:CGRectGetMidX(self.view.bounds) startAngle:degreesToRadians(angle) endAngle:degreesToRadians(angle) clockwise:FALSE] currentPoint]]; | |
return button; | |
}); | |
enumerate_collection(buttons)(^ (UIButton * _Nonnull button, unsigned int property) { | |
float angle = 270.0 - ((90.0 / 4.0) * button.tag); | |
[button setCenter:[[UIBezierPath bezierPathWithArcCenter:CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds)) radius:CGRectGetMidX(self.view.bounds) startAngle:degreesToRadians(angle) endAngle:degreesToRadians(angle) clockwise:FALSE] currentPoint]]; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment