How to swizzle Swift.print(items:separator:terminator)












2















I am looking for ways to swizzle Swift.print function. Overriding it is not an option, as it may get bypasses if you use Swift.print(:)



The selector does not recognise the identifier:



@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)
}


Is that even possible? As swizzling is an obj-c runtime feature.










share|improve this question

























  • For a function to be swizzled, it has to be declared as @dynamic and marked with @objc. Swift.print doesn't check any of those conditions.

    – Carpsen90
    Jan 1 at 8:12






  • 1





    To add to what Carpsen90 said, swizzling only works because in ObjC land, there is one central place that all method calls jump through, which is the ObjC runtime. That's great because it can let you do crazy stuff like intercepting and forwarding messages, swizzling method implementations, etc. On the down side, it can hurt performance pretty drastically. Swift function calls can be much more aggressively optimized (e.g. for small enough functions, calls can be replaced with an inline "copy", saving cost of a function call)

    – Alexander
    Jan 1 at 8:28






  • 1





    Swift.print is a global function, which doesn't belong to any class or object. It has no relation to the ObjC runtime, so you can't use the ObjC runtime to try to modify it

    – Alexander
    Jan 1 at 8:29











  • Explain what you are really trying to do.

    – matt
    Jan 1 at 19:20











  • Thank you @matt , I was after swizzling the print function but as we all know and after everyone commented, this is not possible. All the answers are great for the community to learn. This is what I do now anyway, but wanted to avoid it. Cheers

    – Tal Zion
    Jan 1 at 19:32
















2















I am looking for ways to swizzle Swift.print function. Overriding it is not an option, as it may get bypasses if you use Swift.print(:)



The selector does not recognise the identifier:



@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)
}


Is that even possible? As swizzling is an obj-c runtime feature.










share|improve this question

























  • For a function to be swizzled, it has to be declared as @dynamic and marked with @objc. Swift.print doesn't check any of those conditions.

    – Carpsen90
    Jan 1 at 8:12






  • 1





    To add to what Carpsen90 said, swizzling only works because in ObjC land, there is one central place that all method calls jump through, which is the ObjC runtime. That's great because it can let you do crazy stuff like intercepting and forwarding messages, swizzling method implementations, etc. On the down side, it can hurt performance pretty drastically. Swift function calls can be much more aggressively optimized (e.g. for small enough functions, calls can be replaced with an inline "copy", saving cost of a function call)

    – Alexander
    Jan 1 at 8:28






  • 1





    Swift.print is a global function, which doesn't belong to any class or object. It has no relation to the ObjC runtime, so you can't use the ObjC runtime to try to modify it

    – Alexander
    Jan 1 at 8:29











  • Explain what you are really trying to do.

    – matt
    Jan 1 at 19:20











  • Thank you @matt , I was after swizzling the print function but as we all know and after everyone commented, this is not possible. All the answers are great for the community to learn. This is what I do now anyway, but wanted to avoid it. Cheers

    – Tal Zion
    Jan 1 at 19:32














2












2








2


0






I am looking for ways to swizzle Swift.print function. Overriding it is not an option, as it may get bypasses if you use Swift.print(:)



The selector does not recognise the identifier:



@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)
}


Is that even possible? As swizzling is an obj-c runtime feature.










share|improve this question
















I am looking for ways to swizzle Swift.print function. Overriding it is not an option, as it may get bypasses if you use Swift.print(:)



The selector does not recognise the identifier:



@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)
}


Is that even possible? As swizzling is an obj-c runtime feature.







ios swift method-swizzling






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 1 at 8:42









JJJ

29.2k147591




29.2k147591










asked Jan 1 at 7:07









Tal ZionTal Zion

3,0812244




