Поддерживает ли Swift в настоящее время макросы или планируют ли добавить поддержку? В настоящее время я рассеиваю:
Log.trace(nil, function: __FUNCTION__, file: __FILE__, line: __LINE__)
В разных местах моего кода.
Поддерживает ли Swift в настоящее время макросы или планируют ли добавить поддержку? В настоящее время я рассеиваю:
Log.trace(nil, function: __FUNCTION__, file: __FILE__, line: __LINE__)
В разных местах моего кода.
В этом случае вы должны добавить значение по умолчанию для параметров макроса.
Swift 2.2 и выше
func log(message: String,
function: String = #function,
file: String = #file,
line: Int = #line) {
print("Message \"\(message)\" (File: \(file), Function: \(function), Line: \(line))")
}
log("Some message")
Swift 2.1 и ниже
func log(message: String,
function: String = __FUNCTION__,
file: String = __FILE__,
line: Int = __LINE__) {
print("Message \"\(message)\" (File: \(file.lastPathComponent), Function: \(function), Line: \(line))")
}
log("Some message")
Это то, что делают функции fatalError
и assert
.
Нет других макросов, кроме условной компиляции, уже упомянутой в другом ответе.
Apple docs утверждают, что:
Объявить простые макросы как глобальные константы и перевести сложные макросы в функции.
Вы все еще можете использовать # if/# else/# endif, но я чувствую, что они не будут вводить макрофункции, язык просто не нужен.
Так как XCode 7.3, константы времени компиляции __FILE__
__FUNCTION__
и __LINE__
стали более привлекательными #file
#function
и #line
соответственно.
lastPathComponent
нужен NSURL
, поэтому я изменил код выше:
func log(message: String,
function: String = __FUNCTION__,
file: String = __FILE__,
line: Int = __LINE__) {
let url = NSURL(fileURLWithPath: file)
print("Message \"\(message)\" (File: \(url.lastPathComponent ?? "?"), Function: \(function), Line: \(line))")
}
log("some message")
Вот обновленный ответ Swift 2.
func LogW(msg:String, function: String = #function, file: String = #file, line: Int = #line){
print("[WARNING]\(makeTag(function, file: file, line: line)) : \(msg)")
}
private func makeTag(function: String, file: String, line: Int) -> String{
let url = NSURL(fileURLWithPath: file)
let className = url.lastPathComponent ?? file
return "\(className) \(function)[\(line)]"
}
Пример использования:
LogW("Socket connection error: \(error)")
Макросы являются злыми, но иногда они вам просто нужны. Например, у меня есть
struct RegionEntity {
var id: Int!
}
И я хочу поместить экземпляры этой структуры в Set. Поэтому я должен соответствовать этому протоколу Hashable.
extension RegionEntity: Hashable {
public var hashValue: Int {
return id
}
}
public func ==(first: RegionEntity, second: RegionEntity) -> Bool {
return first.id == second.id
}
Великий. Но что, если у меня есть десятки таких структур и логика одна и та же? Может быть, я могу объявить какой-то протокол и не согласую его с Hashable. Пусть проверьте:
protocol Indexable {
var id: Int! { get }
}
extension Indexable {
var hashValue: Int {
return id
}
}
func ==(first: Indexable, second: Indexable) -> Bool {
return first.id == second.id
}
Ну, это работает. И теперь я собираюсь привязать свою структуру к обоим протоколам:
struct RegionEntity: Indexable, Hashable {
var id: Int!
}
Неа. Я не могу этого сделать, потому что Equatable требует == operator с Self, а для RegionEntity нет оператора ==. Swift заставляет меня копировать код подтверждения для каждой структуры и просто менять имя. С помощью макроса я мог бы сделать это только с одной строкой.
Существует способ использования макросов в swift (но это используется в Mixed of c и swift)
объявить свои макросы в Project-name-Bridging-Header.h
#define YOUR_MACRO @"Description"
или создать отдельный файл заголовка для макросов "macros.h"
импортируйте этот заголовок "macros.h" в файл Bridging-Header.h.
теперь просто сохраните свой проект, ваши макросы попадут в быстрый файл.
если вы не хотите, чтобы объектный код c в вашем быстром проекте... просто создайте манекен cocoa сенсорные классы, он создаст заголовок моста, а затем воспользуется моим способом...