ChatGPT解决这个技术问题 Extra ChatGPT

Swift: #warning equivalent

Does Swift have a #warning equivalent? It's simply used to show a warning in Xcode's own GUI

I'm also interested in whether there's a #error equivalent.

Apple has said #pragma mark is coming soon, it could possibly be the same with this.

https://i.stack.imgur.com/0a7FV.png

I assume it will be //WARNING just like #pragma will be //MARK but currently neither of them are added to XCode beta.
I would highly suggest filing a radar to ask for //WARNING
@pixel I've just filed a radar
Can you accept Jordan Smith's answer? This is now built into Swift as #warning

J
Jordan Smith

Edit

As of Swift 4.2, language level support is available for both build warnings and errors.

#warning("Warning description")
#error("Throws a build error")

Original Answer

Quick, dirty, and oh so elegantly simple all at the same time.

// Description of what you need to fix

var FIX_ME__🛠🛠🛠: AnyObject

Throws a warning that 'FIX_ME__🛠🛠🛠' was never used.

You can add emoticons to the variable name if you like... I often use 😱 and 🛠, for something that really needs fixing I'd even consider 💩. You can replace FIX_ME__ with whatever you want: ALGORITHM_NEEDS_REVIEW, BugID_148, or JOHNNY_YOU_BROKE_THIS are some examples.

Quick, no setup, concise, and emoticons can even add humour/personality to your code. Sometimes the most simple solution is the best solution.


...Why all the down votes? This works just as well as any other method here. If you're down voting, at least give a reason, maybe I wasn't clear enough, or there's something wrong with what I'm doing. I'd love to know if there is.
Yeah, I'm not sure why this isn't upvoted more. All of the other solutions are way too complicated.
@ZaEeMZaFaR the compiler would very likely get rid of it. Besides, in most cases these issues will be fixed before release. And - even if for whatever reason, the compiler isn't smart enough to get rid of it (I think this is very unlikely) - 100 Int vars in memory is 6.4kb of memory - basically nothing. I don't think you've got a valid point sorry.
I used the others but switched over to using this one. It's the simplest and you can even give yourself a little message that will show up in the warning, i.e.: let fixMeMakeMeNonOptional: Int gives you Immutable value fixMeMakeMeNonOptional was never used; consider replacing with _ or removing it in the issue navigator. All the other solutions give you much more generic error messages.
@NathanPerry yeah, agreed. Setting up some complex thing isn't always an option, especially when you work in a team or on multiple projects etc. Plus, simple solutions are always the best. I currently just put the message beside it in a comment, but what you do isn't a bad idea either.
K
Kyle G

In the future, Apple devs may very well release a //WARNING: landmark, or provide the functionality for another named landmark.

To envoke this functionality with Swift in Xcode today however, you could do the following as outlined by Ben Dodson & Jeffrey Sambells:

Add a new Run Script to your target's build phases tab (project settings > build phases > '+' > new run script phase), and paste the following code in the empty box:

TAGS="TODO:|FIXME:"
echo "searching ${SRCROOT} for ${TAGS}"
find "${SRCROOT}" \( -name "*.swift" \) -print0 | xargs -0 egrep --with-filename --line-number --only-matching "($TAGS).*\$" | perl -p -e "s/($TAGS)/ warning: \$1/"

This will force Xcode to flag a warning at compile time for any // TODO: or // FIXME: comments you markup.

Alternatively, you could amend TAGS with a custom tag: TAGS="WARNING:" in the above code which would keep the default behaviour for TODO & FIXME and would raise a compile time warning on any comments marked-up as // WARNING:.

http://bendodson.com/weblog/2014/10/02/showing-todo-as-warning-in-swift-xcode-project/ http://jeffreysambells.com/2013/01/31/generate-xcode-warnings-from-todo-comments

EDIT: 18/11/14

@david-h raised a good point in his comment. If you wanted to only raise these warnings in a specific build configuration, you could do the following:

if [ "${CONFIGURATION}" = "Debug" ]; then
TAGS="TODO:|FIXME:"
echo "searching ${SRCROOT} for ${TAGS}"
find "${SRCROOT}" \( -name "*.swift" \) -print0 | xargs -0 egrep --with-filename --line-number --only-matching "($TAGS).*\$" | perl -p -e "s/($TAGS)/ warning: \$1/"
fi

Alternatively, you could use "Release" rather than "Debug" to target production builds only.