3,0812244













  • For a function to be swizzled, it has to be declared as @dynamic and marked with @objc. Swift.print doesn't check any of those conditions.

    – Carpsen90
    Jan 1 at 8:12






  • 1





    To add to what Carpsen90 said, swizzling only works because in ObjC land, there is one central place that all method calls jump through, which is the ObjC runtime. That's great because it can let you do crazy stuff like intercepting and forwarding messages, swizzling method implementations, etc. On the down side, it can hurt performance pretty drastically. Swift function calls can be much more aggressively optimized (e.g. for small enough functions, calls can be replaced with an inline "copy", saving cost of a function call)

    – Alexander
    Jan 1 at 8:28






  • 1





    Swift.print is a global function, which doesn't belong to any class or object. It has no relation to the ObjC runtime, so you can't use the ObjC runtime to try to modify it

    – Alexander
    Jan 1 at 8:29











  • Explain what you are really trying to do.

    – matt
    Jan 1 at 19:20











  • Thank you @matt , I was after swizzling the print function but as we all know and after everyone commented, this is not possible. All the answers are great for the community to learn. This is what I do now anyway, but wanted to avoid it. Cheers

    – Tal Zion
    Jan 1 at 19:32



















  • For a function to be swizzled, it has to be declared as @dynamic and marked with @objc. Swift.print doesn't check any of those conditions.

    – Carpsen90
    Jan 1 at 8:12






  • 1





    To add to what Carpsen90 said, swizzling only works because in ObjC land, there is one central place that all method calls jump through, which is the ObjC runtime. That's great because it can let you do crazy stuff like intercepting and forwarding messages, swizzling method implementations, etc. On the down side, it can hurt performance pretty drastically. Swift function calls can be much more aggressively optimized (e.g. for small enough functions, calls can be replaced with an inline "copy", saving cost of a function call)

    – Alexander
    Jan 1 at 8:28






  • 1





    Swift.print is a global function, which doesn't belong to any class or object. It has no relation to the ObjC runtime, so you can't use the ObjC runtime to try to modify it

    – Alexander
    Jan 1 at 8:29











  • Explain what you are really trying to do.

    – matt
    Jan 1 at 19:20











  • Thank you @matt , I was after swizzling the print function but as we all know and after everyone commented, this is not possible. All the answers are great for the community to learn. This is what I do now anyway, but wanted to avoid it. Cheers

    – Tal Zion
    Jan 1 at 19:32

















For a function to be swizzled, it has to be declared as @dynamic and marked with @objc. Swift.print doesn't check any of those conditions.

– Carpsen90
Jan 1 at 8:12





For a function to be swizzled, it has to be declared as @dynamic and marked with @objc. Swift.print doesn't check any of those conditions.

– Carpsen90
Jan 1 at 8:12




1




1





To add to what Carpsen90 said, swizzling only works because in ObjC land, there is one central place that all method calls jump through, which is the ObjC runtime. That's great because it can let you do crazy stuff like intercepting and forwarding messages, swizzling method implementations, etc. On the down side, it can hurt performance pretty drastically. Swift function calls can be much more aggressively optimized (e.g. for small enough functions, calls can be replaced with an inline "copy", saving cost of a function call)

– Alexander
Jan 1 at 8:28





To add to what Carpsen90 said, swizzling only works because in ObjC land, there is one central place that all method calls jump through, which is the ObjC runtime. That's great because it can let you do crazy stuff like intercepting and forwarding messages, swizzling method implementations, etc. On the down side, it can hurt performance pretty drastically. Swift function calls can be much more aggressively optimized (e.g. for small enough functions, calls can be replaced with an inline "copy", saving cost of a function call)

– Alexander
Jan 1 at 8:28




1




1





Swift.print is a global function, which doesn't belong to any class or object. It has no relation to the ObjC runtime, so you can't use the ObjC runtime to try to modify it

– Alexander
Jan 1 at 8:29





Swift.print is a global function, which doesn't belong to any class or object. It has no relation to the ObjC runtime, so you can't use the ObjC runtime to try to modify it

