Is there anyway to make log function? [duplicate] - swift

This question already has answers here:
Macros in Swift?
(8 answers)
Closed 6 years ago.
I want to print #file, #function and #line with one method.
I tried the below code but problem is here.
Wherever I call logm(), it always prints information of logm method itself even I declared it as #inline.
#inline(__always) func logm(items: Any...) {
if let f = #file.componentsSeparatedByString("/").last {
print("[\(f)][\(#function)][\(#line)]:", items)
} else {
print("[\(#function)][\(#line)]: ", items)
}
}
Is there anyway to implement this kind of thing? Why does #inline work as I expected?

You can pass the file, line, and function as parameters with the directives as default values:
func logm(items: Any..., file: String = #file, line: Int = #line, function: String = #function) {
if let f = file.componentsSeparatedByString("/").last {
print("[\(f)][\(function)][\(line)]:", items)
} else {
print("[\(function)][\(line)]: ", items)
}
}

Related

How to capture the return value of a closure

I know that closures capture the values in a given environment. That is not my question. My question is how do I capture the return value of a closure. For example if I use a closure as a parameter like:
func myClosure(yourAge x: Int, completion: (Int) -> String) {
if x == 4 {
completion(x)
}
}
then say:
let answer = myClosure(yourAge: 4) { x in
return "You're just a baby"
}
The warning is:
Constant 'answer' inferred to have type '()', which may be unexpected
And I understand that warning. Pretty much answer will not be an answer at all. It will be Void or ()
Now if I make the entire function return a String such as:
func myClosure(yourAge x: Int, completion: (Int) -> String) -> String {
completion(x)
}
Then I can of course capture the result in a property:
let answer = myClosure(yourAge: 4) { x in
if x < 10 { return "You're just a baby"}
else {
return "You can play the game"
}
}
And maybe I just answered my own question here but is there no simple way to place the return value of a closure into a property or I am using this in an unintended way?
If you wanted to do this purely with a closure (and not a function that accepts a closure), you could do something like:
let myClosure: (Int) -> String = { age in
if age < 10 {
return "You're just a baby"
}
else {
return "You can play the game"
}
}
let answer = myClosure(4) // "You're just a baby"

Any way to override the swift built in print function including constant variables? (#line, #function etc)

I want to be able to override the default Swift standard library print function and include the line number and function name. I have tried several methods such as
public func print(_ items: Any..., separator: String = \(#line), terminator: String = #function {
let output = items.map { "\(terminator) \(separator) -> \($0)" }.joined(separator: " ")
Swift.print(output, terminator: "\n")
}
This correctly prints out the function name of the calling method, however the line number is set to the line number of the print function. I therefore tried changing the separator type to Int and passing #line to it as its default value.
This results in an "ambiguous use of function" error, and changing the signature doesn't help either as the default implementation is called in preference to my function.
I have looked at extensions and even swizzling but neither of these seem fruitful in this instance.
So it seems that in my case a signature change does solve the issue. By being specific about the type passed to the items argument, my custom method is called.
public func print(_ items: String..., filename: String = #file, function : String = #function, line: Int = #line, separator: String = " ", terminator: String = "\n") {
let pretty = "\(URL(fileURLWithPath: filename).lastPathComponent) [#\(line)] \(function)\n\t-> "
let output = items.map { "\($0)" }.joined(separator: separator)
Swift.print(pretty+output, terminator: terminator)
}
Note that all the print statements I care about pass Strings. The default implementation is called otherwise:
print(1+1)
// 2
print("Hello, World!")
// ExampleVC.swift [#101] viewDidLoad()
// -> Hello, World!
print("Hello", "World", separator: ", ", terminator: "!\n")
// ExampleVC.swift [#101] viewDidLoad()
// -> Hello, World!

How do you split a string at every n-th character in Swift? [duplicate]

This question already has answers here:
How to split a string into substrings of equal length
(13 answers)
Closed 4 years ago.
Like the question says, if I have:
XQQ230IJFEKJLDSAIOUOIDSAUIFOPDSFE28
How can I split this string at every 8th character to get:
XQQ230IJ FEKJLDSA IOUOIDSA UIFOPDSA
Implement this function
extension String {
func inserting(separator: String, every n: Int) -> String {
var result: String = ""
let characters = Array(self.characters)
stride(from: 0, to: characters.count, by: n).forEach {
result += String(characters[$0..<min($0+n, characters.count)])
if $0+n < characters.count {
result += separator
}
}
return result
}
}
call it this way,
let str = "XQQ230IJFEKJLDSAIOUOIDSAUIFOPDSFE28"
let final = str.inserting(separator: " ", every: 8)
print(final)
Output will be like this,
XQQ230IJ FEKJLDSA IOUOIDSA UIFOPDSF E28
This will be generic solution if you want to add any character instead of space, it will work.

I want to pass some text into the textfield but something wrong....idk why print() is work [duplicate]

This question already has an answer here:
how can i put these print text into Textfield?
(1 answer)
Closed 5 years ago.
swift4 Xocode9
UNUserNotificationCenter.current().getPendingNotificationRequests {
DispatchQueue.main.async {
// Contextual closure type '() -> Void' expects 0 arguments,
// but 1 was used in closure body
let str:String = ""
self.finalresulter.text = str
self.finalresulter.text = "\($0.map{$0.content.title})"
}
print($0.map { $0.content.title},",",$0.map { $0.content.subtitle},","
,$0.map { $0.content.body},","
,$0.map { $0.trigger!})
}
please help...how to fix..
Try this:
notificatecontent.text = "\($0.map{$0.content.title})"
The issue appears to be identical to your other question. In order not to replicate existing answer I gave there, I would only mention the second part, which would look like:
UNUserNotificationCenter.current().getPendingNotificationRequests { requests in
// Textfield assignment here ...
print(requests.map { $0.content.title},",",requests.map { $0.content.subtitle},","
,requests.map { $0.content.body},","
,requests.map { $0.trigger!})
}
But, unless you explicitly want to print everything on one line, this print should be better replaced with regular for loop (or at least a forEach method):
// 1
for item in requests {
print(item.content.title, item.content.subtitle, item.content.body)
}
// 2
requests.forEach {
print($0.content.title, $0.content.subtitle, $0.content.body)
}

Why does my string cleanup function return the original value? [duplicate]

This question already has an answer here:
Can't replacing string with string
(1 answer)
Closed 7 years ago.
I have made a func so that I easily can make all letters of a string lower case, while also removing all ! and spaces. I made this func (outside of viewdidload)
func cleanLink(linkName: String) -> String {
linkName.stringByReplacingOccurrencesOfString("!", withString: "")
linkName.stringByReplacingOccurrencesOfString(" ", withString: "")
linkName.lowercaseString
return linkName
}
I then used these lines of codes
var theLinkName = cleanLink("AB C!")
print(theLinkName)
The problems is that this is just printing AB C! while I want it to print abc. What am I doing wrong?
The problem is that stringByReplacingOccurrencesOfString returns a new string; it does not perform the replacement in place.
You need to use the return value of the function instead, like this:
func cleanLink(linkName: String) -> String {
return linkName
.stringByReplacingOccurrencesOfString("!", withString: "")
.stringByReplacingOccurrencesOfString(" ", withString: "")
.lowercaseString
}
This "chains" the invocations of functions that produce new strings, and returns the final result of the replacement.