我在 Objective-C 中使用__DATE__
and__TIME__
来获取我的应用程序的构建日期和时间。我找不到在 Swift 中获取这些信息的方法。可能吗?
5 回答
您可以在不恢复到 Objective-C 的情况下获取构建日期和时间。构建应用程序时,放置在包中的 Info.plist 文件始终是从项目中的文件创建的。因此,该文件的创建日期与构建日期和时间相匹配。您始终可以读取应用程序包中的文件并获取它们的属性。因此,您可以通过访问其 Info.plist 文件属性来获取 Swift 中的构建日期:
var buildDate:NSDate
{
if let infoPath = NSBundle.mainBundle().pathForResource("Info.plist", ofType: nil),
let infoAttr = try? NSFileManager.defaultManager().attributesOfItemAtPath(infoPath),
let infoDate = infoAttr["NSFileCreationDate"] as? NSDate
{ return infoDate }
return NSDate()
}
注意:当我最初遇到此问题时,这是让我使用桥接头的帖子。从那以后我发现了这个“Swiftier”解决方案,所以我想我会分享它以供将来参考。
[编辑] 添加了 compileDate 变量以获取最新的编译日期,即使没有进行完整构建。这仅在开发过程中有意义,因为您将不得不进行完整构建才能在应用商店上发布应用程序,但它可能仍然有一些用处。它的工作方式相同,但使用包含实际代码的捆绑文件而不是 Info.plist 文件。
var compileDate:Date
{
let bundleName = Bundle.main.infoDictionary!["CFBundleName"] as? String ?? "Info.plist"
if let infoPath = Bundle.main.path(forResource: bundleName, ofType: nil),
let infoAttr = try? FileManager.default.attributesOfItem(atPath: infoPath),
let infoDate = infoAttr[FileAttributeKey.creationDate] as? Date
{ return infoDate }
return Date()
}
您可以使用#line
、#column
和#function
。
原答案:
在你的项目中创建一个新的 Objective-C 文件,当 Xcode 询问时,对创建桥接头说是。
在这个新的 Objective-C 文件中,添加以下.h
文件:
NSString *compileDate();
NSString *compileTime();
并在.m
实现这些功能:
NSString *compileDate() {
return [NSString stringWithUTF8String:__DATE__];
}
NSString *compileTime() {
return [NSString stringWithUTF8String:__TIME__];
}
现在转到桥接头并导入.h
我们创建的。
现在回到你的任何 Swift 文件:
println(compileDate() + ", " + compileTime())
Swift 5 版本的 Alain T 的回答:
var buildDate: Date {
if let infoPath = Bundle.main.path(forResource: "Info", ofType: "plist"),
let infoAttr = try? FileManager.default.attributesOfItem(atPath: infoPath),
let infoDate = infoAttr[.modificationDate] as? Date {
return infoDate
}
return Date()
}
与以前的答案略有不同,而是检查可执行文件的创建日期。这似乎也适用于 macOS(使用 Catalyst 应用程序测试)。
/// Returns the build date of the app.
public static var buildDate: Date
{
if let executablePath = Bundle.main.executablePath,
let attributes = try? FileManager.default.attributesOfItem(atPath: executablePath),
let date = attributes[.creationDate] as? Date
{
return date
}
return Date()
}
这里所有较旧的答案都不好,因为它们没有提供稳定可靠的方法来获取实际构建日期。例如,在应用程序中获取文件的文件日期并不好,因为文件日期可能会更改而不会使应用程序的代码签名无效。
Xcode将正式的构建日期添加到应用程序的 Info.plist 中——这是您应该使用的日期。
例如,使用这段代码(抱歉,它在 ObjC 中,但将其转录为 Swift 应该不会那么难):
+ (NSDate *)buildDate {
static NSDate *result = nil;
if (result == nil) {
NSDictionary *infoDictionary = NSBundle.mainBundle.infoDictionary;
NSString *s = [infoDictionary valueForKey:@"BuildDateString"];
NSISO8601DateFormatter *formatter = [[NSISO8601DateFormatter alloc] init];
NSDate *d = [formatter dateFromString:s];
result = d;
}
return result;
}
这是您必须从项目的构建阶段运行的脚本,以便将其添加BuildDateString
到您的Info.plist
:
#!/bin/sh
infoplist="$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH"
builddate=`date +%Y-%m-%dT%H:%M:%S%z`
if [[ -n "$builddate" ]]; then
# if BuildDateString doesn't exist, add it
/usr/libexec/PlistBuddy -c "Add :BuildDateString string $builddate" "${infoplist}"
# and if BuildDateString already existed, update it
/usr/libexec/PlistBuddy -c "Set :BuildDateString $builddate" "${infoplist}"
fi