– Alexander
Jan 1 at 8:29













Explain what you are really trying to do.

– matt
Jan 1 at 19:20





Explain what you are really trying to do.

– matt
Jan 1 at 19:20













Thank you @matt , I was after swizzling the print function but as we all know and after everyone commented, this is not possible. All the answers are great for the community to learn. This is what I do now anyway, but wanted to avoid it. Cheers

– Tal Zion
Jan 1 at 19:32





Thank you @matt , I was after swizzling the print function but as we all know and after everyone commented, this is not possible. All the answers are great for the community to learn. This is what I do now anyway, but wanted to avoid it. Cheers

– Tal Zion
Jan 1 at 19:32












2 Answers
2






active

oldest

votes


















3














Method swizzling is an Objective-C feature that enables you to exchange implementation of a method at runtime. For that, you need an @objc object that inherits from NSObject. And you need a method.



Swift.print is not a method. It's a function declared in the Swift module. We can say it's global but it's not really global. It's defined inside module Swift which is imported automatically to every Swift code, therefore you can use it without the Swift. prefix.



In summary, there is no way to swizzle Swift.print.



What you can do is to hide that function using your own implementation, that is, if you declare a function with the same name in your own module, then when print is used, the compiler will prefer your function instead because functions in the current module are preferred over functions in other modules (including Swift. module).



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


You can any logic you want in there.



It's actually very common to use this to remove logging from production, e.g.:



#if !DEBUG

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

#endif


See Remove println() for release version iOS Swift for more details.



Essentially, you could hide the whole Swift module by redeclaring it inside your module, e.g. as an enum, therefore disabling calls to Swift.print:



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


However, I would generally advise against this because it will be hard to solve any naming conflicts with the standard library inside the Swift. module.



In general, I would advise to implement your custom logging system and enforce its usage by other means, e.g. code reviews or linting rules (e.g. swiftlint).






share|improve this answer


























  • But he says in his question “Overriding it is not an option, as it may get bypasses if you use Swift.print(:)”. So he knows this and rejects it.

    – matt
    Jan 1 at 19:21













  • @matt Against by better judgement I have updated my answer to solve that.

    – Sulthan
    Jan 1 at 19:29













  • Thanks, @Sulthan , your solution to the problem is interesting.

    – Tal Zion
    Jan 2 at 6:23



















0














Adding to the comments by Alexander and Carpsen90



Method Swizzling is an Objective-C runtime feature and it is inherently not available in Swift as Swift is not a dynamic language. However, you can have a global function as in this SO Post. Below is the updated code for Swift 4.2.
But unfortunately, it calls the original Swift.print function if the function name is print. So I changed the function name to logs



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


Another Possible option is to put it into a protocol



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

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


Usage



class SampleClass : CustomPrintable {

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


But this way the function ceases to be a global function and while using print you have to select the correct methodenter image description here



Output



*****Hello World





share|improve this answer





















  • 1





    You didn't have correct external parameter names. It would have to be print(_ items: ...) not print(items: ...). That's why your method did not get called.

    – Sulthan
    Jan 2 at 8:08











  • @Sulthan Thanks for pointing it out, I made the change but still the function call goes to the Swift.print function

    – Md. Ibrahim Hassan
    Jan 2 at 16:17













Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53993673%2fhow-to-swizzle-swift-printitemsseparatorterminator%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









3














Method swizzling is an Objective-C feature that enables you to exchange implementation of a method at runtime. For that, you need an @objc object that inherits from NSObject. And you need a method.



Swift.print is not a method. It's a function declared in the Swift module. We can say it's global but it's not really global. It's defined inside module Swift which is imported automatically to every Swift code, therefore you can use it without the Swift. prefix.



In summary, there is no way to swizzle Swift.print.



What you can do is to hide that function using your own implementation, that is, if you declare a function with the same name in your own module, then when print is used, the compiler will prefer your function instead because functions in the current module are preferred over functions in other modules (including Swift. module).



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


You can any logic you want in there.



It's actually very common to use this to remove logging from production, e.g.:



#if !DEBUG

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

#endif


See Remove println() for release version iOS Swift for more details.



Essentially, you could hide the whole Swift module by redeclaring it inside your module, e.g. as an enum, therefore disabling calls to Swift.print:



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


However, I would generally advise against this because it will be hard to solve any naming conflicts with the standard library inside the Swift. module.



In general, I would advise to implement your custom logging system and enforce its usage by other means, e.g. code reviews or linting rules (e.g. swiftlint).






share|improve this answer


























