有一段時間沒有更新博客了,今天更新一篇關於最近工作中用到的一個功能,先簡單描述一下:我們知道,測試人員在測試客戶端產品時,當出現問題或者BUG的時候,都得先對頁面截圖,然後從相冊中選擇截圖,加上一段描述放到TD庫或者直接通過郵件發給開發人員,以方便開發人員進行修改,過程繁瑣。通過下面功能的介紹,您可以很方便的讓測試人員遇到BUG的時候,搖一搖設備,然後自動截圖並保存到應用的沙盒之中。截圖保存到沙盒之後,您可以自定義一個問題反饋的頁面,對問題進行描述(描述可使用第三方平台,如訊飛語音,實現語音錄入的效果)之後,將描述信息和頁面截圖一起發送給開發人員(可以是郵件,也可以是直接發送到後台)。
下面來看看功能是怎麼實現的。
首先,定義了一個category:ShakeAndCutter
UIViewController+ShakeAndCutter.h文件源碼:
1
2
3
4
5
#import <UIKit/UIKit.h>
@interface UIViewController (ShakeAndCutter)
@end
UIViewController+ShakeAndCutter.m文件源碼:
復制代碼
1 #import "UIViewController+ShakeAndCutter.h"
2 #import <QuartzCore/QuartzCore.h>
3 #import "TestFeedbackViewController.h"
4
5 @implementation UIViewController (ShakeAndCutter)
6
7 - (BOOL)canBecomeFirstResponder
8 {
9 return YES;
10 }
11
12 #pragma mark - 搖一搖動作處理
13
14 - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
15 {
16 NSLog(@"began");
17 }
18
19 - (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event
20 {
21 NSLog(@"cancel");
22 }
23
24 - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
25 {
26 NSLog(@"end");
27 [self cutterViewToDocument];
28
29 // 這裡是自定義的問題反饋頁面,也可以直接跳轉到系統郵件發送的頁面
30 TestFeedbackViewController *testFeedbackViewController = [[[TestFeedbackViewController alloc] initWithNibName:@"TestFeedbackViewController" bundle:nil] autorelease];
31 [self.navigationController pushViewController:testFeedbackViewController animated:YES];
32 }
33
34 #pragma mark - 截屏處理
35
36 - (void)cutterViewToDocument
37 {
38 UIWindow *screenWindow = [[UIApplication sharedApplication] keyWindow];
39
40 UIGraphicsBeginImageContext(screenWindow.frame.size);
41 [screenWindow.layer renderInContext:UIGraphicsGetCurrentContext()];
42 UIImage *screenShot = UIGraphicsGetImageFromCurrentImageContext();
43 UIGraphicsEndImageContext();
44
45 NSData *screenShotPNG = UIImagePNGRepresentation(screenShot);
46 NSError *error = nil;
47 [screenShotPNG writeToFile:[[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingPathComponent:@"error.png"] options:NSAtomicWrite error:&error];
48 }
49
50 @end
復制代碼
至此,搖一搖和截圖功能就已經完成了,那麼在應用中怎麼使用呢?
對於IOS6.0以上的設備,只需要在項目的pch文件中引進頭文件#import "UIViewController+ShakeAndCutter.h"即可(我在IOS6.0.1、IOS6.1.5、IOS7.0.6設備上已經測試過),這樣測試工作完成之後,您只需要將這行代碼注釋或者刪除就可以了;
對於IOS6.0以下的設備,在需要實現搖一搖效果的頁面,有可能要加入如下代碼(手頭沒有IOS6.0以下的設備,如果大家有的話,幫忙驗證一下,非常感謝):
1.viewDidLoad方法中,添加兩行代碼:
1 [[UIApplication sharedApplication] setApplicationSupportsShakeToEdit:YES];
2 [self becomeFirstResponder];
2.viewDidAppear方法中,添加一行代碼:
1 [self becomeFirstResponder];
3.viewDidDisappear方法中,添加一行代碼:
1 [self resignFirstResponder];
當然,以上的功能,您也可以實現其他的效果:比如說用戶問題的反饋等等,具體可以根據應用的需求而定。
這裡,再附上發送到郵件功能的示例代碼:
MailViewController.h文件源碼:
復制代碼
1 #import <UIKit/UIKit.h>
2 #import <MessageUI/MessageUI.h>
3 #import<MessageUI/MFMailComposeViewController.h>
4
5 @interface MailViewController : UIViewController<MFMailComposeViewControllerDelegate,
6 MFMessageComposeViewControllerDelegate>
7 {
8 UIButton *shareToMailButton;
9 }
10
11 @end
復制代碼
MailViewController.m文件源碼:
復制代碼
1 #import "MailViewController.h"
2 #import "Constants.h"
3
4 @interface MailViewController ()
5
6 @end
7
8 @implementation MailViewController
9
10 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
11 {
12 self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
13 if (self) {
14 // Custom initialization
15 }
16 return self;
17 }
18
19 - (void)viewDidLoad
20 {
21 [super viewDidLoad];
22 // Do any additional setup after loading the view.
23
24 self.title = @"Bug反饋";
25
26 shareToMailButton = [self buttonWithFrame:CGRectMake(20, 100, 280, 40) action:@selector(btnClicked:) withTag:1000];
27 [shareToMailButton setTitle:@"Bug反饋" forState:UIControlStateNormal];
28 }
29
30 - (void)didReceiveMemoryWarning
31 {
32 [super didReceiveMemoryWarning];
33 // Dispose of any resources that can be recreated.
34 }
35
36 #pragma mark - 自定義方法
37
38 - (void)btnClicked:(id)sender
39 {
40 UIButton *btnSender = (UIButton *)sender;
41
42 switch (btnSender.tag)
43 {
44 case 1000: // 分享到郵箱
45 {
46 [self showMailPicker];
47 break;
48 }
49 default:
50 break;
51 }
52 }
53
54 /*******************************************************************************
55 * 方法名稱:buttonWithFrame:action:
56 * 功能描述:初始化頁面按鈕,並添加到頁面視圖
57 * 輸入參數:
58 * 輸出參數:
59 ******************************************************************************/
60 - (UIButton *)buttonWithFrame:(CGRect)frame action:(SEL)action withTag:(int)tag
61 {
62 UIImage *buttonBackgroundImage = [[UIImage imageNamed:@"button_background.png"] stretchableImageWithLeftCapWidth:5 topCapHeight:5];
63 UIImage *disabledButtonBackgroundImage = [[UIImage imageNamed:@"button_background_disabled.png"] stretchableImageWithLeftCapWidth:5 topCapHeight:5];
64
65 UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
66 button.frame = frame;
67 [button setBackgroundImage:buttonBackgroundImage forState:UIControlStateNormal];
68 [button setBackgroundImage:disabledButtonBackgroundImage forState:UIControlStateDisabled];
69 [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
70 [button setTitleColor:[UIColor grayColor] forState:UIControlStateDisabled];
71 [button addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
72 button.tag = tag;
73 [self.view addSubview:button];
74
75 return button;
76 }
77
78 - (void)showMailPicker
79 {
80 Class mailClass = (NSClassFromString(@"MFMailComposeViewController"));
81
82 if (mailClass !=nil)
83 {
84 if ([mailClass canSendMail])
85 {
86 [self displayMailComposerSheet];
87 }
88 else
89 {
90 UIAlertView *alert=[[UIAlertView alloc] initWithTitle:@""message:@"設備不支持郵件功能" delegate:self cancelButtonTitle:@"確定" otherButtonTitles:nil];
91 [alert show];
92 [alert release];
93 }
94 }
95 else
96 {
97
98 }
99
100 }
101
102 - (void)displayMailComposerSheet
103 {
104 MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
105
106 // 設置picker的委托方法,完成之後會自動調用成功或失敗的方法
107 picker.mailComposeDelegate = self;
108 // 添加主題
109 [picker setSubject:@"Bug反饋"];
110 // 添加收件人
111 NSArray *toRecipients = [NSArray arrayWithObject:@"
[email protected]"];
112 // 說明:也可以添加多個收件人,代碼如下所示:
113 // NSArray *toRecipients = [NSArray arrayWithObjects:@"
[email protected]",@"
[email protected]",nil];
114 // 添加抄送
115 // NSArray *ccRecipients = [NSArray arrayWithObjects:@"
[email protected]",@"
[email protected]", nil];
116 // 添加密送
117 // NSArray *bccRecipients = [NSArray arrayWithObject:@"
[email protected]"];
118
119 [picker setToRecipients:toRecipients];
120 // [picker setCcRecipients:ccRecipients];
121 // [picker setBccRecipients:bccRecipients];
122 // 發送圖片附件(其他格式的附件,可以都先轉化稱NSData類型,然後設置相應的mimeType即可,如txt類型為@"text/txt",doc類型為@"text/doc",pdf類型為@"file/pdf"等等)
123 NSData *myData = [NSData dataWithContentsOfFile:[[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingPathComponent:@"error.png"]];
124 [picker addAttachmentData:myData mimeType:@"image/jpeg" fileName:@"error.png"];
125 NSString *emailBody = [NSString stringWithFormat:@"<p>文字沒有全部顯示</p>"];
126
127 // 直接在HTML代碼中寫入圖片的地址
128 // NSString *emailBody = [NSString stringWithFormat:@"<img src=/uploadfile/2014/0226/20140226093504351.com/&' /><p>我分享了圖片</p>"];
129
130 [picker setMessageBody:emailBody isHTML:YES];
131 [self presentModalViewController:picker animated:YES];
132 [picker release];
133 }
134
135
136 - (void)mailComposeController:(MFMailComposeViewController*)controller
137 didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
138 {
139 switch (result)
140 {
141 case MFMailComposeResultCancelled:
142 NSLog(@"Result: Mail sending canceled"); // 郵件發送取消
143 break;
144 case MFMailComposeResultSaved:
145 NSLog(@"Result: Mail saved"); // 郵件保存成功
146 break;
147 case MFMailComposeResultSent:
148 NSLog(@"Result: Mail sent"); // 郵件發送成功
149 break;
150 case MFMailComposeResultFailed:
151 NSLog(@"Result: Mail sending failed"); // 郵件發送失敗
152 break;
153 default:
154 NSLog(@"Result: Mail not sent");
155 break;
156 }
157 [self dismissModalViewControllerAnimated:YES];
158 }
159
160 - (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
161 {
162 NSLog(@"messageComposeViewController");
163 }
164
165 @end