有一段時間沒有更新博客了,今天更新一篇關於最近工作中用到的一個功能,先簡單描述一下:我們知道,測試人員在測試客戶端產品時,當出現問題或者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 ; 68 ; 69 forState:UIControlStateNormal]; 70 forState:UIControlStateDisabled]; 71 ; 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=http://www.2cto.com/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