  • But he says in his question “Overriding it is not an option, as it may get bypasses if you use Swift.print(:)”. So he knows this and rejects it.

    – matt
    Jan 1 at 19:21













  • @matt Against by better judgement I have updated my answer to solve that.

    – Sulthan
    Jan 1 at 19:29













  • Thanks, @Sulthan , your solution to the problem is interesting.

    – Tal Zion
    Jan 2 at 6:23
















3














Method swizzling is an Objective-C feature that enables you to exchange implementation of a method at runtime. For that, you need an @objc object that inherits from NSObject. And you need a method.



Swift.print is not a method. It's a function declared in the Swift module. We can say it's global but it's not really global. It's defined inside module Swift which is imported automatically to every Swift code, therefore you can use it without the Swift. prefix.



In summary, there is no way to swizzle Swift.print.



What you can do is to hide that function using your own implementation, that is, if you declare a function with the same name in your own module, then when print is used, the compiler will prefer your function instead because functions in the current module are preferred over functions in other modules (including Swift. module).



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


You can any logic you want in there.



It's actually very common to use this to remove logging from production, e.g.:



#if !DEBUG

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

#endif


See Remove println() for release version iOS Swift for more details.



Essentially, you could hide the whole Swift module by redeclaring it inside your module, e.g. as an enum, therefore disabling calls to Swift.print:



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


However, I would generally advise against this because it will be hard to solve any naming conflicts with the standard library inside the Swift. module.



In general, I would advise to implement your custom logging system and enforce its usage by other means, e.g. code reviews or linting rules (e.g. swiftlint).






share|improve this answer


























  • But he says in his question “Overriding it is not an option, as it may get bypasses if you use Swift.print(:)”. So he knows this and rejects it.

    – matt
    Jan 1 at 19:21













  • @matt Against by better judgement I have updated my answer to solve that.

    – Sulthan
    Jan 1 at 19:29













  • Thanks, @Sulthan , your solution to the problem is interesting.

