Skip to content

Commit 9e77297

Browse files
committed
添加 RRFPSBar
1 parent 8cb7eaa commit 9e77297

4 files changed

Lines changed: 284 additions & 1 deletion

File tree

Coding_iOS.xcodeproj/project.pbxproj

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@
200200
4E5C06E81AC2B34800F427C5 /* tipIcon_BranchMember@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4E5C06E71AC2B34800F427C5 /* tipIcon_BranchMember@2x.png */; };
201201
4E5C06EB1AC4009100F427C5 /* CannotLoginViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E5C06EA1AC4009100F427C5 /* CannotLoginViewController.m */; };
202202
4E5C06EE1AC4405300F427C5 /* PasswordViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E5C06ED1AC4405300F427C5 /* PasswordViewController.m */; };
203+
4E5D12FE1C0C5EE600985AEB /* RRFPSBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E5D12FD1C0C5EE600985AEB /* RRFPSBar.m */; };
203204
4E5F39021AC951060010515D /* TaskCommentCCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E5F39011AC951060010515D /* TaskCommentCCell.m */; };
204205
4E5F39051ACA958C0010515D /* TopicCommentCCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E5F39041ACA958C0010515D /* TopicCommentCCell.m */; };
205206
4E5F39071ACBFDCD0010515D /* keyboard_photo@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4E5F39061ACBFDCD0010515D /* keyboard_photo@2x.png */; };
@@ -1224,6 +1225,8 @@
12241225
4E5C06EA1AC4009100F427C5 /* CannotLoginViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CannotLoginViewController.m; sourceTree = "<group>"; };
12251226
4E5C06EC1AC4405300F427C5 /* PasswordViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PasswordViewController.h; sourceTree = "<group>"; };
12261227
4E5C06ED1AC4405300F427C5 /* PasswordViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PasswordViewController.m; sourceTree = "<group>"; };
1228+
4E5D12FC1C0C5EE600985AEB /* RRFPSBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RRFPSBar.h; sourceTree = "<group>"; };
1229+
4E5D12FD1C0C5EE600985AEB /* RRFPSBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RRFPSBar.m; sourceTree = "<group>"; };
12271230
4E5F39001AC951060010515D /* TaskCommentCCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TaskCommentCCell.h; sourceTree = "<group>"; };
12281231
4E5F39011AC951060010515D /* TaskCommentCCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TaskCommentCCell.m; sourceTree = "<group>"; };
12291232
4E5F39031ACA958C0010515D /* TopicCommentCCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TopicCommentCCell.h; sourceTree = "<group>"; };
@@ -2612,6 +2615,15 @@
26122615
path = RKSwipeBetweenViewControllers;
26132616
sourceTree = "<group>";
26142617
};
2618+
4E5D12FB1C0C5EE600985AEB /* RRFPSBar */ = {
2619+
isa = PBXGroup;
2620+
children = (
2621+
4E5D12FC1C0C5EE600985AEB /* RRFPSBar.h */,
2622+
4E5D12FD1C0C5EE600985AEB /* RRFPSBar.m */,
2623+
);
2624+
path = RRFPSBar;
2625+
sourceTree = "<group>";
2626+
};
26152627
4E6383991B3262D300D98648 /* task */ = {
26162628
isa = PBXGroup;
26172629
children = (
@@ -4361,6 +4373,7 @@
43614373
8EA6D03E19E240C40076D59C /* Vendor */ = {
43624374
isa = PBXGroup;
43634375
children = (
4376+
4E5D12FB1C0C5EE600985AEB /* RRFPSBar */,
43644377
4EE956521B9C1C500009EDA9 /* UMSocial_Sdk_4.3.0_Extra */,
43654378
4E93F2301B84243D00017916 /* KxMenu */,
43664379
4E0022971B735075005308DE /* EAIntroView */,
@@ -5620,6 +5633,7 @@
56205633
8EA6D1F619E240C40076D59C /* MJPhoto.m in Sources */,
56215634
8EF643CB19FF7E2900F7EEB0 /* TweetCell.m in Sources */,
56225635
4ECE8ADF1A3943E80021E29C /* UIBarButtonItem+Common.m in Sources */,
5636+
4E5D12FE1C0C5EE600985AEB /* RRFPSBar.m in Sources */,
56235637
4E996BD01ABA774800C704F1 /* EaseUserHeaderView.m in Sources */,
56245638
4E0022921B721973005308DE /* PointRecordCell.m in Sources */,
56255639
4E5A66951B268D160007A0AD /* UIView+PressMenu.m in Sources */,

Coding_iOS/AppDelegate.m

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
#if DEBUG
1414
#import <FLEX/FLEXManager.h>
15-
15+
#import "RRFPSBar.h"
1616
#endif
1717

1818
#import "AppDelegate.h"
@@ -109,6 +109,11 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
109109
[self completionStartAnimationWithOptions:launchOptions];
110110
}];
111111

112+
#if DEBUG
113+
[[RRFPSBar sharedInstance] setShowsAverage:YES];
114+
[[RRFPSBar sharedInstance] setHidden:NO];
115+
#endif
116+
112117
return YES;
113118
}
114119

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//
2+
// RRFPSBar.h
3+
//
4+
// Created by Rolandas Razma on 07/03/2013.
5+
// Copyright 2013 Rolandas Razma. All rights reserved.
6+
//
7+
// Permission is hereby granted, free of charge, to any person
8+
// obtaining a copy of this software and associated documentation
9+
// files (the "Software"), to deal in the Software without
10+
// restriction, including without limitation the rights to use,
11+
// copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
// copies of the Software, and to permit persons to whom the
13+
// Software is furnished to do so, subject to the following
14+
// conditions:
15+
//
16+
// The above copyright notice and this permission notice shall be
17+
// included in all copies or substantial portions of the Software.
18+
//
19+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21+
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23+
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24+
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25+
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26+
// OTHER DEALINGS IN THE SOFTWARE.
27+
//
28+
29+
#import <UIKit/UIKit.h>
30+
31+
32+
@interface RRFPSBar : UIWindow
33+
@property (nonatomic, readwrite) NSTimeInterval desiredChartUpdateInterval;
34+
35+
//default is no
36+
@property (nonatomic, readwrite) BOOL showsAverage;
37+
38+
+ (RRFPSBar *)sharedInstance;
39+
40+
@end
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
//
2+
// RRFPSBar.m
3+
//
4+
// Created by Rolandas Razma on 07/03/2013.
5+
// Copyright 2013 Rolandas Razma. All rights reserved.
6+
//
7+
// Permission is hereby granted, free of charge, to any person
8+
// obtaining a copy of this software and associated documentation
9+
// files (the "Software"), to deal in the Software without
10+
// restriction, including without limitation the rights to use,
11+
// copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
// copies of the Software, and to permit persons to whom the
13+
// Software is furnished to do so, subject to the following
14+
// conditions:
15+
//
16+
// The above copyright notice and this permission notice shall be
17+
// included in all copies or substantial portions of the Software.
18+
//
19+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21+
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23+
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24+
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25+
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26+
// OTHER DEALINGS IN THE SOFTWARE.
27+
//
28+
29+
30+
#import "RRFPSBar.h"
31+
#import <QuartzCore/QuartzCore.h>
32+
33+
34+
@implementation RRFPSBar {
35+
CADisplayLink *_displayLink;
36+
NSUInteger _historyDTLength;
37+
NSUInteger _maxHistoryDTLength;
38+
CFTimeInterval *_historyDT;
39+
CFTimeInterval _displayLinkTickTimeLast;
40+
CFTimeInterval _lastUIUpdateTime;
41+
42+
CATextLayer *_fpsTextLayer;
43+
CAShapeLayer *_linesLayer;
44+
CAShapeLayer *_chartLayer;
45+
46+
BOOL _showsAverage;
47+
}
48+
49+
50+
#pragma mark -
51+
#pragma mark NSObject
52+
53+
54+
- (void)dealloc {
55+
[_displayLink setPaused:YES];
56+
[_displayLink removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
57+
free(_historyDT);
58+
}
59+
60+
61+
- (id)init {
62+
if( (self = [super initWithFrame:[[UIApplication sharedApplication] statusBarFrame]]) ){
63+
64+
_maxHistoryDTLength = (NSInteger)CGRectGetWidth(self.bounds);
65+
_historyDT = malloc(sizeof(CFTimeInterval) * _maxHistoryDTLength);
66+
_historyDTLength = 0;
67+
_displayLinkTickTimeLast= CACurrentMediaTime();
68+
69+
[self setWindowLevel: UIWindowLevelStatusBar +1.0f];
70+
[self setBackgroundColor:[UIColor clearColor]];
71+
72+
[[NSNotificationCenter defaultCenter] addObserver: self
73+
selector: @selector(applicationDidBecomeActiveNotification)
74+
name: UIApplicationDidBecomeActiveNotification
75+
object: nil];
76+
77+
[[NSNotificationCenter defaultCenter] addObserver: self
78+
selector: @selector(applicationWillResignActiveNotification)
79+
name: UIApplicationWillResignActiveNotification
80+
object: nil];
81+
82+
// Track FPS using display link
83+
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkTick)];
84+
[_displayLink setPaused:YES];
85+
[_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
86+
87+
// Lines Layer
88+
_linesLayer = [CAShapeLayer layer];
89+
[_linesLayer setFrame: self.bounds];
90+
[_linesLayer setStrokeColor:[UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:0.5f].CGColor];
91+
[_linesLayer setContentsScale: [UIScreen mainScreen].scale];
92+
93+
UIBezierPath *path = [UIBezierPath bezierPath];
94+
[path moveToPoint:CGPointMake(0.0f, self.frame.size.height)];
95+
[path addLineToPoint:CGPointMake(self.frame.size.width, self.frame.size.height)];
96+
[path closePath];
97+
98+
[_linesLayer setPath:path.CGPath];
99+
100+
[self.layer addSublayer:_linesLayer];
101+
102+
// Chart Layer
103+
_chartLayer = [CAShapeLayer layer];
104+
[_chartLayer setFrame: self.bounds];
105+
[_chartLayer setStrokeColor: [UIColor redColor].CGColor];
106+
[_chartLayer setContentsScale: [UIScreen mainScreen].scale];
107+
[self.layer addSublayer:_chartLayer];
108+
109+
// Info Layer
110+
_fpsTextLayer = [CATextLayer layer];
111+
[_fpsTextLayer setFrame: CGRectMake(CGRectGetWidth(self.bounds) - 120, 0, 120.0f, self.bounds.size.height)];
112+
[_fpsTextLayer setFont:CGFontCreateWithFontName((CFStringRef)[UIFont boldSystemFontOfSize:12].fontName)];
113+
[_fpsTextLayer setFontSize: 12.0f];
114+
[_fpsTextLayer setForegroundColor: [UIColor redColor].CGColor];
115+
[_fpsTextLayer setAlignmentMode:kCAAlignmentCenter];
116+
117+
[_fpsTextLayer setBackgroundColor:[UIColor colorWithWhite:0 alpha:0.5].CGColor];
118+
[_fpsTextLayer setContentsScale: [UIScreen mainScreen].scale];
119+
[self.layer addSublayer:_fpsTextLayer];
120+
121+
// Draw asynchronously on iOS6+
122+
if( [_chartLayer respondsToSelector:@selector(setDrawsAsynchronously:)] ){
123+
[_linesLayer setDrawsAsynchronously:YES];
124+
[_chartLayer setDrawsAsynchronously:YES];
125+
[_fpsTextLayer setDrawsAsynchronously:YES];
126+
}
127+
128+
[self setDesiredChartUpdateInterval: 1.0f /60.0f];
129+
}
130+
return self;
131+
}
132+
133+
134+
#pragma mark -
135+
#pragma mark RRFPSBar
136+
137+
138+
+ (RRFPSBar *)sharedInstance {
139+
static RRFPSBar *_sharedInstance;
140+
static dispatch_once_t onceToken;
141+
dispatch_once(&onceToken, ^{
142+
_sharedInstance = [[RRFPSBar alloc] init];
143+
if([[UIDevice currentDevice].systemVersion floatValue] >= 9.0)
144+
_sharedInstance.rootViewController = [UIViewController new]; // iOS 9 requires rootViewController for any window
145+
});
146+
return _sharedInstance;
147+
}
148+
149+
150+
- (void)applicationDidBecomeActiveNotification {
151+
[_displayLink setPaused:NO];
152+
}
153+
154+
155+
- (void)applicationWillResignActiveNotification {
156+
[_displayLink setPaused:YES];
157+
}
158+
159+
160+
- (void)displayLinkTick {
161+
162+
// Shift up the buffer
163+
for (NSUInteger i = _historyDTLength; i >= 1; i-- ) {
164+
_historyDT[i] = _historyDT[i -1];
165+
}
166+
167+
// Store new state
168+
_historyDT[0] = _displayLink.timestamp -_displayLinkTickTimeLast;
169+
170+
// Update length if there is more place
171+
if ( _historyDTLength < _maxHistoryDTLength - 1) _historyDTLength++;
172+
173+
// Store last timestamp
174+
_displayLinkTickTimeLast = _displayLink.timestamp;
175+
176+
// Update UI
177+
CFTimeInterval timeSinceLastUIUpdate = _displayLinkTickTimeLast -_lastUIUpdateTime;
178+
if( _historyDT[0] < 0.1f && timeSinceLastUIUpdate >= _desiredChartUpdateInterval ){
179+
[self updateChartAndText];
180+
}
181+
}
182+
183+
184+
- (void)updateChartAndText {
185+
186+
UIBezierPath *path = [UIBezierPath bezierPath];
187+
[path moveToPoint:CGPointZero];
188+
189+
CFTimeInterval maxDT = CGFLOAT_MIN;
190+
CFTimeInterval avgDT = 0.0f;
191+
192+
for( NSUInteger i=0; i<=_historyDTLength; i++ ){
193+
maxDT = MAX(maxDT, _historyDT[i]);
194+
avgDT += _historyDT[i];
195+
196+
CGFloat fraction = roundf(1.0f /(float)_historyDT[i]) /60.0f;
197+
CGFloat y = _chartLayer.frame.size.height -_chartLayer.frame.size.height *fraction;
198+
y = MAX(0.0f, MIN(_chartLayer.frame.size.height, y));
199+
200+
[path addLineToPoint:CGPointMake(i +1.0f, y)];
201+
}
202+
203+
[path addLineToPoint:CGPointMake(_historyDTLength, 0)];
204+
205+
avgDT /= _historyDTLength;
206+
_chartLayer.path = path.CGPath;
207+
208+
CFTimeInterval minFPS = roundf(1.0f /(float)maxDT);
209+
CFTimeInterval avgFPS = roundf(1.0f /(float)avgDT);
210+
211+
NSString *text;
212+
if( _showsAverage ){
213+
text = [NSString stringWithFormat:@"low: %.f | avg: %.f", minFPS, avgFPS];
214+
} else {
215+
text = [NSString stringWithFormat:@"low %.f", minFPS];
216+
}
217+
218+
[_fpsTextLayer setString: text];
219+
220+
_lastUIUpdateTime = _displayLinkTickTimeLast;
221+
}
222+
223+
224+
@end

0 commit comments

Comments
 (0)