Skip to content

Commit

Permalink
Updated to Swift 5
Browse files Browse the repository at this point in the history
  • Loading branch information
acecilia committed Apr 13, 2020
1 parent c52df80 commit 211a222
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 47 deletions.
94 changes: 84 additions & 10 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,36 @@

# Created by https://www.gitignore.io/api/xcode,macos,swift,swiftpm,swiftpackagemanager
# Edit at https://www.gitignore.io/?templates=xcode,macos,swift,swiftpm,swiftpackagemanager

### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

### Swift ###
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
Expand All @@ -19,7 +52,8 @@ xcuserdata/

## Other
*.moved-aside
*.xcuserstate
*.xccheckout
*.xcscmblueprint

## Obj-C/Swift specific
*.hmap
Expand All @@ -32,36 +66,76 @@ timeline.xctimeline
playground.xcworkspace

# Swift Package Manager
#
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
# Package.pins
# Package.resolved
.build/
# Add this line if you want to avoid checking in Xcode SPM integration.
.swiftpm/xcode

# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/
# Add this line if you want to avoid checking in source code from the Xcode workspace
# *.xcworkspace

# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts

Carthage/Build

# Accio dependency management
Dependencies/
.accio/

# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
# https://docs.fastlane.tools/best-practices/source-control/#source-control

fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/screenshots/**/*.png
fastlane/test_output
ObjectiveKit.xcodeproj/project.xcworkspace/xcuserdata/marmelroy.xcuserdatad/UserInterfaceState.xcuserstate
ObjectiveKit.xcodeproj/xcuserdata/marmelroy.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

# Code Injection
# After new code Injection tools there's a generated folder /iOSInjectionProject
# https://github.com/johnno1962/injectionforxcode

iOSInjectionProject/

### SwiftPackageManager ###
Packages
xcuserdata
*.xcodeproj


### SwiftPM ###


### Xcode ###
# Xcode
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore

## User settings

## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)

## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)

## Xcode Patch
*.xcodeproj/*
!*.xcodeproj/project.pbxproj
!*.xcodeproj/xcshareddata/
!*.xcworkspace/contents.xcworkspacedata
/*.gcno

### Xcode Patch ###
**/xcshareddata/WorkspaceSettings.xcsettings

# End of https://www.gitignore.io/api/xcode,macos,swift,swiftpm,swiftpackagemanager
22 changes: 8 additions & 14 deletions ObjectiveKit/ObjectiveClass.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@

import Foundation

typealias ImplementationBlock = @convention(block) () -> Void