This is a very nice temporary solution until Apple fixes it :)
The problem with this is that my app has two modes - development and production. I want to know that it builds clean in production, but I get a warning in development that essentially reminds me I'm in dev mode - using different URLs, timeouts, other settings etc. Arie's suggestion above lets me do this, your technique just flags everything. That said, this technique has its use for sure so I up voted it too!
What a useful idea! Thank you for sharing this useful information.
@kyle Could you please let me know the meaning of perl -p -e "s/($TAGS)/ warning: \$1/" this line
Works great, however I had to add the -type f option to the find command to exclude directories from the find results. This shouldn't be a problem for most people, but anyone who uses the R.swift pod will run into the same error I had because R.swift is a directory
J
Jeehut

Post WWDC 2018 Update

Starting with Xcode 10 and Swift 4.2 you will now be able to use #warning again like so:

#warning("TODO: Clean up this code after testing")

This will show up as a warning in Xcode just as expected!

This works even in combination with #if checks, for example the following will only show a warning if your target platform is iOS:

#if os(iOS)
    #warning("this code is untested in iOS")
#endif

There's also #error if you want your build to fail.

Pre WWDC 2018 Answer

In Swift using XCode 6 you can use different kinds of landmarks for different purposes. Here's what Apple says about it:

Xcode now supports //MARK:, //TODO: and //FIXME: landmarks to annotate your code and lists them in the jump bar.

So for setting a warning with a description you would use something like this:

//TODO: Clean up this code after testing

If you just want to set a short mark (assuming you will remember what to do), use this:

//FIXME

EDIT: These landmarks however only appear in the jump bar of XCode which might not be what you wish for and what one would expect – especially from the //TODO: and //FIXME marks. I've filed a radar on that: #17776817. Hopefully Apple will add this in the coming builds in XCode 6.

SOLUTION (EDIT 2): If you install the Swift Linter via Homebrew (run brew install swiftlint after a brew update) and add the suggested build script to your project, then you will see all your TODO and FIXME landmarks appear as warnings within Xcode. SwiftLint will even add some more warnings/errors that you can configure to fit your needs – I can only recommend using SwiftLint and it solves this problem in a great way!


Unfortunately these don't show up in the warnings panel when you compile your app. I'm still waiting for one that sticks out like a sore thumb so you aren't likely to forget about them. These just show up in the jumpbar and you would need to remember to search your project for "//TODO" to find it. Or if anybody knows how to see them for the entire project, let me know. - time for another Radar :)
Uh yeah, you're right. I thought the jump bar is the side bar on the left and that those marks would appear on the Issue Navigator, but they don't. I've just filed a radar on that: #17776817. :)
@SomeGuy What do you mean by they show up in the jumpbar? From what I can see they are no where on the bar that is located at the top of the editor window in Xcode. The only way to notice them (to me) seems to be to search for them with Command + F. Where are the landmarks shown?
@almel The jumpbar is the drop down at the top of a file, it gives a list of functions in current file i.cubeupload.com/jLRwTs.png
i
interrupt

Still not added by Apple team yet. What I decided to do is probably a cheating, but at least it does show me a FIXME message. So what I do is declare FIXME() function in Swift file:

@availability(iOS, deprecated=1.0, message="I'm not deprecated, please ***FIXME**")
func FIXME()
{
}

and when I call it from any other function it does show a warning, e.g.

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
    FIXME()     // Incomplete method implementation.
    return 0
}

https://i.stack.imgur.com/fCV1p.png

For Swift 2 use

@available(iOS, deprecated=1.0, message="I'm not deprecated, please ***FIXME**")

Just for the record: @availability has been renamed to "@available" in swift 2.
k
kelin

Look at this article.

You can write your own script which will highlight all tags.

TAGS="TODO:|FIXME:"
ERRORTAG="ERROR:"
find "${SRCROOT}" \( -name "*.h" -or -name "*.m" -or -name "*.swift" \) -print0 | xargs -0 egrep --with-filename --line-number --only-matching "($TAGS).*\$|($ERRORTAG).*\$" | perl -p -e "s/($TAGS)/ warning: \$1/" | perl -p -e "s/($ERRORTAG)/ error: \$1/"

https://i.stack.imgur.com/a5OVk.png


Add egrep --directories='skip' to ignore directories with names like Device.swift
A
Arie Litovsky

As an alternative, if you want something to show up in the warnings panel, you could write something like:

if (false){
   var x = 2;
}

You can't really get any text to show up, but at least it's a more visible marker, especially if you tend to treat (most) warnings like errors.


Or just do if false {"the warning message"}
This solution is terrible. But seems to be the best available. Voted up, thanks.
H
Harlan Haskins