    – Tal Zion
    Jan 2 at 6:23














3












3








3







Method swizzling is an Objective-C feature that enables you to exchange implementation of a method at runtime. For that, you need an @objc object that inherits from NSObject. And you need a method.



Swift.print is not a method. It's a function declared in the Swift module. We can say it's global but it's not really global. It's defined inside module Swift which is imported automatically to every Swift code, therefore you can use it without the Swift. prefix.



In summary, there is no way to swizzle Swift.print.



What you can do is to hide that function using your own implementation, that is, if you declare a function with the same name in your own module, then when print is used, the compiler will prefer your function instead because functions in the current module are preferred over functions in other modules (including Swift. module).



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


You can any logic you want in there.



It's actually very common to use this to remove logging from production, e.g.:



#if !DEBUG

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

#endif


See Remove println() for release version iOS Swift for more details.



Essentially, you could hide the whole Swift module by redeclaring it inside your module, e.g. as an enum, therefore disabling calls to Swift.print:



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


However, I would generally advise against this because it will be hard to solve any naming conflicts with the standard library inside the Swift. module.



In general, I would advise to implement your custom logging system and enforce its usage by other means, e.g. code reviews or linting rules (e.g. swiftlint).






share|improve this answer















Method swizzling is an Objective-C feature that enables you to exchange implementation of a method at runtime. For that, you need an @objc object that inherits from NSObject. And you need a method.



Swift.print is not a method. It's a function declared in the Swift module. We can say it's global but it's not really global. It's defined inside module Swift which is imported automatically to every Swift code, therefore you can use it without the Swift. prefix.



In summary, there is no way to swizzle Swift.print.



What you can do is to hide that function using your own implementation, that is, if you declare a function with the same name in your own module, then when print is used, the compiler will prefer your function instead because functions in the current module are preferred over functions in other modules (including Swift. module).



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


You can any logic you want in there.



It's actually very common to use this to remove logging from production, e.g.:



#if !DEBUG

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

#endif


See Remove println() for release version iOS Swift for more details.



Essentially, you could hide the whole Swift module by redeclaring it inside your module, e.g. as an enum, therefore disabling calls to Swift.print:



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


However, I would generally advise against this because it will be hard to solve any naming conflicts with the standard library inside the Swift. module.



In general, I would advise to implement your custom logging system and enforce its usage by other means, e.g. code reviews or linting rules (e.g. swiftlint).







share|improve this answer














share|improve this answer



share|improve this answer








edited Jan 1 at 19:35

























answered Jan 1 at 19:13









SulthanSulthan

96.9k16157202




96.9k16157202













  • But he says in his question “Overriding it is not an option, as it may get bypasses if you use Swift.print(:)”. So he knows this and rejects it.

    – matt
    Jan 1 at 19:21













  • @matt Against by better judgement I have updated my answer to solve that.

    – Sulthan
    Jan 1 at 19:29













  • Thanks, @Sulthan , your solution to the problem is interesting.

    – Tal Zion
    Jan 2 at 6:23



















  • But he says in his question “Overriding it is not an option, as it may get bypasses if you use Swift.print(:)”. So he knows this and rejects it.

    – matt
    Jan 1 at 19:21













  • @matt Against by better judgement I have updated my answer to solve that.

    – Sulthan
    Jan 1 at 19:29













  • Thanks, @Sulthan , your solution to the problem is interesting.

    – Tal Zion
    Jan 2 at 6:23

















But he says in his question “Overriding it is not an option, as it may get bypasses if you use Swift.print(:)”. So he knows this and rejects it.

– matt
Jan 1 at 19:21







But he says in his question “Overriding it is not an option, as it may get bypasses if you use Swift.print(:)”. So he knows this and rejects it.

– matt
Jan 1 at 19:21















@matt Against by better judgement I have updated my answer to solve that.

– Sulthan
Jan 1 at 19:29







@matt Against by better judgement I have updated my answer to solve that.

– Sulthan
Jan 1 at 19:29















Thanks, @Sulthan , your solution to the problem is interesting.

– Tal Zion
Jan 2 at 6:23





Thanks, @Sulthan , your solution to the problem is interesting.

– Tal Zion
Jan 2 at 6:23













0














Adding to the comments by Alexander and Carpsen90



Method Swizzling is an Objective-C runtime feature and it is inherently not available in Swift as Swift is not a dynamic language. However, you can have a global function as in this SO Post. Below is the updated code for Swift 4.2.
But unfortunately, it calls the original Swift.print function if the function name is print. So I changed the function name to logs



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


Another Possible option is to put it into a protocol



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

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


Usage



class SampleClass : CustomPrintable {

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


But this way the function ceases to be a global function and while using print you have to select the correct methodenter image description here



Output



*****Hello World





share|improve this answer





















  • 1





    You didn't have correct external parameter names. It would have to be print(_ items: ...) not print(items: ...). That's why your method did not get called.

    – Sulthan
    Jan 2 at 8:08











  • @Sulthan Thanks for pointing it out, I made the change but still the function call goes to the Swift.print function