/// An object that allows you to introspect and modify classes through the ObjC runtime.
public class ObjectiveClass <T: NSObject>: ObjectiveKitRuntimeModification {
public class ObjectiveClass<T: NSObject>: ObjectiveKitRuntimeModification {

public var internalClass: AnyClass

Expand All @@ -33,7 +31,7 @@ public class ObjectiveClass <T: NSObject>: ObjectiveKitRuntimeModification {
var ivars = [String]()
let ivarList = class_copyIvarList(internalClass, &count)
for i in (0..<Int(count)) {
let unwrapped = ivarList?[i].unsafelyUnwrapped
let unwrapped = (ivarList?[i]).unsafelyUnwrapped
if let ivar = ivar_getName(unwrapped) {
let string = String(cString: ivar)
ivars.append(string)
Expand All @@ -44,7 +42,6 @@ public class ObjectiveClass <T: NSObject>: ObjectiveKitRuntimeModification {
}
}


/// Get all selectors implemented by the class.
///
/// - Returns: An array of selectors.
Expand All @@ -54,8 +51,8 @@ public class ObjectiveClass <T: NSObject>: ObjectiveKitRuntimeModification {
var selectors = [Selector]()
let methodList = class_copyMethodList(internalClass, &count)
for i in (0..<Int(count)) {
let unwrapped = methodList?[i].unsafelyUnwrapped
if let selector = method_getName(unwrapped) {
if let unwrapped = methodList?[i] {
let selector = method_getName(unwrapped)
selectors.append(selector)
}
}
Expand All @@ -73,8 +70,8 @@ public class ObjectiveClass <T: NSObject>: ObjectiveKitRuntimeModification {
var protocols = [String]()
let protocolList = class_copyProtocolList(internalClass, &count)
for i in (0..<Int(count)) {
let unwrapped = protocolList?[i].unsafelyUnwrapped
if let protocolName = protocol_getName(unwrapped) {
if let unwrapped = protocolList?[i] {
let protocolName = protocol_getName(unwrapped)
let string = String(cString: protocolName)
protocols.append(string)
}
Expand All @@ -92,8 +89,8 @@ public class ObjectiveClass <T: NSObject>: ObjectiveKitRuntimeModification {
var properties = [String]()
let propertyList = class_copyPropertyList(internalClass, &count)
for i in (0..<Int(count)) {
let unwrapped = propertyList?[i].unsafelyUnwrapped
if let propretyName = property_getName(unwrapped) {
if let unwrapped = propertyList?[i] {
let propretyName = property_getName(unwrapped)
let string = String(cString: propretyName)
properties.append(string)
}
Expand All @@ -102,7 +99,4 @@ public class ObjectiveClass <T: NSObject>: ObjectiveKitRuntimeModification {
return properties
}
}

}


12 changes: 4 additions & 8 deletions ObjectiveKit/RuntimeClass.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ import Foundation

/// A class created at runtime.
public class RuntimeClass: NSObject, ObjectiveKitRuntimeModification {

public var internalClass: AnyClass

private var registered: Bool = false

// MARK: Lifecycle
Expand All @@ -22,7 +20,10 @@ public class RuntimeClass: NSObject, ObjectiveKitRuntimeModification {
/// - Parameter superclass: Superclass to inherit from.
public init(superclass: AnyClass = NSObject.classForCoder()) {
let name = NSUUID().uuidString
self.internalClass = objc_allocateClassPair(superclass, name, 0)
guard let internalClass = objc_allocateClassPair(superclass, name, 0) else {
fatalError("The class '\(superclass)' could not be created")
}
self.internalClass = internalClass
}

// MARK: Dynamic class creation
Expand All @@ -41,7 +42,6 @@ public class RuntimeClass: NSObject, ObjectiveKitRuntimeModification {
class_addIvar(self.internalClass, name, size, UInt8(alignment), rawEncoding)
}


/// Register class. Required before usage. Happens automatically on allocate.
public func register() {
if registered == false {
Expand All @@ -57,10 +57,8 @@ public class RuntimeClass: NSObject, ObjectiveKitRuntimeModification {
self.register()
return internalClass.alloc() as! NSObject
}

}


/// Objective Type
///
/// - NSString: NSString
Expand All @@ -87,6 +85,4 @@ public enum ObjectiveType: Int {
case .Void: return "v"
}
}

}

27 changes: 13 additions & 14 deletions ObjectiveKit/RuntimeModification.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import Foundation

public protocol ObjectiveKitRuntimeModification {

var internalClass: AnyClass { get }

// MARK: Runtime modification
Expand All @@ -26,50 +25,50 @@ public protocol ObjectiveKitRuntimeModification {
/// - Parameters:
/// - identifier: Selector name.
/// - implementation: Implementation as a closure.
func addMethod(_ identifier: String, implementation: ImplementationBlock)
@discardableResult
func addMethod(_ identifier: String, implementation: @escaping @convention(block) (AnyObject) -> Void) -> Selector

/// Exchange selectors implemented in the current class.
///
/// - Parameters:
/// - aSelector: Selector.
/// - otherSelector: Selector.
func exchangeSelector(_ aSelector: Selector, with otherSelector: Selector)

}

extension ObjectiveKitRuntimeModification {

public func addSelector(_ selector: Selector, from originalClass: AnyClass) {
guard let method = class_getInstanceMethod(originalClass, selector), let implementation = method_getImplementation(method), let typeEncoding = method_getTypeEncoding(method) else {
guard let method = class_getInstanceMethod(originalClass, selector), let typeEncoding = method_getTypeEncoding(method) else {
return
}
let implementation = method_getImplementation(method)
let string = String(cString: typeEncoding)
class_addMethod(internalClass, selector, implementation, string)
}

public func addMethod(_ identifier: String, implementation: ImplementationBlock) {
let blockObject = unsafeBitCast(implementation, to: AnyObject.self)
@discardableResult
public func addMethod(_ identifier: String, implementation: @escaping @convention(block) (AnyObject) -> Void) -> Selector {
let blockObject = unsafeBitCast(implementation, to: NSObject.self)
let implementation = imp_implementationWithBlock(blockObject)
let selector = NSSelectorFromString(identifier)
let encoding = "v@:f"
class_addMethod(internalClass, selector, implementation, encoding)
class_replaceMethod(internalClass, selector, implementation, encoding)
return selector
}

public func exchangeSelector(_ aSelector: Selector, with otherSelector: Selector) {
let method = class_getInstanceMethod(internalClass, aSelector)
let otherMethod = class_getInstanceMethod(internalClass, otherSelector)
guard let method = class_getInstanceMethod(internalClass, aSelector), let otherMethod = class_getInstanceMethod(internalClass, otherSelector) else {
return
}
method_exchangeImplementations(method, otherMethod)
}

}

public extension NSObject {

/// A convenience method to perform selectors by identifier strings.
///
/// - Parameter identifier: Selector name.
public func performMethod(_ identifier: String) {
func performMethod(_ identifier: String) {
perform(NSSelectorFromString(identifier))
}
}

23 changes: 22 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
// swift-tools-version:5.2
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "Interpolate"
name: "ObjectiveKit",
products: [
.library(name: "ObjectiveKit", targets: ["ObjectiveKit"]),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target(
name: "ObjectiveKit",
path: "ObjectiveKit"
),
.testTarget(
name: "ObjectiveKitTests",
dependencies: [
"ObjectiveKit"
],
path: "ObjectiveKitTests"
),
]
)

0 comments on commit 211a222

Please sign in to comment.