I proposed and implemented this feature, and it will ship with Swift 4.2. You can use it now by download the master toolchain on swift.org.

#if os(macOS)
  #error("macOS is not supported")
#endif
#warning("finish this")

j
jscs

One CocoaPod that I was using had .swift in its name, so a directory was returned, which caused the script by Kyle to crash. Adding -type f to the find command fixes that problem by only looking at files that match *.swift instead of also returning directories that match the pattern.

Final code that I used:

TAGS="TODO:|FIXME:"
echo "searching ${SRCROOT} for ${TAGS}"
find "${SRCROOT}" \( -name "*.swift" \) -type f -print0 | xargs -0 egrep --with-filename --line-number --only-matching "($TAGS).*\$" | perl -p -e "s/($TAGS)/ warning: \$1/"

Is there a way to not have the compiler complain? I get "Command /bin/sh emitted errors but did not return a nonzero exit code to indicate failure"
As an alternative see this comment above
M
Minh Nguyễn

If you’re loath to adjust your build setup, another simple home remedy is to stick an editor placeholder in front of the comment:

<#todo#>// stop and fixme!

You get an “Editor placeholder in source file” error when you build, but unlike Jordan’s solution, there’s no live error to annoy you while typing:

https://i.stack.imgur.com/QYltE.png


Nice idea - but isn't the idea to throw a warning, and not an error? Doing this won't let you build until you remove it, which, in many (most?) cases is definitely not what you want. Todo and fixme marks sometimes involve weeks worth of work - I'd imagine you'd want to build and run your project during this time :)
Sure, that’s a good point. This approach is only useful for more urgent to-do items that have to happen before committing or even running the application. The main benefit is that syntax highlighting and other editor niceties continue to work despite the presence of this placeholder. I use some of the other approaches here myself, including yours, but the placeholders are sometimes helpful when multitasking. It fits the same use cases as the placeholders Xcode inserts when autocompleting a function call.
r
rcw3

After much searching and longing, I'm convinced no such entity exists. I'm still hopeful with the latest Xcode release notes mentioning the continued lack of a #pragma mark mechanism, #warning and #error may also be coming as well.

As an aside, I highly recommend filing a Radar with Apple at bugreport.apple.com to add this functionality (you can dupe 17702491).


I did my part: rdar://19005171
Also filled in a radar
s
soolwan

We wrote a configurable tool that lets you put warnings and errors in Xcode Issue Navigator based on comment tag and build configuration: https://github.com/doubleencore/XcodeIssueGenerator

Install it:

brew tap doubleencore/tap
brew install xcodeissuegenerator

Then put a line in a Run Script Build Phase:

# Mark WARNINGs, SERIOUSs, and TODOs as warnings in DEBUG builds excluding the Vendor and Third Party directories.
XcodeIssueGenerator -b DEBUG -w "WARNING, SERIOUS, TODO" -x "Vendor/, Third Party/"

Here's an article describing how we use it.


N
Nikolay Shubenkov

My answer is not quite satisfy your question, but if you want something easy you can use this plugin of alcatraz which works in all the projects without any additional preparations. Just do the following:

1) install Alcatraz (Nice package manager for Xcode Plug-ins) by entering this line in terminal: 
curl -fsSL https://raw.githubusercontent.com/supermarin/Alcatraz/deploy/Scripts/install.sh | sh
2) Then restart Xcode and on it launch agree to install all bundles not included in Xcode
3) In Xcode select menu item -> Window -> Package manager -> type in search panel XTodo and press install
4) Relaunch Xcode and again agree to install additional bundles
5) From now press Ctrl + T and you will see all Tags in nice window

It also has preferences for adding new tags

https://i.stack.imgur.com/VULQl.png


I
Igor

Advantage of this snippet - it doesn't show warnings from Pods:

if [ "${CONFIGURATION}" = "DEBUG" ]; then 
    TAGS="TODO:|FIXME:|WARNING:|warning:" find "." \( -name "*.swift" \) -not -path "./Pods/*" -print0 | xargs -0 egrep --with-filename --line-number --only-matching "($TAGS).*\$" | perl -p -e "s/($TAGS)/ warning: \$1/"
fi

How to install:

https://i.stack.imgur.com/ztkcn.png


P
Przemysław Wrzesiński

I may be late to the party with Xcode 10 supporting errors and warnings, but simply putting a String:

"Need to finish implementing this"

will produce a warning: String literal is unused with autocompletion still working and the project still compiling.