Skip to content

Commit

Permalink
Convert UIAlertAction swizzling to better, more Swift-dependent method
Browse files Browse the repository at this point in the history
[#142848761]
  • Loading branch information
jwfriese committed Apr 4, 2017
1 parent 144ddc3 commit 00a1120
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 65 deletions.
8 changes: 4 additions & 4 deletions Fleet.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@
7BB14A701D77B425002ABE82 /* Screen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB14A6D1D77B425002ABE82 /* Screen.swift */; };
7BB14A711D77B425002ABE82 /* FLTScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB14A6E1D77B425002ABE82 /* FLTScreen.swift */; };
7BDB63B31E47725600515C22 /* FleetError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDB63B21E47725600515C22 /* FleetError.swift */; };
7BDF61EA1E935B4600990588 /* UIAlertAction+Fleet.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BDF61E71E935B4600990588 /* UIAlertAction+Fleet.h */; settings = {ATTRIBUTES = (Public, ); }; };
7BDF61EB1E935B4600990588 /* UIAlertAction+Fleet.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BDF61E81E935B4600990588 /* UIAlertAction+Fleet.m */; };
7BDF61EC1E935B4600990588 /* UIAlertController+Fleet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDF61E91E935B4600990588 /* UIAlertController+Fleet.swift */; };
7BDF61F01E935B7500990588 /* UIAlertAction+FleetSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDF61EE1E935B7500990588 /* UIAlertAction+FleetSpec.swift */; };
Expand All @@ -67,6 +66,7 @@
7BDF61FA1E93685800990588 /* FleetSwizzle.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BDF61F91E93685800990588 /* FleetSwizzle.m */; };
7BDF61FC1E93691200990588 /* UITableViewRowAction+Fleet.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BDF61FB1E93691200990588 /* UITableViewRowAction+Fleet.m */; };
7BDF61FE1E936A3200990588 /* UIStoryboard+Fleet.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BDF61FD1E936A3200990588 /* UIStoryboard+Fleet.m */; };
7BDF62001E936BFB00990588 /* UIAlertAction+Fleet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDF61FF1E936BFB00990588 /* UIAlertAction+Fleet.swift */; };
7BEE35B51E15434A00302991 /* UITableView+SelectRowMinimalDelegateImplSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BEE35B41E15434A00302991 /* UITableView+SelectRowMinimalDelegateImplSpec.swift */; };
7BF913981E384A4E00019CF2 /* TableViewError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BF913971E384A4E00019CF2 /* TableViewError.swift */; };
7BF913AE1E3A4BA800019CF2 /* UIViewController+Fleet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BF913AD1E3A4BA800019CF2 /* UIViewController+Fleet.swift */; };
Expand Down Expand Up @@ -164,7 +164,6 @@
7BB14A6D1D77B425002ABE82 /* Screen.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Screen.swift; sourceTree = "<group>"; };
7BB14A6E1D77B425002ABE82 /* FLTScreen.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FLTScreen.swift; sourceTree = "<group>"; };
7BDB63B21E47725600515C22 /* FleetError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FleetError.swift; sourceTree = "<group>"; };
7BDF61E71E935B4600990588 /* UIAlertAction+Fleet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIAlertAction+Fleet.h"; sourceTree = "<group>"; };
7BDF61E81E935B4600990588 /* UIAlertAction+Fleet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIAlertAction+Fleet.m"; sourceTree = "<group>"; };
7BDF61E91E935B4600990588 /* UIAlertController+Fleet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIAlertController+Fleet.swift"; sourceTree = "<group>"; };
7BDF61EE1E935B7500990588 /* UIAlertAction+FleetSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIAlertAction+FleetSpec.swift"; sourceTree = "<group>"; };
Expand All @@ -175,6 +174,7 @@
7BDF61F91E93685800990588 /* FleetSwizzle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FleetSwizzle.m; sourceTree = "<group>"; };
7BDF61FB1E93691200990588 /* UITableViewRowAction+Fleet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UITableViewRowAction+Fleet.m"; sourceTree = "<group>"; };
7BDF61FD1E936A3200990588 /* UIStoryboard+Fleet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIStoryboard+Fleet.m"; sourceTree = "<group>"; };
7BDF61FF1E936BFB00990588 /* UIAlertAction+Fleet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIAlertAction+Fleet.swift"; sourceTree = "<group>"; };
7BEE35B41E15434A00302991 /* UITableView+SelectRowMinimalDelegateImplSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UITableView+SelectRowMinimalDelegateImplSpec.swift"; sourceTree = "<group>"; };
7BF913971E384A4E00019CF2 /* TableViewError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewError.swift; sourceTree = "<group>"; };
7BF913AD1E3A4BA800019CF2 /* UIViewController+Fleet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+Fleet.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -508,8 +508,8 @@
7BDF61E61E935B0E00990588 /* Alerts */ = {
isa = PBXGroup;
children = (
7BDF61E71E935B4600990588 /* UIAlertAction+Fleet.h */,
7BDF61E81E935B4600990588 /* UIAlertAction+Fleet.m */,
7BDF61FF1E936BFB00990588 /* UIAlertAction+Fleet.swift */,
7BDF61E91E935B4600990588 /* UIAlertController+Fleet.swift */,
);
path = Alerts;
Expand Down Expand Up @@ -593,7 +593,6 @@
files = (
7BA90AB71CC130990040B031 /* Fleet.h in Headers */,
7B8F2B3B1DE2592C00B6F4C2 /* FleetObjC.h in Headers */,
7BDF61EA1E935B4600990588 /* UIAlertAction+Fleet.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -789,6 +788,7 @@
7BB14A711D77B425002ABE82 /* FLTScreen.swift in Sources */,
7B675E941D0DA7EA002E6B45 /* Fleet.swift in Sources */,
7B9458101D4D7DFA00F16A64 /* StoryboardDeserializer.swift in Sources */,
7BDF62001E936BFB00990588 /* UIAlertAction+Fleet.swift in Sources */,
7BDF61EB1E935B4600990588 /* UIAlertAction+Fleet.m in Sources */,
7B8F2B3C1DE2592C00B6F4C2 /* FleetObjC.m in Sources */,
7BFABD5C1E3DA2CD002823B3 /* UIButton+Fleet.swift in Sources */,
Expand Down
7 changes: 0 additions & 7 deletions Fleet/CoreExtensions/Alerts/UIAlertAction+Fleet.h

This file was deleted.

58 changes: 5 additions & 53 deletions Fleet/CoreExtensions/Alerts/UIAlertAction+Fleet.m
Original file line number Diff line number Diff line change
@@ -1,69 +1,21 @@
#import "UIAlertAction+Fleet.h"
#import <objc/runtime.h>

@interface ObjectifiedBlock : NSObject

@property (nonatomic, copy) void (^block)(UIAlertAction *);

- (instancetype)initWithBlock:(void (^)(UIAlertAction *))block;

@end

@implementation ObjectifiedBlock

- (instancetype)initWithBlock:(void (^)(UIAlertAction *))block {
if (self == [super init]) {
self.block = block;
}

return self;
}

@end
#import <UIKit/UIKit.h>
#import "FleetSwizzle.h"

BOOL didSwizzleUIAlertAction = NO;
unsigned int handlerAssociatedKey = 0;

@interface UIAlertAction (FleetPrivate)

@property (nonatomic, copy) void (^fleet_property_handler)(UIAlertAction *);

@end

@implementation UIAlertAction (FleetPrivate)

+ (void)initialize {
if (self == [UIAlertAction class]) {
if (!didSwizzleUIAlertAction) {
[self swizzleHandlerSettler];
[self objc_swizzleHandlerSetter];
didSwizzleUIAlertAction = YES;
}
}
}

+ (void)swizzleHandlerSettler {
SEL originalSelector = NSSelectorFromString(@"setHandler:");
SEL swizzledSelector = @selector(fleet_setHandler:);

Method originalMethod = class_getInstanceMethod(self, originalSelector);
Method swizzledMethod = class_getInstanceMethod(self, swizzledSelector);

method_exchangeImplementations(originalMethod, swizzledMethod);
}

- (void)fleet_setHandler:(void (^)(UIAlertAction *))handler {
self.fleet_property_handler = handler;
[self fleet_setHandler: handler];
}

- (void (^)(UIAlertAction *))fleet_property_handler {
ObjectifiedBlock *block = objc_getAssociatedObject(self, &handlerAssociatedKey);
return [block block];
}

- (void)setFleet_property_handler:(void (^)(UIAlertAction *))fleet_property_handler {
ObjectifiedBlock *block = [[ObjectifiedBlock alloc] initWithBlock: fleet_property_handler];
objc_setAssociatedObject(self, &handlerAssociatedKey, block, OBJC_ASSOCIATION_RETAIN);
+ (void)objc_swizzleHandlerSetter {
memorySafeExecuteSelector(self, NSSelectorFromString(@"swizzleHandlerSetter"));
}

@end
47 changes: 47 additions & 0 deletions Fleet/CoreExtensions/Alerts/UIAlertAction+Fleet.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import UIKit
import ObjectiveC

private var handlerAssociatedKey: UInt = 0

@objc private class ObjectifiedBlock: NSObject {
var block: ((UIAlertAction) -> Void)?

init(block: ((UIAlertAction) -> Void)?) {
self.block = block
}
}

extension UIAlertAction {
var handler: ((UIAlertAction) -> Void)? {
get {
return fleet_property_handler
}
}

@objc class func swizzleHandlerSetter() {
let originalSelector = Selector(("setHandler:"))
let swizzledSelector = #selector(UIAlertAction.fleet_setHandler(_:))

let originalMethod = class_getInstanceMethod(self, originalSelector)
let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)

method_exchangeImplementations(originalMethod, swizzledMethod)
}

func fleet_setHandler(_ handler: ((UIAlertAction) -> Void)?) {
fleet_property_handler = handler
fleet_setHandler(handler)
}

fileprivate var fleet_property_handler: ((UIAlertAction) -> Void)? {
get {
let block = objc_getAssociatedObject(self, &handlerAssociatedKey) as? ObjectifiedBlock
return block?.block
}

set {
let block = ObjectifiedBlock(block: newValue)
objc_setAssociatedObject(self, &handlerAssociatedKey, block, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}
}
}
1 change: 0 additions & 1 deletion Fleet/Fleet.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#import <UIKit/UIKit.h>
#import "FleetObjC.h"
#import "UIAlertAction+Fleet.h"

FOUNDATION_EXPORT double FleetVersionNumber;
FOUNDATION_EXPORT const unsigned char FleetVersionString[];

0 comments on commit 00a1120

Please sign in to comment.