是否有一种方法可以确定一个方法需要执行多少时间(以毫秒为单位)?
当前回答
对于Swift 4,添加一个委托到你的类:
public protocol TimingDelegate: class {
var _TICK: Date?{ get set }
}
extension TimingDelegate {
var TICK: Date {
_TICK = Date()
return(_TICK)!
}
func TOCK(message: String) {
if (_TICK == nil){
print("Call 'TICK' first!")
}
if (message == ""){
print("\(Date().timeIntervalSince(_TICK!))")
}
else{
print("\(message): \(Date().timeIntervalSince(_TICK!))")
}
}
}
加入我们班:
class MyViewcontroller: UIViewController, TimingDelegate
然后添加到你的类:
var _TICK: Date?
当你想为某事计时时,可以从以下开始:
TICK
最后:
TOCK("Timing the XXX routine")
其他回答
NSDate *methodStart = [NSDate date];
/* ... Do whatever you need to do ... */
NSDate *methodFinish = [NSDate date];
NSTimeInterval executionTime = [methodFinish timeIntervalSinceDate:methodStart];
NSLog(@"executionTime = %f", executionTime);
迅速:
let methodStart = NSDate()
/* ... Do whatever you need to do ... */
let methodFinish = NSDate()
let executionTime = methodFinish.timeIntervalSinceDate(methodStart)
print("Execution time: \(executionTime)")
Swift3:
let methodStart = Date()
/* ... Do whatever you need to do ... */
let methodFinish = Date()
let executionTime = methodFinish.timeIntervalSince(methodStart)
print("Execution time: \(executionTime)")
易于使用,具有亚毫秒精度。
我使用非常少的,一页的类实现,灵感来自这篇博客文章的代码:
#import <mach/mach_time.h>
@interface DBGStopwatch : NSObject
+ (void)start:(NSString *)name;
+ (void)stop:(NSString *)name;
@end
@implementation DBGStopwatch
+ (NSMutableDictionary *)watches {
static NSMutableDictionary *Watches = nil;
static dispatch_once_t OnceToken;
dispatch_once(&OnceToken, ^{
Watches = @{}.mutableCopy;
});
return Watches;
}
+ (double)secondsFromMachTime:(uint64_t)time {
mach_timebase_info_data_t timebase;
mach_timebase_info(&timebase);
return (double)time * (double)timebase.numer /
(double)timebase.denom / 1e9;
}
+ (void)start:(NSString *)name {
uint64_t begin = mach_absolute_time();
self.watches[name] = @(begin);
}
+ (void)stop:(NSString *)name {
uint64_t end = mach_absolute_time();
uint64_t begin = [self.watches[name] unsignedLongLongValue];
DDLogInfo(@"Time taken for %@ %g s",
name, [self secondsFromMachTime:(end - begin)]);
[self.watches removeObjectForKey:name];
}
@end
它的用法很简单:
调用[DBGStopwatch start:@"slow-operation"];一开始 然后[DBGStopwatch stop:@"slow-operation"];做完之后,才能得到时间
下面是我使用的两个单行宏:
#define TICK NSDate *startTime = [NSDate date]
#define TOCK NSLog(@"Time: %f", -[startTime timeIntervalSinceNow])
像这样使用它:
TICK;
/* ... Do Some Work Here ... */
TOCK;
我在我的utils库中使用这个(Swift 4.2):
public class PrintTimer {
let start = Date()
let name: String
public init(file: String=#file, line: Int=#line, function: String=#function, name: String?=nil) {
let file = file.split(separator: "/").last!
self.name = name ?? "\(file):\(line) - \(function)"
}
public func done() {
let end = Date()
print("\(self.name) took \((end.timeIntervalSinceReferenceDate - self.start.timeIntervalSinceReferenceDate).roundToSigFigs(5)) s.")
}
}
…然后调用如下方法:
func myFunctionCall() {
let timer = PrintTimer()
// ...
timer.done()
}
…运行后在控制台中看起来是这样的:
MyFile.swift:225 - myFunctionCall() took 1.8623 s.
虽然不像上面的TICK/TOCK那样简洁,但它足以清楚地看到它在做什么,并自动包括正在计时的内容(通过文件、方法开头的行和函数名)。显然,如果我想要更多的细节(例如,如果我不只是计时一个方法调用,因为是通常的情况下,而是在该方法内计时块),我可以在PrintTimer init上添加“name="Foo""参数来命名它除了默认值之外的东西。
这里有另一种方法,在Swift中,使用defer关键字来做到这一点
func methodName() {
let methodStart = Date()
defer {
let executionTime = Date().timeIntervalSince(methodStart)
print("Execution time: \(executionTime)")
}
// do your stuff here
}
来自苹果的文档:defer语句用于在将程序控制权转移到该defer语句出现的范围之外之前执行代码。
这类似于try/finally块,优点是将相关代码分组。
推荐文章
- 如何删除默认的导航栏空间在SwiftUI导航视图
- 如何在iOS中使用Swift编程segue
- Swift -整数转换为小时/分钟/秒
- Swift:声明一个空字典
- 为什么ARC仍然需要@autoreleasepool ?
- 检测浏览器标签是否有焦点
- 在成功提交我的应用程序后,“太多符号文件”
- 首先添加一个UIView,甚至是导航栏
- 就性能而言,使用std::memcpy()还是std::copy()更好?
- 我如何改变UIButton标题颜色?
- 在Swift中如何调用GCD主线程上的参数方法?
- NSLayoutConstraints是可动画的吗?
- iOS -构建失败,CocoaPods无法找到头文件
- Xcode 4挂在“附加到(应用程序名称)”
- CFNetwork SSLHandshake iOS 9失败