Как swizzle Swift.print (элементы: разделитель: терминатор) - PullRequest
0 голосов
/ 01 января 2019

Я ищу способы поменять функцию Swift.print.Заменить его нельзя, так как он может обойтись, если вы используете Swift.print(:)

Селектор не распознает идентификатор:

@objc class func printSwizzle() {
    guard let instance = class_getInstanceMethod(self, #selector(print(separator:terminator:))),
    let swizzleInstance = class_getInstanceMethod(self, #selector(swizzlePrint(separator:terminator:))) else { return }
    method_exchangeImplementations(instance, swizzleInstance)
}

Возможно ли это вообще?Swizzling - это obj-c функция времени выполнения.

Ответы [ 2 ]

0 голосов
/ 01 января 2019

Метод Swizzling - это функция Objective C, которая позволяет вам обмениваться реализацией метода во время выполнения.Для этого вам нужен объект @objc, который наследуется от NSObject.И вам нужен метод .

Swift.print это не метод.Это функция, объявленная в модуле Swift.Мы можем сказать, что это глобально, но это не совсем глобально.Он определен внутри модуля Swift, который автоматически импортируется в каждый код Swift, поэтому вы можете использовать его без префикса Swift..

Таким образом, нет никакого способа промахнуться Swift.print.

Что вы можете сделать, это скрыть эту функцию, используя вашу собственную реализацию, то есть, если вы объявите функцию с тем же именем в вашем собственном модуле, то когда используется print, компиляторвместо этого вы предпочтете свою функцию, потому что функции в текущем модуле предпочтительнее, чем функции в других модулях (включая Swift. модуль).

public func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
    let output = items.map { "\($0)" }.joined(separator: separator)
    Swift.print(output, terminator: terminator)
}

Вы можете использовать любую логику, какую захотите.

На самом деле очень часто это используется для удаления ведения журнала с производства, например:

#if !DEBUG

func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {}
func debugPrint(_ items: Any..., separator: String = " ", terminator: String = "\n") {}

#endif

См. Удаление println () для версии выпуска iOS Swift для получения более подробной информации.

По сути, вы могли бы скрыть весь модуль Swift, перераспределив его внутри модуля, например, как enum, поэтому отключив вызовы на Swift.print:

enum Swift {
    public static func print(_ items: Any..., separator: String = " ", terminator: String = " ") {
        // do something
    }
}

Однако я бы, как правило,советую против этого, потому что будет трудно разрешить любые конфликты имен со стандартной библиотекой внутри модуля Swift..

В общем, я бы посоветовал реализовать вашу собственную систему ведения журналов и обеспечить ее использование другими средствами,например, проверки кода или правила печати (например, swiftlint).

0 голосов
/ 01 января 2019

Добавление к комментариям Александра и Carpsen90

Метод Swizzling - это функция Objective-C времени выполнения, которая по своей сути не доступна в Swift, поскольку Swift не являетсядинамический язык.Тем не менее, вы можете иметь глобальную функцию, как в этом SO Post .Ниже обновленный код для Swift 4.2.Но, к сожалению, он вызывает оригинальную функцию Swift.print, если имя функции print.Поэтому я изменил имя функции на logs

public func logs(items: Any..., separator: String = " ", terminator: String = "\n") {
    let output = items.map { "*\($0)"}.joined(separator: " ")
    Swift.print(output, terminator: terminator)
}

Другой возможный вариант - поместить его в протокол

public protocol CustomPrintable {
    func print(_ items: Any...)
}

extension CustomPrintable {
    func print(_ items: Any...) {
        let output = items.map { "*\($0)"}.joined(separator: " ")
        Swift.print("****" + output)
    }
}

Использование

class SampleClass : CustomPrintable {

  func printValue() {
      print ("Hello World")
  }
}

Но при этом функция перестает быть глобальной функцией, и при использовании print вы должны выбрать правильный метод enter image description here

Вывод

*****Hello World
...