    – Md. Ibrahim Hassan
    Jan 2 at 16:17


















0














Adding to the comments by Alexander and Carpsen90



Method Swizzling is an Objective-C runtime feature and it is inherently not available in Swift as Swift is not a dynamic language. However, you can have a global function as in this SO Post. Below is the updated code for Swift 4.2.
But unfortunately, it calls the original Swift.print function if the function name is print. So I changed the function name to logs



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


Another Possible option is to put it into a protocol



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

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


Usage



class SampleClass : CustomPrintable {

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


But this way the function ceases to be a global function and while using print you have to select the correct methodenter image description here



Output



*****Hello World





share|improve this answer





















  • 1





    You didn't have correct external parameter names. It would have to be print(_ items: ...) not print(items: ...). That's why your method did not get called.

    – Sulthan
    Jan 2 at 8:08











  • @Sulthan Thanks for pointing it out, I made the change but still the function call goes to the Swift.print function

    – Md. Ibrahim Hassan
    Jan 2 at 16:17
















0












0








0







Adding to the comments by Alexander and Carpsen90



Method Swizzling is an Objective-C runtime feature and it is inherently not available in Swift as Swift is not a dynamic language. However, you can have a global function as in this SO Post. Below is the updated code for Swift 4.2.
But unfortunately, it calls the original Swift.print function if the function name is print. So I changed the function name to logs



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


Another Possible option is to put it into a protocol



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

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


Usage



class SampleClass : CustomPrintable {

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


But this way the function ceases to be a global function and while using print you have to select the correct methodenter image description here



Output



*****Hello World





share|improve this answer















Adding to the comments by Alexander and Carpsen90



Method Swizzling is an Objective-C runtime feature and it is inherently not available in Swift as Swift is not a dynamic language. However, you can have a global function as in this SO Post. Below is the updated code for Swift 4.2.
But unfortunately, it calls the original Swift.print function if the function name is print. So I changed the function name to logs



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


Another Possible option is to put it into a protocol



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

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


Usage



class SampleClass : CustomPrintable {

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


But this way the function ceases to be a global function and while using print you have to select the correct methodenter image description here



Output



*****Hello World






share|improve this answer














share|improve this answer



share|improve this answer








edited Jan 1 at 20:59









Tal Zion

3,0812244




3,0812244










answered Jan 1 at 16:18









Md. Ibrahim HassanMd. Ibrahim Hassan

3,60211130




3,60211130








  • 1





    You didn't have correct external parameter names. It would have to be print(_ items: ...) not print(items: ...). That's why your method did not get called.

    – Sulthan
    Jan 2 at 8:08











  • @Sulthan Thanks for pointing it out, I made the change but still the function call goes to the Swift.print function

    – Md. Ibrahim Hassan
    Jan 2 at 16:17
















  • 1





    You didn't have correct external parameter names. It would have to be print(_ items: ...) not print(items: ...). That's why your method did not get called.

    – Sulthan
    Jan 2 at 8:08











  • @Sulthan Thanks for pointing it out, I made the change but still the function call goes to the Swift.print function

    – Md. Ibrahim Hassan
    Jan 2 at 16:17










1




1





You didn't have correct external parameter names. It would have to be print(_ items: ...) not print(items: ...). That's why your method did not get called.

– Sulthan
Jan 2 at 8:08





You didn't have correct external parameter names. It would have to be print(_ items: ...) not print(items: ...). That's why your method did not get called.

– Sulthan
Jan 2 at 8:08













@Sulthan Thanks for pointing it out, I made the change but still the function call goes to the Swift.print function

– Md. Ibrahim Hassan
Jan 2 at 16:17







@Sulthan Thanks for pointing it out, I made the change but still the function call goes to the Swift.print function

– Md. Ibrahim Hassan
Jan 2 at 16:17




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53993673%2fhow-to-swizzle-swift-printitemsseparatorterminator%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Monofisismo

Angular Downloading a file using contenturl with Basic Authentication

Olmecas