From e78d9e5a53946eb59bd4805b10e06c67e55aced1 Mon Sep 17 00:00:00 2001 From: Oleksa 'trimm' Korin Date: Tue, 7 Feb 2017 20:54:10 +0200 Subject: [PATCH 1/7] ObjectiveClass -> refactored and removed duplication --- ObjectiveKit/ObjectiveClass.swift | 99 ++++++++++++++----------------- 1 file changed, 44 insertions(+), 55 deletions(-) diff --git a/ObjectiveKit/ObjectiveClass.swift b/ObjectiveKit/ObjectiveClass.swift index a9cd787..2cf2236 100644 --- a/ObjectiveKit/ObjectiveClass.swift +++ b/ObjectiveKit/ObjectiveClass.swift @@ -10,6 +10,14 @@ import Foundation typealias ImplementationBlock = @convention(block) () -> Void +fileprivate func toStringDecorator(_ f: @escaping (T!) -> UnsafePointer!) -> (T!) -> String? { + return { + let name = f($0) + + return name.map { String(cString: $0) } + } +} + /// An object that allows you to introspect and modify classes through the ObjC runtime. public class ObjectiveClass : ObjectiveKitRuntimeModification { @@ -28,20 +36,10 @@ public class ObjectiveClass : ObjectiveKitRuntimeModification { /// /// - Returns: An array of instance variables. public var ivars: [String] { - get { - var count: CUnsignedInt = 0 - var ivars = [String]() - let ivarList = class_copyIvarList(internalClass, &count) - for i in (0..: ObjectiveKitRuntimeModification { /// /// - Returns: An array of selectors. public var selectors: [Selector] { - get { - var count: CUnsignedInt = 0 - var selectors = [Selector]() - let methodList = class_copyMethodList(internalClass, &count) - for i in (0.. UnsafeMutablePointer! in + let raw = UnsafeRawPointer(class_copyProtocolList(cls, count)) + let unsafeProtocols = raw?.assumingMemoryBound(to: (Protocol?).self) + + return UnsafeMutablePointer(mutating: unsafeProtocols) + }, + transform: toStringDecorator(protocol_getName)) } /// Get all properties implemented by the class. /// /// - Returns: An array of property names. public var properties: [String] { - get { - var count: CUnsignedInt = 0 - var properties = [String]() - let propertyList = class_copyPropertyList(internalClass, &count) - for i in (0..( + with copyingGetter:(AnyClass?, UnsafeMutablePointer?) -> UnsafeMutablePointer!, + transform: (Type) -> Result? + ) -> [Result] + { + var cCount: CUnsignedInt = 0 + + let entities = copyingGetter(self.internalClass, &cCount) + let count = Int(exactly: cCount) ?? 0 + + defer { entities?.deallocate(capacity: count) } + + return UnsafeMutableBufferPointer(start: entities, count: count).flatMap { $0 } + .flatMap(transform) } - } From bdcf49fc491cd3a728f21273321071c2b3859c2c Mon Sep 17 00:00:00 2001 From: Oleksa 'trimm' Korin Date: Tue, 7 Feb 2017 20:55:33 +0200 Subject: [PATCH 2/7] ObjectiveClass -> added additional method for fetching String from runtime for better deduplication --- ObjectiveKit/ObjectiveClass.swift | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/ObjectiveKit/ObjectiveClass.swift b/ObjectiveKit/ObjectiveClass.swift index 2cf2236..a89a92b 100644 --- a/ObjectiveKit/ObjectiveClass.swift +++ b/ObjectiveKit/ObjectiveClass.swift @@ -36,9 +36,9 @@ public class ObjectiveClass : ObjectiveKitRuntimeModification { /// /// - Returns: An array of instance variables. public var ivars: [String] { - return self.runtimeEntities( + return self.runtimeStrings( with: { class_copyIvarList($0, $1) }, - transform: toStringDecorator(ivar_getName) + transform: ivar_getName ) } @@ -57,23 +57,23 @@ public class ObjectiveClass : ObjectiveKitRuntimeModification { /// /// - Returns: An array of protocol names. public var protocols: [String] { - return self.runtimeEntities( + return self.runtimeStrings( with: { (cls, count) -> UnsafeMutablePointer! in let raw = UnsafeRawPointer(class_copyProtocolList(cls, count)) let unsafeProtocols = raw?.assumingMemoryBound(to: (Protocol?).self) return UnsafeMutablePointer(mutating: unsafeProtocols) }, - transform: toStringDecorator(protocol_getName)) + transform: protocol_getName) } /// Get all properties implemented by the class. /// /// - Returns: An array of property names. public var properties: [String] { - return self.runtimeEntities( + return self.runtimeStrings( with: { class_copyPropertyList($0, $1) }, - transform: toStringDecorator(property_getName) + transform: property_getName ) } @@ -92,6 +92,14 @@ public class ObjectiveClass : ObjectiveKitRuntimeModification { return UnsafeMutableBufferPointer(start: entities, count: count).flatMap { $0 } .flatMap(transform) } + + private func runtimeStrings( + with copyingGetter:(AnyClass?, UnsafeMutablePointer?) -> UnsafeMutablePointer!, + transform: @escaping (Type!) -> UnsafePointer! + ) -> [String] + { + return self.runtimeEntities(with: copyingGetter, transform: toStringDecorator(transform)) + } } From b1c8fdb304625c4a911b0d31cd9899332006d2b4 Mon Sep 17 00:00:00 2001 From: Oleksa 'trimm' Korin Date: Wed, 8 Feb 2017 00:24:27 +0200 Subject: [PATCH 3/7] ObjectiveClass -> removed obsolete methods, improved style --- ObjectiveKit/ObjectiveClass.swift | 32 +++++++++---------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/ObjectiveKit/ObjectiveClass.swift b/ObjectiveKit/ObjectiveClass.swift index a89a92b..5d1ae19 100644 --- a/ObjectiveKit/ObjectiveClass.swift +++ b/ObjectiveKit/ObjectiveClass.swift @@ -10,14 +10,6 @@ import Foundation typealias ImplementationBlock = @convention(block) () -> Void -fileprivate func toStringDecorator(_ f: @escaping (T!) -> UnsafePointer!) -> (T!) -> String? { - return { - let name = f($0) - - return name.map { String(cString: $0) } - } -} - /// An object that allows you to introspect and modify classes through the ObjC runtime. public class ObjectiveClass : ObjectiveKitRuntimeModification { @@ -36,21 +28,14 @@ public class ObjectiveClass : ObjectiveKitRuntimeModification { /// /// - Returns: An array of instance variables. public var ivars: [String] { - return self.runtimeStrings( - with: { class_copyIvarList($0, $1) }, - transform: ivar_getName - ) + return self.runtimeStrings(with: { class_copyIvarList($0, $1) }, transform: ivar_getName) } - /// Get all selectors implemented by the class. /// /// - Returns: An array of selectors. public var selectors: [Selector] { - return self.runtimeEntities( - with: { class_copyMethodList($0, $1) }, - transform: { method_getName($0) } - ) + return self.runtimeEntities(with: { class_copyMethodList($0, $1) }, transform: { method_getName($0) }) } /// Get all protocols implemented by the class. @@ -71,10 +56,7 @@ public class ObjectiveClass : ObjectiveKitRuntimeModification { /// /// - Returns: An array of property names. public var properties: [String] { - return self.runtimeStrings( - with: { class_copyPropertyList($0, $1) }, - transform: property_getName - ) + return self.runtimeStrings(with: { class_copyPropertyList($0, $1) }, transform: property_getName) } private func runtimeEntities( @@ -95,10 +77,14 @@ public class ObjectiveClass : ObjectiveKitRuntimeModification { private func runtimeStrings( with copyingGetter:(AnyClass?, UnsafeMutablePointer?) -> UnsafeMutablePointer!, - transform: @escaping (Type!) -> UnsafePointer! + transform: (Type!) -> UnsafePointer! ) -> [String] { - return self.runtimeEntities(with: copyingGetter, transform: toStringDecorator(transform)) + return self.runtimeEntities(with: copyingGetter) { + let name = transform($0) + + return name.map { String(cString: $0) } + } } } From 9b816909d23e80c10bea5dc35d420733e6c8d98a Mon Sep 17 00:00:00 2001 From: Oleksa 'trimm' Korin Date: Wed, 8 Feb 2017 00:27:07 +0200 Subject: [PATCH 4/7] ObjectiveClass -> removed obsolete type declarations --- ObjectiveKit/ObjectiveClass.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ObjectiveKit/ObjectiveClass.swift b/ObjectiveKit/ObjectiveClass.swift index 5d1ae19..8078d10 100644 --- a/ObjectiveKit/ObjectiveClass.swift +++ b/ObjectiveKit/ObjectiveClass.swift @@ -43,8 +43,8 @@ public class ObjectiveClass : ObjectiveKitRuntimeModification { /// - Returns: An array of protocol names. public var protocols: [String] { return self.runtimeStrings( - with: { (cls, count) -> UnsafeMutablePointer! in - let raw = UnsafeRawPointer(class_copyProtocolList(cls, count)) + with: { + let raw = UnsafeRawPointer(class_copyProtocolList($0, $1)) let unsafeProtocols = raw?.assumingMemoryBound(to: (Protocol?).self) return UnsafeMutablePointer(mutating: unsafeProtocols) From 4c454e503056a6170361c357b29a49edcf89546b Mon Sep 17 00:00:00 2001 From: Oleksa 'trimm' Korin Date: Wed, 8 Feb 2017 00:30:40 +0200 Subject: [PATCH 5/7] ObjectiveClass -> added runtime copying getter typealias --- ObjectiveKit/ObjectiveClass.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ObjectiveKit/ObjectiveClass.swift b/ObjectiveKit/ObjectiveClass.swift index 8078d10..0b137d4 100644 --- a/ObjectiveKit/ObjectiveClass.swift +++ b/ObjectiveKit/ObjectiveClass.swift @@ -59,8 +59,9 @@ public class ObjectiveClass : ObjectiveKitRuntimeModification { return self.runtimeStrings(with: { class_copyPropertyList($0, $1) }, transform: property_getName) } + private typealias RuntimeCopyingGetter = (AnyClass?, UnsafeMutablePointer?) -> UnsafeMutablePointer! private func runtimeEntities( - with copyingGetter:(AnyClass?, UnsafeMutablePointer?) -> UnsafeMutablePointer!, + with copyingGetter: RuntimeCopyingGetter, transform: (Type) -> Result? ) -> [Result] { @@ -76,7 +77,7 @@ public class ObjectiveClass : ObjectiveKitRuntimeModification { } private func runtimeStrings( - with copyingGetter:(AnyClass?, UnsafeMutablePointer?) -> UnsafeMutablePointer!, + with copyingGetter:RuntimeCopyingGetter, transform: (Type!) -> UnsafePointer! ) -> [String] { From 5b93e3850278bede58be4a2267bef3b815a1e61d Mon Sep 17 00:00:00 2001 From: Oleksa 'trimm' Korin Date: Wed, 8 Feb 2017 22:05:53 +0200 Subject: [PATCH 6/7] ObjectiveClass -> removed unnecessary conversions for autoreleasingunsafemutablepointer, used pure to convert from implicit optional, improved style --- ObjectiveKit.xcodeproj/project.pbxproj | 5 +++++ ObjectiveKit/ObjectiveClass.swift | 28 +++++++++----------------- ObjectiveKit/Optional+Extensions.swift | 17 ++++++++++++++++ 3 files changed, 31 insertions(+), 19 deletions(-) create mode 100644 ObjectiveKit/Optional+Extensions.swift diff --git a/ObjectiveKit.xcodeproj/project.pbxproj b/ObjectiveKit.xcodeproj/project.pbxproj index a6fb358..671e7af 100644 --- a/ObjectiveKit.xcodeproj/project.pbxproj +++ b/ObjectiveKit.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 344C27861DD5CDCF008AA223 /* ObjectiveKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 344C27781DD5CDCF008AA223 /* ObjectiveKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 344C27901DD5CFAB008AA223 /* ObjectiveClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344C278F1DD5CFAB008AA223 /* ObjectiveClass.swift */; }; 344C27941DD6F4E1008AA223 /* RuntimeClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344C27931DD6F4E1008AA223 /* RuntimeClass.swift */; }; + D7D1F6F71E4BAE4200C6E22E /* Optional+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7D1F6F61E4BAE4200C6E22E /* Optional+Extensions.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -35,6 +36,7 @@ 344C27851DD5CDCF008AA223 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 344C278F1DD5CFAB008AA223 /* ObjectiveClass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectiveClass.swift; sourceTree = ""; }; 344C27931DD6F4E1008AA223 /* RuntimeClass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RuntimeClass.swift; sourceTree = ""; }; + D7D1F6F61E4BAE4200C6E22E /* Optional+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Optional+Extensions.swift"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -82,6 +84,7 @@ 344C27931DD6F4E1008AA223 /* RuntimeClass.swift */, 344553051DDA6C1B007852A1 /* RuntimeModification.swift */, 344C27791DD5CDCF008AA223 /* Info.plist */, + D7D1F6F61E4BAE4200C6E22E /* Optional+Extensions.swift */, ); path = ObjectiveKit; sourceTree = ""; @@ -174,6 +177,7 @@ hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); mainGroup = 344C276B1DD5CDCF008AA223; productRefGroup = 344C27761DD5CDCF008AA223 /* Products */; @@ -209,6 +213,7 @@ buildActionMask = 2147483647; files = ( 344C27901DD5CFAB008AA223 /* ObjectiveClass.swift in Sources */, + D7D1F6F71E4BAE4200C6E22E /* Optional+Extensions.swift in Sources */, 344553061DDA6C1B007852A1 /* RuntimeModification.swift in Sources */, 344C27941DD6F4E1008AA223 /* RuntimeClass.swift in Sources */, ); diff --git a/ObjectiveKit/ObjectiveClass.swift b/ObjectiveKit/ObjectiveClass.swift index 0b137d4..e3be347 100644 --- a/ObjectiveKit/ObjectiveClass.swift +++ b/ObjectiveKit/ObjectiveClass.swift @@ -12,6 +12,8 @@ typealias ImplementationBlock = @convention(block) () -> Void /// An object that allows you to introspect and modify classes through the ObjC runtime. public class ObjectiveClass : ObjectiveKitRuntimeModification { + + private typealias RuntimeCopyingGetter = (AnyClass?, UnsafeMutablePointer?) -> UnsafeMutablePointer! public var internalClass: AnyClass @@ -35,7 +37,7 @@ public class ObjectiveClass : ObjectiveKitRuntimeModification { /// /// - Returns: An array of selectors. public var selectors: [Selector] { - return self.runtimeEntities(with: { class_copyMethodList($0, $1) }, transform: { method_getName($0) }) + return self.runtimeEntities(with: { class_copyMethodList($0, $1) }, transform: method_getName) } /// Get all protocols implemented by the class. @@ -43,13 +45,9 @@ public class ObjectiveClass : ObjectiveKitRuntimeModification { /// - Returns: An array of protocol names. public var protocols: [String] { return self.runtimeStrings( - with: { - let raw = UnsafeRawPointer(class_copyProtocolList($0, $1)) - let unsafeProtocols = raw?.assumingMemoryBound(to: (Protocol?).self) - - return UnsafeMutablePointer(mutating: unsafeProtocols) - }, - transform: protocol_getName) + with: { UnsafeMutablePointer(mutating: class_copyProtocolList($0, $1)) }, + transform: protocol_getName + ) } /// Get all properties implemented by the class. @@ -59,7 +57,6 @@ public class ObjectiveClass : ObjectiveKitRuntimeModification { return self.runtimeStrings(with: { class_copyPropertyList($0, $1) }, transform: property_getName) } - private typealias RuntimeCopyingGetter = (AnyClass?, UnsafeMutablePointer?) -> UnsafeMutablePointer! private func runtimeEntities( with copyingGetter: RuntimeCopyingGetter, transform: (Type) -> Result? @@ -72,21 +69,14 @@ public class ObjectiveClass : ObjectiveKitRuntimeModification { defer { entities?.deallocate(capacity: count) } - return UnsafeMutableBufferPointer(start: entities, count: count).flatMap { $0 } - .flatMap(transform) + return UnsafeMutableBufferPointer(start: entities, count: count).flatMap(identity).flatMap(transform) } private func runtimeStrings( - with copyingGetter:RuntimeCopyingGetter, + with copyingGetter: RuntimeCopyingGetter, transform: (Type!) -> UnsafePointer! ) -> [String] { - return self.runtimeEntities(with: copyingGetter) { - let name = transform($0) - - return name.map { String(cString: $0) } - } + return self.runtimeEntities(with: copyingGetter) { pure(transform($0)).map { String(cString: $0) } } } } - - diff --git a/ObjectiveKit/Optional+Extensions.swift b/ObjectiveKit/Optional+Extensions.swift new file mode 100644 index 0000000..06b5852 --- /dev/null +++ b/ObjectiveKit/Optional+Extensions.swift @@ -0,0 +1,17 @@ +// +// Optional+Extensions.swift +// ObjectiveKit +// +// Created by Oleksa 'trimm' Korin on 2/8/17. +// Copyright © 2017 Roy Marmelstein. All rights reserved. +// + +/// Wraps value in optional +public func pure(_ value: T) -> T? { + return value +} + +/// Returns the value passed as the parameter +public func identity(_ value: T) -> T { + return value +} From b3f0b2367167982a26e8cea5b4b31c8a589d3f74 Mon Sep 17 00:00:00 2001 From: Oleksa 'trimm' Korin Date: Fri, 13 Oct 2017 00:46:31 +0300 Subject: [PATCH 7/7] Fixed style --- ObjectiveKit/ObjectiveClass.swift | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/ObjectiveKit/ObjectiveClass.swift b/ObjectiveKit/ObjectiveClass.swift index e3be347..0de9f02 100644 --- a/ObjectiveKit/ObjectiveClass.swift +++ b/ObjectiveKit/ObjectiveClass.swift @@ -57,10 +57,13 @@ public class ObjectiveClass : ObjectiveKitRuntimeModification { return self.runtimeStrings(with: { class_copyPropertyList($0, $1) }, transform: property_getName) } + // MARK: Private + private func runtimeEntities( with copyingGetter: RuntimeCopyingGetter, transform: (Type) -> Result? - ) -> [Result] + ) + -> [Result] { var cCount: CUnsignedInt = 0 @@ -69,14 +72,19 @@ public class ObjectiveClass : ObjectiveKitRuntimeModification { defer { entities?.deallocate(capacity: count) } - return UnsafeMutableBufferPointer(start: entities, count: count).flatMap(identity).flatMap(transform) + return UnsafeMutableBufferPointer(start: entities, count: count) + .flatMap(identity) + .flatMap(transform) } private func runtimeStrings( with copyingGetter: RuntimeCopyingGetter, transform: (Type!) -> UnsafePointer! - ) -> [String] + ) + -> [String] { - return self.runtimeEntities(with: copyingGetter) { pure(transform($0)).map { String(cString: $0) } } + return self.runtimeEntities(with: copyingGetter) { + pure(transform($0)).map(String.init(cString:)) + } } }