ios基礎知識

   1 1獲取系統語言設置
   2 
   3      NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
   4 
   5      NSArray *languages = [userDefault objectForKey:@"AppleLanguages"];
   6 
   7      NSString *preferredLang = [languages objectAtIndex:0];
   8 
   9 2
  10 
  11 緩存路徑下文件大小
  12 
  13 
  14 - (unsigned long long int) cacheFolderSize 
  15 
  16 {
  17 
  18     NSFileManager  *_manager = [NSFileManager defaultManager];
  19 
  20     NSArray *_cachePaths =  NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
  21                                                 NSUserDomainMask, YES);
  22 
  23     NSString  *_cacheDirectory = [_cachePaths objectAtIndex:]; 
  24 
  25     NSArray  *_cacheFileList;
  26 
  27     NSEnumerator *_cacheEnumerator;
  28 
  29     NSString *_cacheFilePath;
  30 
  31     unsigned long long int _cacheFolderSize = ;
  32 
  33     _cacheFileList = [ _manager subpathsAtPath:_cacheDirectory];
  34 
  35    _cacheEnumerator = [_cacheFileList objectEnumerator];
  36 
  37     while (_cacheFilePath = [_cacheEnumerator nextObject]) 
  38 
  39    {
  40 
  41          NSDictionary *_cacheFileAttributes = [_managerfileAttributesAtPath:  
  42 
  43          [_cacheDirectory   stringByAppendingPathComponent:_cacheFilePath]
  44 
  45          traverseLink:YES];
  46 
  47       _cacheFolderSize += [_cacheFileAttributes fileSize];
  48 
  49     }
  50 
  51 // 單位是字節
  52 
  53     return _cacheFolderSize;
  54 
  55 }
  56 
  57 3Popover push 時 Frame沒法改變解決辦法
  58 
  59 在popover中的ViewController中實現:
  60 
  61 - (void)viewWillAppear:(BOOL)animated 
  62 {
  63 
  64    CGSize size = CGSizeMake(320, 480); // size of view in popover  
  65 
  66    self.contentSizeForViewInPopover = size; 
  67 
  68    [super viewWillAppear:animated]; 
  69 
  70 }
  71 
  72 4tableview滑動致使NSTimer和委託回調中止解決辦法
  73 
  74 / /請求回調
  75 
  76 NSURLRequest  * 請求  =  ...
  77 
  78 scheduleInRunLoop :[ NSRunLoop  currentRunLoop ] 
  79                                             forMode :NSRunLoopCommonModes ] 
  80 [ 鏈接開始] / /定時器回調
  81 
  82 NSTimer * updateTimer = [NSTimer scheduledTimerWithTimeInterval:0.01f目標:自我選擇:選擇(updatePencent)的UserInfo:無重複:是];
  83 
  84 * NSRunLoop主要= [NSRunLoop currentRunLoop] 
  85 [主要addTimer:updateTimer forMode:NSRunLoopCommonModes];
  86 
  87 5手勢識別類
  88 
  89 UIGestureRecognizer
  90 
  91 
  92 6SFHFKeychainUtils 存儲信息
  93 
  94 蘋果SDK自帶的就有密碼保護,使用方法很簡單,以下:
  95 
  96 1、引入Security.frameWork框架。
  97 
  98 2、引入頭文件:SFHKeychainUtils.h.
  99 
 100 3、存密碼:
 101 
 102 [SFHFKeychainUtils storeUsername:@"dd" andPassword:@"aa"forServiceName:SERVICE_NAMEupdateExisting:1 error:nil];
 103 
 104 [SFHFKeychainUtils deleteItemForUsername:@"dd" andServiceName:SERVICE_NAME error:nil];
 105 
 106 4、取密碼:
 107 
 108 NSString *passWord =  [SFHFKeychainUtils getPasswordForUsername:@"dd"andServiceName:SERVICE_NAMEerror:nil];
 109 
 110 7missing required architecture i386 in file 解決辦法
 111 
 112 在TargetInfo裏面修改 Framework Search Pasths 刪除裏面內容就能夠了。
 113 
 114 
 115 8view 放大縮小動畫效果
 116 
 117 //建立縮小了的視圖
 118 myWeiBoImageVC = [[UIViewController alloc] init];
 119 myWeiBoImageVC.view.clipsToBounds = YES;
 120 myWeiBoImageVC.view.alpha = 0.0;
 121 myWeiBoImageVC.view.frame = CGRectMake(64, 0, 1024-64, 768-20);
 122 [self.view addSubview:myWeiBoImageVC.view];
 123     
 124 CGAffineTransform newTransform = 
 125 CGAffineTransformScale(myWeiBoImageVC.view.transform, 0.1, 0.1);
 126 [myWeiBoImageVC.view setTransform:newTransform];
 127 myWeiBoImageVC.view.center = CGPointMake(670, 100);
 128  
 129 [self performSelector:@selector(imageViewControllerBigAnimation)];
 130 
 131 //放大剛剛建立縮小後的視圖
 132 - (void)imageViewControllerBigAnimation{
 133    
 134     [UIView beginAnimations:@"imageViewBig" context:nil];
 135     [UIView setAnimationDuration:0.5];   
 136     CGAffineTransform newTransform =            CGAffineTransformConcat(myWeiBoImageVC.view.transform,  CGAffineTransformInvert(myWeiBoImageVC.view.transform));
 137     [myWeiBoImageVC.view setTransform:newTransform];
 138     myWeiBoImageVC.view.alpha = 1.0;
 139     myWeiBoImageVC.view.center = CGPointMake(416, 510);
 140     [UIView commitAnimations];
 141    
 142 }
 143 
 144 //縮小視圖 隱藏
 145 
 146 - (void)imageViewControllerSmallAnimation{
 147 
 148     [UIView beginAnimations:@"imageViewSmall" context:nil];
 149     [UIView setAnimationDuration:0.5];
 150     CGAffineTransform newTransform =  CGAffineTransformScale(myWeiBoImageVC.view.transform, 0.1, 0.1);
 151     [myWeiBoImageVC.view setTransform:newTransform];
 152     myWeiBoImageVC.view.center = CGPointMake(670, 100);
 153     [UIView commitAnimations];
 154    
 155 }
 156 
 157 9UIScrollView 控制View縮放
 158 
 159 allImageScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 768, 1024)];
 160 allImageScrollView.minimumZoomScale = 0.3;
 161 allImageScrollView.maximumZoomScale = 1.0;
 162 allImageScrollView.backgroundColor = [UIColor clearColor];
 163 allImageScrollView.delegate = self;
 164 [self.view addSubview:allImageScrollView];
 165 
 166 mPicStatusesViewController = [[PicStatusesViewController alloc] init];
 167 [allImageScrollView addSubview:mPicStatusesViewController.view];
 168 
 169 //UIScrollView Delegete 實現
 170 
 171 - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
 172 
 173 {
 174     return mPicStatusesViewController.view; //返回ScrollView上添加的須要縮放的視圖
 175 }
 176 
 177 - (void)scrollViewDidZoom:(UIScrollView *)scrollView
 178 
 179 {
 180     //縮放操做中被調用
 181 }
 182 
 183 - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
 184 
 185 {
 186     //縮放結束後被調用
 187   }
 188 
 189 10、iOS3.2 播放視頻
 190 
 191 NSString *urlString = [NSString stringWithString:@"視頻url"];
 192 
 193 NSURL *movieUrl = [[NSURL alloc] initWithString:urlString];
 194     
 195 MPMoviePlayerController *myMoviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:movieUrl];
 196 myMoviePlayer.view.frame = CGRectMake(250, 250, 350, 350);
 197 [self.view addSubview:myMoviePlayer.view];    
 198 myMoviePlayer.shouldAutoplay = YES;
 199 myMoviePlayer.scalingMode= MPMovieScalingModeAspectFit;  
 200 [myMoviePlayer play];
 201 
 202 
 203 11、谷歌地圖翻起動畫效果
 204 
 205     CATransition *animation = [CATransition animation];
 206     [animation setDelegate:self];
 207     [animation setDuration:0.35];
 208     [animation setTimingFunction:UIViewAnimationCurveEaseInOut];
 209     if (!curled){
 210 
 211         animation.type = @"pageCurl";
 212         animation.fillMode = kCAFillModeForwards;
 213         animation.endProgress = 0.40;
 214     } else {
 215         animation.type = @"pageUnCurl";
 216         animation.fillMode = kCAFillModeBackwards;
 217         animation.startProgress = 0.30;
 218     }
 219     [animation setRemovedOnCompletion:NO];
 220     [self.view exchangeSubviewAtIndex:0 withSubviewAtIndex:1];
 221     
 222     [self.view.layer addAnimation:animation forKey:@"pageCurlAnimation"];
 223 
 224 12、給View添加陰影 和邊框
 225 
 226 UIImageView *imgvPhoto  = [UIImageView alloc] init];
 227 
 228 //添加邊框
 229    CALayer *layer = [_imgvPhoto layer];
 230     layer.borderColor = [[UIColor whiteColor] CGColor];
 231     layer.borderWidth = 5.0f;
 232 //添加四個邊陰影
 233     _imgvPhoto.layer.shadowColor = [UIColor blackColor].CGColor;
 234     _imgvPhoto.layer.shadowOffset = CGSizeMake(0, 0);
 235     _imgvPhoto.layer.shadowOpacity = 0.5;
 236     _imgvPhoto.layer.shadowRadius = 10.0;
 237 //添加兩個邊陰影
 238     _imgvPhoto.layer.shadowColor = [UIColor blackColor].CGColor;
 239     _imgvPhoto.layer.shadowOffset = CGSizeMake(4, 4);
 240     _imgvPhoto.layer.shadowOpacity = 0.5;
 241     _imgvPhoto.layer.shadowRadius = 2.0;
 242 
 243 13、使用NSTimer與UIView動畫實現飄雪效果
 244 
 245 viewDidLoad事件中,增長一個圖片及定時器並啓動,這裏的pic請在頭文件中定義。
 246 
 247 -(void)viewDidLoad{
 248  [super viewDidLoad];
 249  self.pic = [UIImage imageNamed:@"snow.png"];//初始化圖片
 250  //啓動定時器,實現飄雪效果
 251  [NSTimer scheduledTimerWithTimeInterval:(0.2) target:self selector:@selector(ontime) userInfo:nil repeats:YES];
 252 }
 253 
 254 而後再實現定時器定時調用的ontime方法:
 255 -(void)ontime{
 256  UIImageView *view = [[UIImageView alloc] initWithImage:pic];//聲明一個UIImageView對象,用來添加圖片
 257  view.alpha = 0.5;//設置該view的alpha爲0.5,半透明的
 258  int x = round(random()20);//隨機獲得該圖片的x座標
 259  int y = round(random()20);//這個是該圖片移動的最後座標x軸的
 260  int s = round(random())+10;//這個是定義雪花圖片的大小
 261  int sp = 1/round(random()0)+1;//這個是速度
 262  view.frame = CGRectMake(x, -50, s, s);//雪花開始的大小和位置
 263  [self.view addSubview:view];//添加該view
 264  [UIView beginAnimations:nil context:view];//開始動畫
 265  [UIView setAnimationDuration:10*sp];//設定速度
 266  view.frame = CGRectMake(y, 500, s, s);//設定該雪花最後的消失座標
 267  [UIView setAnimationDelegate:self];
 268  [UIView commitAnimations];
 269 }
 270 
 271 14、配置Xcode 看程序崩潰信息
 272 
 273 1、在xcode中的左側目錄中找到Executables 打開
 274 
 275 2、雙擊和工程名同樣的文件。
 276 
 277 3、在打開的文件中的Arguments選項,在下面的框中加入Name: NSZombieEnabled 設置value爲YES。
 278 
 279 15、程序中發送郵件和檢測設備郵箱是否被配置
 280 
 281 -(void)addEmail{
 282 
 283 Class mailClass = (NSClassFromString(@"MFMailComposeViewController"));
 284 
 285 if (mailClass != nil){
 286 
 287     if ([mailClass canSendMail]){
 288 
 289         [self displayComposerSheet];
 290 
 291     }else{
 292 
 293         [self launchMailAppOnDevice];
 294 
 295     }
 296 
 297 }else{
 298 
 299     [self launchMailAppOnDevice];
 300 
 301     }
 302 
 303 }
 304 
 305 -(void)displayComposerSheet
 306 
 307 {
 308 
 309 MFMailComposeViewController *controller = [[MFMailComposeViewController alloc] init];
 310 
 311 controller.navigationBar.tag = 1002;
 312 
 313 [self.navigationController.navigationBar setNeedsDisplay];
 314 
 315 controller.mailComposeDelegate = self;
 316 
 317 [controller setSubject:@"意見反饋"];
 318 
 319 [controller setToRecipients:[[NSArray alloc] initWithObjects:@"555@cifco.net.cn",nil]];
 320 
 321 NSString *emailBody = nil;
 322 
 323 [controller setMessageBody:emailBody isHTML:YES];
 324 
 325 [self presentModalViewController:controller animated:YES];
 326 
 327 [controller release];
 328 
 329 }
 330 
 331 #pragma mark mailComposeDelegate ----
 332 
 333 - (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error 
 334 
 335 {
 336 
 337 if (result == MFMailComposeResultSent) 
 338 
 339 {
 340 
 341 [self dismissModalViewControllerAnimated:YES];
 342 
 343 }
 344 
 345 if (result == MFMailComposeResultSaved) 
 346 
 347 {
 348 
 349 [self dismissModalViewControllerAnimated:YES];
 350 
 351 }
 352 
 353 if (result == MFMailComposeResultFailed) 
 354 
 355 {
 356 
 357 Emailalert = [[UIAlertView alloc] initWithTitle:@"" message:@"發送失敗" delegate:selfcancelButtonTitle:@"知道了" otherButtonTitles:nil];
 358 
 359 [Emailalert show];
 360 
 361 }
 362 
 363 if (result == MFMailComposeResultCancelled) 
 364 
 365 {
 366 
 367 [self dismissModalViewControllerAnimated:YES];
 368 
 369 }
 370 
 371 }
 372 
 373 - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
 374 
 375 {
 376 
 377 if(alertView == Emailalert)
 378 
 379 {
 380 
 381 if (buttonIndex == ) 
 382 
 383 {
 384 
 385 [self dismissModalViewControllerAnimated:YES];
 386 
 387 }
 388 
 389 }else 
 390 
 391 {
 392 
 393 if (buttonIndex == ) 
 394 
 395 {
 396 
 397 //[self dismissModalViewControllerAnimated:YES];
 398 
 399 }else 
 400 
 401 {
 402 
 403 NSString *recipients = @"mailto:theonelgq@gmail.com?cc=theone_liuguoqing@163.com&subject=text";
 404 
 405 NSString *body = @"&body=text!";
 406 
 407 NSString *email = [NSString stringWithFormat:@"%@%@", recipients, body];
 408 
 409 email = [email stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
 410 
 411 [[UIApplication sharedApplication] openURL:[NSURL URLWithString:email]];
 412 
 413 }
 414 
 415 }
 416 
 417 }
 418 
 419 #pragma mark -
 420 
 421 #pragma mark Workaround
 422 
 423 -(void)launchMailAppOnDevice
 424 
 425 {
 426 
 427 isEmailalert = [[UIAlertView alloc] initWithTitle:@"警告" message:@"請配置您的郵箱" delegate:selfcancelButtonTitle:@"取消" otherButtonTitles:@"好的",nil];
 428 
 429 [isEmailalert show];
 430 
 431 }
 432 
 433 16、程序啓動畫面大小
 434 
 435  iOS設備如今有三種不一樣的分辨率:iPhone 320x480、iPhone 4 640x960、iPad 768x1024。之前程序的啓動畫面(圖片)只要準備一個 Default.png 就能夠了,可是如今變得複雜多了。下面就是 CocoaChina 會員作得總結
 436 
 437   若是一個程序,既支持iPhone又支持iPad,那麼它須要包含下面幾個圖片:
 438 
 439 Default-Portrait.png iPad專用豎向啓動畫面 768x1024或者768x1004
 440 
 441 Default-Landscape.png iPad專用橫向啓動畫面 1024x768或者1024x748
 442 
 443 Default-PortraitUpsideDown.png iPad專用豎向啓動畫面(Home按鈕在屏幕上面),可省略 768x1024或者768x1004
 444 
 445 Default-LandscapeLeft.png iPad專用橫向啓動畫面,可省略 1024x768或者1024x748
 446 
 447 Default-LandscapeRight.png iPad專用橫向啓動畫面,可省略 1024x768或者1024x748
 448 
 449 Default.png iPhone默認啓動圖片,若是沒有提供上面幾個iPad專用啓動圖片,則在iPad上運行時也使用Default.png(不推薦) 320x480或者320x460
 450 
 451 Default@2x.png iPhone4啓動圖片640x960或者640x920
 452 
 453   爲了在iPad上使用上述的啓動畫面,你還須要在info.plist中加入key: UISupportedInterfaceOrientations。同時,加入值UIInterfaceOrientationPortrait, UIInterfacOrientationPortraitUpsideDown, UIInterfaceOrientationLandscapeLeft, UIInterfaceOrientationLandscapeRight
 454 
 455 17、ASIHTTPRequest實現斷點下載
 456 
 457 - (IBAction)URLFetchWithProgress:(id)sender
 458 
 459 {
 460 
 461 [startButton setTitle:@"Stop" forState:UIControlStateNormal];
 462 
 463 [startButton addTarget:self action:@selector(stopURLFetchWithProgress:)forControlEvents:UIControlEventTouchUpInside];
 464 
 465 NSString*tempFile = [[[[NSBundle mainBundle] bundlePath]stringByDeletingLastPathComponent]stringByAppendingPathComponent:@"MemexTrails_1.0b1.zip.download"];
 466 
 467 if ([[NSFileManager defaultManager] fileExistsAtPath:tempFile]) {
 468 
 469 [[NSFileManager defaultManager] removeItemAtPath:tempFile error:nil];
 470 
 471 }
 472 
 473 [self resumeURLFetchWithProgress:self];
 474 
 475 }
 476 
 477 - (IBAction)stopURLFetchWithProgress:(id)sender
 478 
 479 {
 480 
 481 networkQueue = [[ASINetworkQueue alloc] init];
 482 
 483 timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:selfselector:@selector(updateBandwidthUsageIndicator) userInfo:nil repeats:YES];
 484 
 485 timer = nil;
 486 
 487 [startButton setTitle:@"Stop" forState:UIControlStateNormal];
 488 
 489 [startButton addTarget:self action:@selector(URLFetchWithProgress:)forControlEvents:UIControlEventTouchUpInside];
 490 
 491 [networkQueue cancelAllOperations];
 492 
 493 [resumeButton setEnabled:YES];
 494 
 495 }
 496 
 497 - (IBAction)resumeURLFetchWithProgress:(id)sender 
 498 
 499 {
 500 
 501 [resumeButton setEnabled:NO];
 502 
 503 [startButton setTitle:@"Start" forState:UIControlStateNormal];
 504 
 505  [startButton addTarget:self action:@selector(stopURLFetchWithProgress:)forControlEvents:UIControlEventTouchUpInside];
 506 
 507 [networkQueue cancelAllOperations];
 508 
 509 [networkQueue setShowAccurateProgress:YES];
 510 
 511 [networkQueue setDownloadProgressDelegate:progressIndicator];
 512 
 513 [networkQueue setDelegate:self];
 514 
 515 [networkQueue setRequestDidFinishSelector:@selector(URLFetchWithProgressComplete:)];
 516 
 517 ASIHTTPRequest*request=[[[ASIHTTPRequest alloc] initWithURL:[NSURLURLWithString:@"http://9991.net/blog/mp3/2.mp3"]] autorelease];
 518 
 519 [request setDownloadDestinationPath:[[[[NSBundle mainBundle] bundlePath]
 520 
 521 stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"MemexTrails_1.0b1.mp3"]];
 522 
 523 [request setTemporaryFileDownloadPath:[[[[NSBundle mainBundle] bundlePath]stringByDeletingLastPathComponent]stringByAppendingPathComponent:@"MemexTrails_1.0b1.zip.down"]];
 524 
 525 [request setAllowResumeForFileDownloads:YES];
 526 
 527 [networkQueue addOperation:request];
 528 
 529 [networkQueue go];
 530 
 531 }
 532 
 533 - (void)URLFetchWithProgressComplete:(ASIHTTPRequest *)request
 534 
 535 {
 536 
 537 if ([request error]) {
 538 
 539 fileLocation.text=[NSString stringWithFormat:@"An error occurred:%@",[[[requesterror] userInfo] objectForKey:@"Title"]];
 540 
 541 } else {
 542 
 543 fileLocation.text=[NSString stringWithFormat:@"File downloaded to %@",[requestdownloadDestinationPath]];
 544 
 545 }
 546 
 547 [startButton setTitle:@"Start" forState:UIControlStateNormal];
 548 
 549 [startButton addTarget:self action:@selector(URLFetchWithProgress:)forControlEvents:UIControlEventTouchUpInside];
 550 
 551 }
 552 
 553 - (IBAction)throttleBandwidth:(id)sender
 554 
 555 {
 556 
 557 if ([(UIButton *)sender state] ==YES) {
 558 
 559 [ASIHTTPRequest setMaxBandwidthPerSecond:ASIWWANBandwidthThrottleAmount];
 560 
 561 } else {
 562 
 563 [ASIHTTPRequest setMaxBandwidthPerSecond:];
 564 
 565 }
 566 
 567 }
 568 
 569 18、Safari 啓動本地app
 570 
 571 在plist文件中加入URL types 結構以下圖,在Safari中地址欄輸入 設置的字符串,好比設置的是
 572 
 573 QQ,地址欄輸入 QQ:// 就能夠起點本地應用。
 574 
 575  
 576 
 577 
 578 19、拖到視頻進度與滑動手勢衝突解決辦法
 579 
 580 #pragma mark -
 581 #pragma mark UIGestureRecognizerDelegate
 582 
 583 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
 584 {
 585     UIView *touchView = touch.view;
 586     
 587     if ([touchView isKindOfClass:[UISlider class]]) 
 588     {
 589         return NO;
 590     }
 591     else 
 592     {
 593         return YES;
 594     }
 595 }
 596 
 597 20、建立並保存Cookie的方法
 598 
 599 
 600         NSString *cookieString = [NSString stringWithString:[headers objectForKey:@"Cookie"]];
 601         
 602         NSMutableDictionary *cookieProperties = [[NSMutableDictionary alloc] init];
 603         [cookieProperties setValue:cookieString forKey:NSHTTPCookieValue];
 604         [cookieProperties setValue:@"QQCookie" forKey:NSHTTPCookieName];
 605         [cookieProperties setValue:@".QQ.com" forKey:NSHTTPCookieDomain];
 606         [cookieProperties setValue:[NSDate dateWithTimeIntervalSinceNow:60*60] forKey:NSHTTPCookieExpires];
 607         [cookieProperties setValue:@"/" forKey:NSHTTPCookiePath];
 608         NSHTTPCookie *newcookie = [[NSHTTPCookie alloc] initWithProperties:cookieProperties];
 609         
 610         [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:newcookie];
 611 
 612 
 613 21、popover橫豎屏位置改變解決辦法
 614 
 615 1、 delegate中 處理
 616 
 617 - (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
 618 {
 619     userImageShow = NO;
 620     
 621     if ([popoverController isEqual:myPopover]) 
 622     {
 623         [myPopover release];
 624         myPopover = nil;
 625     }
 626 }
 627 
 628 2、屏幕旋轉時從新彈出Popover
 629 
 630 if (myPopover)  
 631 
 632 {
 633 
 634      if ((self.interfaceOrientation == 
 635        UIInterfaceOrientationLandscapeLeft) || (self.interfaceOrientation == 
 636        UIInterfaceOrientationLandscapeRight)) 
 637      {
 638             [myPopover presentPopoverFromRect:CGRectMake(10,180, 1, 1)
 639                                                 inView:self.view
 640                               permittedArrowDirections:UIPopoverArrowDirectionRight
 641                                               animated:YES];
 642      }
 643      else 
 644      {
 645            [myPopover presentPopoverFromRect:CGRectMake(20,180, 1, 1)
 646                                                 inView:self.view
 647                               permittedArrowDirections:UIPopoverArrowDirectionRight
 648                                               animated:YES];
 649       }
 650 
 651 }
 652 
 653 22、plist各類key值含義
 654 
 655 原文:http://www.minroad.com/?p=434
 656 
 657 
 658 
 659 UIRequiresPersistentWiFi 在程序中彈出wifi選擇的key(系統設置中須要將wifi提示打開)
 660 UIAppFonts 內嵌字體(http://www.minroad.com/?p=412 有詳細介紹)
 661 UIApplicationExitsOnSuspend 程序是否在後臺運行,本身在進入後臺的時候exit(0)是很傻的辦法
 662 UIBackgroundModes 後臺運行時的服務,具體看iOS4的後臺介紹
 663 UIDeviceFamily array類型(1爲iPhone和iPod touch設備,2爲iPad)
 664 UIFileSharingEnabled 開啓itunes共享document文件夾
 665 UILaunchImageFile 至關於Default.png(改名而已)
 666 UIPrerenderedIcon icon上是否有高光
 667 UIRequiredDeviceCapabilities 設備須要的功能(具體點擊這裏查看)
 668 UIStatusBarHidden 狀態欄隱藏(和程序內的區別是在於顯示Default.png已經生效)
 669 UIStatusBarStyle 狀態欄類型
 670 UIViewEdgeAntialiasing 是否開啓抗鋸齒
 671 CFBundleDisplayName app顯示名
 672 CFBundleIconFile、CFBundleIconFiles 圖標
 673 CFBundleName 與CFBundleDisplayName的區別在於這個是短名,16字符以內
 674 CFBundleVersion 版本
 675 CFBundleURLTypes 自定義url,用於利用url彈回程序
 676 CFBundleLocalizations 本地資源的本地化語言,用於itunes頁面左下角顯示本地話語種
 677 CFBundleDevelopmentRegion 也是本地化相關,若是用戶所在地沒有相應的語言資源,則用這個key的value來做爲默認
 678 最後附上官方文檔,全部的key都有,看英文原版纔是正路:)點我進入
 679 
 680 24、xcode工程內添加多個Target
 681 
 682 轉自:http://blog.sina.com.cn/s/blog_682dc7810100pv8t.html
 683 
 684  
 685 
 686 啥叫多Targets, 有啥用!
 687 
 688  
 689 
 690    相信不少人都注意到XCode中,
 691 有個Target的概念.
 692     這在不少地方都有所體現,
 693 好比打開一個工程後, 左側的列表中有Targets一項, 而在工程界面的頂部菜單中,
 694 project裏面也有多個涉及到Target的項目,
 695 那麼這個Target究竟是什麼呢?  
 696     Apple的人是這樣說的:
 697     
 698 
 699 引用
 700 
 701 Targets that define the products to build. A
 702 target organizes the files and instructions needed to build a
 703 product into a sequence of build actions that can be taken.
 704 
 705 
 706 
 707     簡單的理解的話, 
 708 
 709 能夠認爲一個target對應一個新的product(基於同一份代碼的狀況下). 但都一份代碼了, 弄個新product作啥呢? 
 710 
 711 折騰這個有意思麼? 
 712 
 713     其實這不是單純的瞎折騰, 
 714 
 715 雖然代碼是同一份, 但編譯設置(好比編譯條件), 以及包含的資源文件卻能夠有很大的差異. 因而即便同一份代碼, 
 716 
 717 產出的product也可能大不相同. 
 718 
 719     咱們來舉幾個典型的應用多Targets的狀況吧, 
 720 
 721 好比完整版和lite版; 好比同一個遊戲的20關, 30關, 50關版; 再或者好比同一個遊戲換些資源和名字就當新遊戲賣的(喂喂, 
 722 
 723 你在教些什麼...) 
 724 
 725 
 726 Targets之間, 什麼相同, 什麼不一樣! 
 727 
 728 
 729     既然是利用同一份代碼產出不一樣的product, 
 730 
 731 那麼到底不一樣Target之間存在着什麼樣的差別呢? 
 732 
 733     要解釋這個問題, 
 734 
 735 咱們就要來看看一個Target指定了哪些內容. 
 736 
 737 
 738     從XCode左側的列表中, 
 739 
 740 咱們能夠看到一個Target包含了Copy Bundle Resources, Compile Sources, Link 
 741 
 742 Binary With Libraries. 其中 
 743 
 744         Copy 
 745 
 746 Bundle Resources 是指生成的product的.app內將包含哪些資源文件 
 747 
 748         Compile 
 749 
 750 Sources 是指將有哪些源代碼被編譯 
 751 
 752         Link 
 753 
 754 Binary With Libraries 是指編譯過程當中會引用哪些庫文件 
 755 
 756 
 757     經過Copy 
 758 
 759 Bundle Resources中內容的不一樣設置, 咱們可讓不一樣的product包含不一樣的資源, 包括程序的主圖標等, 
 760 
 761 而不是把XCode的工程中列出的資源一股腦的包含進去. 
 762 
 763     而這還不是一個target所指定的所有內容. 
 764 
 765 每一個target可使用一個獨立, 
 766 
 767 不一樣的Info.plist文件.   
 768 
 769     咱們都知道, 
 770 
 771 這個Info.plist文件內定義了一個iPhone項目的不少關鍵性內容, 好比程序名稱, 
 772 
 773 最終生成product的全局惟一id等等. 
 774 
 775      
 776 
 777     並且不一樣的target還能夠定義完整的差別化的編譯設置, 
 778 
 779 從簡單的調整優化選項, 到增長條件編譯所使用的編譯條件, 以致於所使用的base SDK均可以差別化指定. 
 780 
 781 
 782 建立第二個Target! 
 783 
 784     爲何是第二個? 
 785 
 786 由於第一個就是建立好工程後的默認Target呀! (廢話這麼多, 拖走...) 
 787 
 788 
 789     建立target有多種方法, 
 790 
 791 咱們能夠從現有的target上覆製出一份, 而後略加改動, 也能夠徹底新建一個target出來. 但其實說穿了, 
 792 
 793 兩個方法大同小異 
 794 
 795     首先咱們來看看利用複製的方法建立target 
 796 
 797 
 798      利用複製建立target 
 799 
 800     咱們在XCode左側的列表中, 
 801 
 802 展開 Targets 項, 在現有的target上, 右鍵選擇 "Duplicate", 或者選中現有target後, 
 803 
 804 在頂部菜單的Edit內選擇"Duplicate"也能夠. 
 805 
 806     此時咱們就獲得了一個新的target, 
 807 
 808 而在Resource裏面也會獲得一個 xxxx copy.plist. 這個新的target與原有的target是徹底一致的, 
 809 
 810 餘下的就是一些差別化的修改, 這個咱們後面再說 
 811 
 812 
 813      建立全新的target 
 814 
 815     相似複製的方法, 
 816 
 817 咱們能夠在左側的列表中不少地方按下右鍵菜單, 均可以看到Add中會有"New Target..."一項, 
 818 
 819 而在工程頂部菜單的Project內, 也能夠看到這個"New Target..."的身影. 
 820 
 821     點擊後, 
 822 
 823 首先會讓你選擇target的類型, 既然我一直所指的都是程序自己, 那麼天然選擇Application了(至於其餘的嘛, 
 824 
 825 有興趣的本身研究吧, 好比咱們能夠把程序中的部分提取成一個Static Library). 
 826 
 827     Next後, 
 828 
 829 會讓你輸入一個新的Target的名字, 而不像複製的方法中, 默認生成 xxxxx copy這樣的target名. 
 830 
 831     可是這樣生成出的Target幾乎是空的. 
 832 
 833 Copy Bundle Resources, Compile Sources, Link Binary With 
 834 
 835 Libraries裏面都沒有任何內容. 編譯設置也是徹底原始的狀態. 
 836 
 837     能夠經過拖拽內容到這些target的設置中, 
 838 
 839 以及調整編譯選項來完成Target的配置. 
 840 
 841 
 842 
 843 Target中部份內容的修改方法! 
 844 
 845     其實這段的部份內容, 
 846 
 847 在非多Targets的工程中也可能會用獲得. 
 848 
 849     因爲修改基本都是在工程/編譯設置中完成, 
 850 
 851 所以沒有特殊狀況, 就再也不聲明瞭, 打開target對應的工程/編譯設置的方法能夠採用在該target上右鍵, 選擇get 
 852 
 853 info來作到. 
 854 
 855 
 856     生成的product名稱的修改: 
 857 
 858 Packing段內的Product Name一項 
 859 
 860 
 861     Info.plist文件名: 
 862 
 863 Packing段內的Info.plist File一項, 好比複製出來的target以爲那個xxxxx 
 864 
 865 copy.plist太傻就能夠在這裏改 
 866 
 867 
 868  869 
 870 件編譯: 增長一個User-Defined Setting(Target "xxxx" 
 871 
 872 Info的build頁的左下角那個齒輪中能夠看到這個內容), 在Other C Flag裏面填入, 
 873 
 874 好比要定義一個叫作LITE_VERSION的define值, 咱們能夠寫上 "-DLITE_VERSION" 875 
 876 "-DLITE_VERSION=1". 那麼在程序中就能夠用 
 877 
 878     #if 
 879 
 880 defined(LITE_VERSION) 
 881 
 882     #else 
 883 
 884     #endif 
 885 
 886 這樣的條件編譯來部分差別化代碼了 
 887 
 888 
 889     也許有些朋友記得我在代碼區貼過的檢測破解版的代碼, 
 890 
 891 其中有一種檢測方法就是看info.plist是文本仍是二進制的, 那麼咱們可否建議一個模擬破解的target, 
 892 
 893 直接生成文本的info.plist以便測試呢? 
 894 
 895     固然能夠, 
 896 
 897 在packing段內, 有一項叫"Info.plist Output Encoding", 默認值是Binary, 
 898 
 899 咱們只要選成xml, 那麼生成出的product.app內的info.plist就直接是文本樣式的了. 
 900 
 901 
 902 
 903  904 
 905 外, 向Copy Bundle Resources, Compile Sources, Link Binary With 
 906 
 907 Libraries內添加/刪除文件, 能夠在要改動的文件上, 選擇get info, 而且切換到Target頁, 
 908 
 909 勾選要引用這個文件的target便可. 好比icon.png能夠指定給默認target, 而icon_lite.png指定給lite 
 910 
 911 verion的target 
 912 
 913 
 914 
 915 大體就是如此吧, 懶得抓圖了. 各位將就吧. 想到什麼須要補充的, 我會加入 
 916 
 917 另外 
 918 
 919 一個英文教程:http://www.codza.com/free-iphone-app-version-from-the-same-xcode-project
 920 
 921 25、詳解IOS SDK兼容性引導
 922 
 923 轉自: http://mobile.51cto.com/iphone-284052.htm
 924 
 925  
 926 
 927 IOS SDK兼容性引導是本文要介紹的內容,主要是基於IOS SDK基礎的開發介紹說明如何應用於XCode工程的基於IOS SDK開發的技術。來看詳細內容講解。
 928 
 929 1、用(weakly linked)弱鏈接類、方法和函數來支持在不一樣版本之間的程序運行
 930 
 931 2、弱鏈接整個框架(framework)
 932 
 933 3、爲不一樣的IOS SDK選擇不一樣的編譯條件
 934 
 935 4、在代碼中找出過期API的使用
 936 
 937 5、肯定在運行時操做系統和框架(framework)的版本
 938 
 939 一 、在IOS中使用弱鏈接類
 940 
 941 在工程中使用類的弱鏈接的時候必須確保這些類在運行時的可用性,要不會引發動態鏈接的錯誤。
 942 
 943 在IOS4.2之後的版本都是使用NSObject class的方法來檢測弱鏈接在運行時態的可用性,這種簡單高效的機制使用了NS_CLASS_AVAILABLE的可用性宏。
 944 
 945 檢測最近release的framework還不支持NS_CLASS_AVAILABLE的宏
 946 
 947 在支持NS_CLASS_AVAILABLE的宏framework的條件編譯中,能夠以下的使用
 948 
 949 if ([UIPrintInteractionController class]) {   
 950     // Create an instance of the class and use it.   
 951 } else {   
 952     // Alternate code path to follow when the   
 953     // class is not available.   
 954 } 
 955 若是你在不確保是否已經可使用類方法的時候你可使用NSClassFromString 方法來判斷,使用方法以下:
 956 
 957 Class cls = NSClassFromString (@"NSRegularExpression");   
 958 if (cls) {   
 959     // Create an instance of the class and use it.   
 960 } else {   
 961     // Alternate code path to follow when the   
 962     // class is not available.   
 963 } 
 964 2、在方法,函數和符號中使用弱鏈接
 965 
 966 和使用類的弱鏈接同樣,在使用它以前要確保方法函數和符號在運行時的可用性,要不在編譯的時候會報錯動態鏈接錯誤,假設你想使用新版本IOS 
 967 SDK的特性可是又想可以運行在低版本的SDK中,那麼就要對早期的版本設置相應的開發target,在Object-c中 
 968 instancesRespondToSelector: 
 969 方法告訴咱們所給的方法是否可用,例如:使用availableCaptureModesForCameraDevice:這個方法(在4.0之後纔是可
 970 用的),咱們能夠這樣使用它。
 971 
 972 1、檢查一個Object-c方法的可用性
 973 
 974 if ([UIImagePickerController instancesRespondToSelector:   
 975               @selector (availableCaptureModesForCameraDevice:)]) {   
 976     // Method is available for use.   
 977     // Your code can check if video capture is available and,   
 978     // if it is, offer that option.   
 979 } else {   
 980     // Method is not available.   
 981     // Alternate code to use only still image capture.   
 982 } 
 983 判斷一個弱鏈接的C函數是否可用,只要判斷函數的地址是否返回爲NULL,以CGColorCreateGenericCMYK 函數爲例,咱們能夠像如下那樣使用。
 984 
 985 2、檢查C方法的可用性
 986 
 987 if (CGColorCreateGenericCMYK != NULL) {   
 988     CGColorCreateGenericCMYK (0.1,0.5.0.0,1.0,0.1);   
 989 } else {   
 990     // Function is not available.   
 991     // Alternate code to create a color object with earlier technology   
 992 }  
 993 要檢測一個C方法是否可用,比較明確的爲地址是否爲NULL或零。你不能使用反運算符(!)來否認一個函數的可用性
 994 
 995 檢測一個 external(extern)常量或一個通知的名字應當比較它的地址(address)--而不是符號的名稱, 判斷是否爲NULL or nil
 996 
 997 3、弱鏈接整個Framework
 998 
 999 好比一個在高版本中才出現的Framework,想在低版本使用他的特性。那你就必須弱鏈接那個使用的Framework,詳見官方的圖解---(其實就是在添加進去的Framework的 required 改爲 optional)
1000 
1001 http://developer.apple.com/library/ios/#documentation/DeveloperTools/Conceptual/XcodeProjectManagement/
1002 130-Files_in_Projects/project_files.html#//apple_ref/doc/uid/TP40002666-SW4 
1003 4、條件編譯for不一樣的SDK
1004 
1005 若是你不止基於一個IOS SDK編譯,你就可能須要爲base 
1006 sdk使用條件化,可使用在Availability.h中的定義。這個.h文件存在於系統的文件夾/usr/include的文件夾下,例如想在
1007 Mac OS X v10.5(而不是IOS)中使用函數 CGColorCreateGenericCMYK
1008 
1009 使用預處理指令for條件編譯
1010 
1011 #ifdef __MAC_OS_X_VERSION_MAX_ALLOWED   
1012     // code only compiled when targeting Mac OS X and not iOS   
1013     // note use of 1050 instead of __MAC_10_5   
1014 #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050   
1015     if (CGColorCreateGenericCMYK != NULL) {   
1016         CGColorCreateGenericCMYK(0.1,0.5.0.0,1.0,0.1);   
1017     } else {   
1018 #endif   
1019     // code to create a color object with earlier technology   
1020 #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050   
1021     }   
1022 #endif   
1023 #endif   
1024 } 
1025 5、尋找出在程序中使用的以過期的實例
1026 
1027 在IOS或Mac 
1028 OS中有時候API會過期,可是過期不表明着那些就從Library或framework中刪除,可是在使用的過程當中會報出warning,而且在不遠的
1029 未來可能會被Apple從中移除。例如咱們在code中使用了過期的函數 HPurge那麼就會報出以下
1030 
1031 'HPurge' is deprecated (declared at /Users/steve/MyProject/main.c:51) 
1032 因此咱們應當在工程中查找出以下的警告而且修改。
1033 
1034 6、肯定操做系統和Framework的版本
1035 
1036 在運行時檢查IOS的版本
1037 
1038 NSString *osVersion = [[UIDevice currentDevice] systemVersion]; 
1039 在運行時檢查Mac OS X用Gestalt function 和 系統版本常量
1040 
1041 另外,對於許多的Framework你能夠在運行時檢查指定Framework的版本。
1042 
1043 例如:Application Kit(NSApplication.h)定義了NSAppKitVersionNumber常量---能夠用來檢查Application Kit Framework的版本
1044 
1045 1046 
1047 APPKIT_EXTERN double NSAppKitVersionNumber;   
1048 #define NSAppKitVersionNumber10_0 577   
1049 #define NSAppKitVersionNumber10_1 620   
1050 #define NSAppKitVersionNumber10_2 663   
1051 #define NSAppKitVersionNumber10_2_3 663.6   
1052 #define NSAppKitVersionNumber10_3 743   
1053 #define NSAppKitVersionNumber10_3_2 743.14   
1054 #define NSAppKitVersionNumber10_3_3 743.2   
1055 #define NSAppKitVersionNumber10_3_5 743.24   
1056 #define NSAppKitVersionNumber10_3_7 743.33   
1057 #define NSAppKitVersionNumber10_3_9 743.36   
1058 #define NSAppKitVersionNumber10_4 824   
1059 #define NSAppKitVersionNumber10_4_1 824.1   
1060 #define NSAppKitVersionNumber10_4_3 824.23   
1061 #define NSAppKitVersionNumber10_4_4 824.33   
1062 #define NSAppKitVersionNumber10_4_7 824.41   
1063 #define NSAppKitVersionNumber10_5 949   
1064 #define NSAppKitVersionNumber10_5_2 949.27   
1065 #define NSAppKitVersionNumber10_5_3 949.33 
1066 因此咱們能夠像以下使用:
1067 
1068 if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_0) {   
1069   /* On a 10.0.x or earlier system */   
1070 } else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_1) {   
1071   /* On a 10.1 - 10.1.x system */   
1072 } else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_2) {   
1073   /* On a 10.2 - 10.2.x system */   
1074 } else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_3) {   
1075   /* On 10.3 - 10.3.x system */   
1076 } else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_4) {   
1077   /* On a 10.4 - 10.4.x system */   
1078 } else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_5) {   
1079   /* On a 10.5 - 10.5.x system */   
1080 } else {   
1081   /* 10.6 or later system */   
1082 } 
1083 跟以上同樣在 NSObjCRuntime.h中用定義了NSFoundationVersionNumber全局常量
1084 
1085 小結:詳解IOS SDK兼容性引導的內容介紹玩玩了,但願經過本文的學習能對你有所幫助!
1086 
1087 原文地址:http://blog.csdn.net/diyagoanyhacker/article/details/6673344
1088 
1089 26、NSDate 與 NSString 轉換
1090 
1091 將字符串 「Fri Nov 11 09:06:27 +0800 2011」 轉換成Date:
1092 
1093     NSDateFormatter *format = [[NSDateFormatter alloc] init];
1094     NSLocale *enLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en-US"];
1095     [format setLocale:enLocale];
1096     [enLocale release];
1097     [format setDateFormat:@"EEE MMM dd HH:mm:ss ZZZ yyyy"];
1098     NSDate *dateTime = [format dateFromString:message];
1099 
1100  
1101 
1102 將Date轉換成字符串:
1103 
1104     NSDate *date = [NSDate date];
1105     NSString * dateString = [format stringFromDate:date];
1106 
1107 //字符串轉換成NSDate 須要設置NSLocale 不然真機上會失敗。
1108 
1109 27、數組中存儲數據查詢
1110 
1111 NSMutableDictionary *userDic1 = [NSMutableDictionary dictionaryWithCapacity:10];
1112     NSMutableDictionary *userDic2 = [NSMutableDictionary dictionaryWithCapacity:10];
1113     [userDic1 setValue:@"Li" forKey:@"name"];
1114     [userDic2 setValue:@"Wang" forKey:@"name"];
1115     
1116     NSArray *userArray = [NSArray arrayWithObjects:userDic1,userDic2,nil];
1117     NSPredicate *namePredicate = [NSPredicate predicateWithFormat:@"SELF.name contains[cd] %@ ",@"L"];
1118     
1119     NSMutableArray *searchArray = [NSMutableArray arrayWithArray:[userArray filteredArrayUsingPredicate:namePredicate]];
1120     
1121     NSLog(@"searchArray  == %@",searchArray);
1122 
1123 28、CoreText 總結
1124 
11251) NSAttributedString
1126 
1127       NSAttributedString 能夠將一段文字中的部分文字設置單獨的字體和顏色。
1128 
1129       與UITouch結合能夠實現點擊不一樣文字觸發不一樣事件的交互功能。
1130 
1131        主要方法:
1132 
1133            - (void)addAttribute:(NSString *)name value:(id)value range:(NSRange)range;
1134 
1135            能夠設置某段文字的字體名稱,顏色,下滑線等信息。
1136 
1137            - (void)removeAttribute:(NSString *)name range:(NSRange)range;
1138 
1139            移除以前設置的字體屬性值。
1140 
1141            - (void)addAttributes:(NSDictionary *)attrs range:(NSRange)range;
1142 
1143            存儲某段文字包含的信息(包括字體屬性或其它,也能夠存儲一些自定義的信息) 
1144 
1145            - (NSDictionary *)attributesAtIndex:(NSUInteger)location effectiveRange:(NSRangePointer)range;
1146 
1147            經過location來獲取某段文字中以前存儲的信息NSDictionary
1148 
1149  
1150 
1151    //設置字體
1152    CTFontRef aFont = CTFontCreateWithName((CFStringRef)textFont.fontName, textFont.pointSize, NULL);
1153    if (!aFont) return;
1154    CTFontRef newFont = CTFontCreateCopyWithSymbolicTraits(aFont, 0.0, NULL, kCTFontItalicTrait, kCTFontBoldTrait);    //將默認黑體字設置爲其它字體 
1155    [self removeAttribute:(NSString*)kCTFontAttributeName range:textRange];
1156    [self addAttribute:(NSString*)kCTFontAttributeName value:(id)newFont range:textRange];
1157    CFRelease(aFont);
1158    CFRelease(newFont);
1159    
1160    //設置字體顏色
1161    [self removeAttribute:(NSString*)kCTForegroundColorAttributeName range:textRange];
1162    [self addAttribute:(NSString*)kCTForegroundColorAttributeName value:(id)textColor.CGColor range:textRange];
1163    
1164    //設置對齊 換行
1165    CTTextAlignment coreTextAlign = kCTLeftTextAlignment;
1166    CTLineBreakMode coreTextLBMode = kCTLineBreakByCharWrapping;
1167    CTParagraphStyleSetting paraStyles[2] =
1168    {
1169        {.spec = kCTParagraphStyleSpecifierAlignment, .valueSize = sizeof(CTTextAlignment), .value = (const void*)&coreTextAlign},
1170        {.spec = kCTParagraphStyleSpecifierLineBreakMode, .valueSize = sizeof(CTLineBreakMode), .value = (const void*)&coreTextLBMode},
1171    };
1172    CTParagraphStyleRef aStyle = CTParagraphStyleCreate(paraStyles, 2);
1173    [self removeAttribute:(NSString*)kCTParagraphStyleAttributeName range:textRange];
1174    [self addAttribute:(NSString*)kCTParagraphStyleAttributeName value:(id)aStyle range:textRange];
1175    CFRelease(aStyle);
1176 
1177  
1178 
11792)Draw NSAttributedString
1180 
1181 
1182        
1183    CGContextRef cgc = UIGraphicsGetCurrentContext();
1184    CGContextSaveGState(cgc);
1185    
1186    //圖像方向轉換
1187    CGContextConcatCTM(cgc, CGAffineTransformScale(CGAffineTransformMakeTranslation(0, self.bounds.size.height), 1.f, -1.f));
1188    
1189    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)weiBoText);
1190    drawingRect = self.bounds;
1191    CGMutablePathRef path = CGPathCreateMutable();
1192    CGPathAddRect(path, NULL, drawingRect);
1193    textFrame = CTFramesetterCreateFrame(framesetter,CFRangeMake(0,0), path, NULL);
1194    CGPathRelease(path);
1195    CFRelease(framesetter);
1196    
1197    CTFrameDraw(textFrame, cgc);
1198    CGContextRestoreGState(cgc);
1199 
12003)圖文混排
1201 
1202      CTFrameRef  textFrame     // coreText 的 frame
1203 
1204      CTLineRef      line             //  coreText 的 line
1205 
1206      CTRunRef      run             //  line  中的部分文字
1207 
1208      相關方法:
1209 
1210    
1211    CFArrayRef CTFrameGetLines    (CTFrameRef frame )      //獲取包含CTLineRef的數組
1212 
1213    void CTFrameGetLineOrigins(
1214    CTFrameRef frame,
1215    CFRange range,
1216    CGPoint origins[] )  //獲取全部CTLineRef的原點
1217 
1218  CFRange CTLineGetStringRange  (CTLineRef line )    //獲取line中文字在整段文字中的Range
1219 
1220  CFArrayRef CTLineGetGlyphRuns  (CTLineRef line )    //獲取line中包含全部run的數組
1221 
1222  CFRange CTRunGetStringRange  (CTRunRef run )     //獲取run在整段文字中的Range
1223 
1224  CFIndex CTLineGetStringIndexForPosition(
1225    CTLineRef line,
1226    CGPoint position )   //獲取點擊處position文字在整段文字中的index
1227 
1228    CGFloat CTLineGetOffsetForStringIndex(
1229    CTLineRef line,
1230    CFIndex charIndex,
1231    CGFloat* secondaryOffset ) //獲取整段文字中charIndex位置的字符相對line的原點的x值
1232 
1233   主要步驟:
1234 
1235        1)計算並存儲文字中保含的全部表情文字及其Range
1236 
1237        2)替換表情文字爲指定寬度的NSAttributedString
1238 
1239            CTRunDelegateCallbacks callbacks;
1240    callbacks.version = kCTRunDelegateVersion1;
1241    callbacks.getAscent = ascentCallback;
1242    callbacks.getDescent = descentCallback;
1243    callbacks.getWidth = widthCallback;
1244    callbacks.dealloc = deallocCallback;
1245    
1246    CTRunDelegateRef runDelegate = CTRunDelegateCreate(&callbacks, NULL);
1247    NSDictionary *attrDictionaryDelegate = [NSDictionary dictionaryWithObjectsAndKeys:
1248                                            (id)runDelegate, (NSString*)kCTRunDelegateAttributeName,
1249                                            [UIColor clearColor].CGColor,(NSString*)kCTForegroundColorAttributeName,
1250                                            nil];
1251    
1252    NSAttributedString *faceAttributedString = [[NSAttributedString alloc] initWithString:@"*" attributes:attrDictionaryDelegate];
1253    
1254    [weiBoText replaceCharactersInRange:faceRange withAttributedString:faceAttributedString];
1255    [faceAttributedString release];    
1256 
1257        3)  根據保存的表情文字的Range計算表情圖片的Frame
1258 
1259                 textFrame 經過CTFrameGetLines 獲取全部line的數組 lineArray
1260 
1261                遍歷lineArray中的line經過CTLineGetGlyphRuns獲取line中包含run的數組 runArray
1262 
1263                遍歷runArray中的run 經過CTRunGetStringRange獲取run的Range
1264 
1265                判斷表情文字的location是否在run的Range
1266 
1267                若是在 經過CTLineGetOffsetForStringIndex獲取x的值 y的值爲line原點的值
1268 
1269        4)Draw表情圖片到計算獲取到的Frame
1270 
1271  
1272 
12733)點擊文字觸發事件
1274 
1275   
1276 
1277   主要步驟:
1278 
1279        1) 根據touch事件獲取點point
1280 
1281        2)   textFrame 經過CTFrameGetLineOrigins獲取全部line的原點
1282 
1283        3) 比較point和line原點的y值獲取點擊處於哪一個line
1284 
1285        4)  line、point 經過CTLineGetStringIndexForPosition獲取到點擊字符在整段文字中的    index   
1286 
1287        5)  NSAttributedString 經過index 用方法-(NSDictionary *)attributesAtIndex:(NSUInteger)location effectiveRange:(NSRangePointer)range  能夠獲取到點擊到的NSAttributedString中存儲的NSDictionary
1288 
1289        6) 經過NSDictionary中存儲的信息判斷點擊的哪一種文字類型分別處理
1290 
1291 23、視頻播放、編輯
1292 
1293 
1294 
1295 
1296  
1297 
1298 轉載: http://www1.huachu.com.cn/read/readbookinfo.asp?sectionid=1000006772
1299 
1300 
1301 對於不一樣的設備,視頻功能是各不相同的。全部的設備都可以回放視頻,可是僅有iPhone 3GS設備有記錄視頻的能力。對於每一個設備而言,都存在API可以讓您檢測哪些功能是可用的和哪些功能是不可用的,這樣就可以針對使用視頻功能的全部用戶建立優秀的用戶體驗。這一節內容討論如何才能將視頻集成到應用程序中,以及如何才能使用特定的設備記錄視頻。
1302 
1303 10.2.1  播放視頻
1304 
1305 iPhone SDK提供了一個簡單的控制器來在應用程序中播放視頻。MPMoviePlayerController類位於MonoTouch.MediaPlayer名稱空間中,它提供了播放影片、準備播放影片和中止播放影片的功能。程序清單10-9說明了如何開始播放視頻。第一行代碼顯示的是實例化一個新的影片播放器對象,並將視頻內容文件路徑傳入其構造函數內。第二行代碼簡單地調用了Play方法,該方法顯示影片播放器並開始播放視頻。
1306 
1307 程序清單10-9  播放視頻文件
1308 
1309 var player = new MPMoviePlayerController(NSUrl.FromFilename("video.mp4"));
1310 
1311 player.Play();
1312 
1313 若是但願使用外部視頻,並以漸進方式下載視頻,而不是直接播放設備上的視頻,那麼就要使用NSUrl的FromString方法,而不是使用FromFilename,並將視頻的URL地址傳入其中。固然,須要使用本身的外部視頻替換這裏的URL字符串。
1314 
1315 var videoUrl = NSUrl.FromString("http://example.com/video.mp4")
1316 
1317 var player = new MPMoviePlayerController(videoUrl);
1318 
1319 player.Play();
1320 
1321 您也許會注意到,在視頻開始播放以前有一個短暫的緩衝週期。這就是所謂的預加載過程。能夠設置視頻播放器上的通知,在視頻已經開始預加載時讓其引起一條消息,這樣就可以顯示加載屏幕,而後在預加載完成後開始顯示視頻。當視頻完成播放或者用戶改變視頻的縮放比例時,也可使用通知引起消息。
1322 
1323 使用NSNotificationCenter類的DefaultCenter屬性添加觀察者,從而在通知產生時引起這些消息。能夠將觀察者看做將事件添加到特定動做上的一種方式,使用字符串做爲建立這些事件的方式,而不是使用您也許已經熟悉的C#內的強類型事件。對於本示例而言,只須要使用通知MPMoviePlayerContentPreloadDidFinishNotification和MPMoviePlayerPlaybackDid- FinishNotification。另外一個通知名爲MPMoviePlayerScalingModeDidChangeNotification。還要添加兩個NSObject類型的類變量,它們能夠做爲預加載和回放完成的觀察者。使用AddObserver方法,爲每一個觀察者傳入一個動做方法,當通知被調用時這些動做方法就會運行。可使用Lambda表達式之內聯方式放置這段代碼。當預加載通知被激活之後,只須要開始播放視頻,所以能夠調用MPMoviePlayerController上的Play方法;當回放通知激活之後,須要移除觀察者,並清除影片播放器實例。可使用活動指示器確保讓用戶知道當應用程序啓動時正在預加載視頻。程序清單10-10給出了完成這項工做的示例代碼。一樣,須要確保改變第8行代碼中的URL,讓其指向選擇的外部視頻。
1324 
1325 程序清單10-10  使用影片播放器觀察者
1326 
1327 MPMoviePlayerController moviePlayer;
1328 
1329 NSObject didFinishPreload, didFinishPlayback;
1330 
1331 
1332 public override void ViewDidLoad()
1333 
1334 {
1335 
1336   base.ViewDidLoad ();
1337 
1338  
1339 
1340   var videoUrl = NSUrl.FromString("http://example.com/video.mp4");
1341 
1342   moviePlayer = new MPMoviePlayerController(videoUrl);
1343 
1344  
1345 
1346   activityIndicator.StartAnimating();
1347 
1348 
1349   var centre = NSNotificationCenter.DefaultCenter;
1350 
1351   var preloadFinish = "MPMoviePlayerContentPreloadDidFinishNotification";
1352 
1353   didFinishPreload = centre.AddObserver(preloadFinish,
1354 
1355      (notify) => {
1356 
1357         Console.WriteLine ("Start playing movie");
1358 
1359         activityIndicator.StopAnimating();
1360 
1361         moviePlayer.Play();
1362 
1363      });
1364 
1365 
1366   var playbackFinished = "MPMoviePlayerPlaybackDidFinishNotification";
1367 
1368   didFinishPlayback = centre.AddObserver(playbackFinished,
1369 
1370      (notify) => {
1371 
1372         Console.WriteLine ("Movie finished, Clean up");
1373 
1374 
1375         centre.RemoveObserver(didFinishPreload);
1376 
1377         centre.RemoveObserver(didFinishPlayback);
1378 
1379 
1380         activityIndicator.Hidden = true;
1381 
1382 
1383         moviePlayer.Dispose();
1384 
1385         moviePlayer = null;
1386 
1387      }); }
1388 
1389 }
1390 
1391 10.2.2  定製視頻播放器
1392 
1393 影片播放器提供的功能是至關有限的,僅容許對兩個屬性根據須要進行調整,這兩個屬性是ScalingMode和MovieControlMode。
1394 
1395 縮放模式對播放影片的長寬比進行設置。可用的長寬比選項爲Fill、AspectFill、AspectFit和None。
1396 
1397 Fill選項用於讓視頻填滿整個屏幕,這樣視頻的邊緣會與屏幕吻合,可是可能沒法保持原有的長寬比。
1398 
1399 AspectFill選項在視頻填滿整個屏幕時不會扭曲視頻,可是確實會對視頻進行裁剪,這樣視頻纔可以無縫地填滿這個屏幕。
1400 
1401 AspectFit選項會保留視頻原有的長寬比,並讓視頻的邊緣儘量地與屏幕吻合,但若是視頻不是徹底吻合,那麼可能會露出背景視圖。
1402 
1403 None選項不會調整視頻,而是按照視頻自身的大小進行播放。
1404 
1405 使用MPMovieScalingMode枚舉,能夠將ScalingMode設置爲這個列表中的任何選項。參見圖10-10~圖10-13,其中給出了每一種縮放模式的示例。播放器的背景設置爲藍色(在這些圖中,背景是以淺灰色打印版本進行顯示的),所以能夠看到視頻大小和播放器大小之間的差別。注意,在這個示例中,Aspect Fit和Fill視頻是同樣的。這是由於視頻的當前長寬比容許視頻的邊緣與屏幕吻合,而無須改變長寬比。
1406 
1407 
140810-1010-11  
1409 
1410 
141110-1210-13  
1412 
1413 另一個能夠針對視頻播放器修改的屬性是MovieControlMode。使用MPMovieControlMode枚舉,能夠將控件模式設置爲Default、Hidden或VolumeOnly。圖10-14和圖10-15給出了Default和VolumeOnly控件模式。Hidden模式隱藏了屏幕上全部默認的動做;若是但願讓本身提供的用戶界面位於視頻的上方,那麼該模式就頗有用。
1414 
1415 
141610-1410-15  
1417 
1418 影片播放器自己是做爲一個關鍵窗口出如今屏幕上的。爲了將自定義界面添加到影片播放器關鍵窗口的上方,能夠從應用程序中具備的窗口列表內獲取該關鍵窗口的引用(關鍵窗口在本質上是窗口框架內能夠得到的最頂層的可見視圖)。而後能夠簡單地將子視圖添加到影片播放器關鍵窗口中。由於影片播放器是以橫屏模式出現的,因此必須對疊加視圖進行變換,從而使其可以與橫屏模式匹配。程序清單10-11說明了如何使用代碼實現此處提到的全部內容。
1419 
1420 程序清單10-11  在視頻播放器上疊加視圖
1421 
1422 public MPMoviePlayerController mPlayer;
1423 
1424 
1425 public override void ViewDidLoad ()
1426 
1427 {
1428 
1429   base.ViewDidLoad ();
1430 
1431 
1432   var button = UIButton.FromType(UIButtonType.RoundedRect);
1433 
1434   button.Frame = new RectangleF(0f, 20f, 320f, 40f);
1435 
1436   button.SetTitle("Play Video", UIControlState.Normal);
1437 
1438   button.TouchUpInside += delegate(object sender, EventArgs e)
1439 
1440   {
1441 
1442      PlayMovie ();
1443 
1444 
1445      var windows = UIApplication.SharedApplication.Windows;
1446 
1447      if(windows.Count() > 1)
1448 
1449      {
1450 
1451         var moviePlayerWindow = UIApplication.SharedApplication.KeyWindow;
1452 
1453         var customView = new MyOverlayView(this);
1454 
1455         moviePlayerWindow.AddSubview(customView);
1456 
1457      }
1458 
1459   };
1460 
1461   this.View.AddSubview(button);
1462 
1463 }
1464 
1465 
1466 void PlayMovie ()
1467 
1468 {
1469 
1470   var url = NSUrl.FromFilename("video.mp4");
1471 
1472   mPlayer = new MPMoviePlayerController(url);
1473 
1474   mPlayer.Play();
1475 
1476 }
1477 
1478 
1479 ...
1480 
1481 
1482 public class MyOverlayView : UIView
1483 
1484 {
1485 
1486   public MyOverlayView (MainViewController mvc)
1487 
1488   {
1489 
1490      this.Frame = new RectangleF(0f, 0f, 320f, 480f);
1491 
1492      this.Transform = CGAffineTransform.MakeRotation((float)(Math.PI / 2));
1493 
1494 
1495      UIButton button = UIButton.FromType(UIButtonType.RoundedRect);
1496 
1497      button.SetTitle("Pause", UIControlState.Normal);
1498 
1499      button.Frame = new RectangleF(65f, 360f, 190f, 32f);
1500 
1501      button.TouchUpInside += delegate(object sender, EventArgs e) {
1502 
1503         Console.WriteLine ("Paused the video");
1504 
1505         mvc.mPlayer.Pause();
1506 
1507      };
1508 
1509 
1510      this.AddSubview(button);
1511 
1512   }
1513 
1514 }
1515 
1516 圖10-16顯示的是在程序清單10-11中建立的疊加視圖。
1517 
1518 
151910-16  
1520 
1521 10.2.3  選取視頻
1522 
1523 爲了讓用戶能夠從存儲在設備上的視頻列表中選取視頻,可使用UIImagePickerController,在本章前面已經使用過該類。由於面向iPhone的視頻功能很是相似於攝像頭功能,因此看到視頻功能屬於UIImagePickerController類的組成部分並不使人感到驚奇。在程序清單10-6中,咱們使用IsSourceTypeAvailable方法來肯定設備是否具備攝像頭。由於視頻功能僅限於iPhone3GS模型,因此只是弄清楚是否存在攝像頭並不足夠。這時就須要使用UIImagePickerController類上的AvailableMediaTypes靜態方法。
1524 
1525 AvailableMediaTypes方法以源類型做爲輸入,返回設備上可用媒體類型的數組。圖像的媒體類型爲public.image,而視頻的媒體類型爲public.movie。若是該方法返回public.movie類型,那麼能夠將UIImagePickerController實例的MediaTypes屬性設置爲僅有public.movie媒體類型。程序清單10-12給出了以這種方式設置的選取器。
1526 
1527 程序清單10-12  使用圖像選取器控制器選取視頻
1528 
1529 if (HasVideoSupport())
1530 
1531 {
1532 
1533   UIImagePickerController picker = new UIImagePickerController();
1534 
1535   picker.SourceType = UIImagePickerControllerSourceType.PhotoLibrary;
1536 
1537   picker.MediaTypes = new []{"public.movie"};
1538 
1539   picker.Delegate = new MyImagePickerDelegate(this);
1540 
1541   this.PresentModalViewController(picker, true);
1542 
1543 }
1544 
1545 else
1546 
1547 {
1548 
1549   using (var alert = new UIAlertView("Whoops", "No video support found",
1550 
1551                                       null, "Ok!", null))
1552 
1553   {
1554 
1555      alert.Show();
1556 
1557   }
1558 
1559 }
1560 
1561 
1562 ...
1563 
1564 
1565 bool HasVideoSupport()
1566 
1567 {
1568 
1569   var cameraType = UIImagePickerControllerSourceType.Camera;
1570 
1571   var cameraSupport =
1572 
1573                  UIImagePickerController.IsSourceTypeAvailable(cameraType);
1574 
1575   return (!cameraSupport) ? false :
1576 
1577          UIImagePickerController.AvailableMediaTypes(cameraType)
1578 
1579                                        .Contains("public.movie");
1580 
1581 }
1582 
1583 在顯示該選取器時,注意到您只看到了視頻,由於視頻是能夠選取的惟一的媒體類型。圖10-17說明了如何顯示只選取視頻的選取器。
1584 
1585 
158610-17  
1587 
1588 在選取視頻之後,該選取器使用與圖像選取器相同的回調:FinishedPickingMedia。NSDictionary帶有兩個鍵:UIImagePickerControllerMediaURL和UIImagePickerControllerMediaType。媒體URL包含一個指向所選擇視頻的臨時位置的NSUrl對象。這就是您能夠處理視頻的地方—— 要麼將視頻移動到Documents文件夾中,要麼經過其餘方式使用視頻。臨時視頻存儲在應用程序的tmp文件夾中,OS在認爲合適的時候會將其清除。
1589 
1590 10.2.4  記錄視頻
1591 
1592 使用iPhone記錄視頻很是相似於使用iPhone進行拍照。在前一個示例中,能夠僅將源類型設置爲攝像頭而不是圖片庫的默認源類型,全部這些設置都是爲了記錄視頻而不是拍攝照片。固然,這就是假設您已經使用AvailableMediaTypes方法驗證了該設備能夠記錄視頻。注意,攝像頭控件會發生變化,從而反映出是記錄視頻而不是拍攝照片。做爲可選項,能夠選擇經過將ShowsCameraControls設置爲false來隱藏攝像頭控件;然而,在編寫本書的時候,若是不使用默認的攝像頭控件,那麼尚未方式能夠經過編程來記錄視頻。程序清單10-13是設置UIImagePickerController以記錄視頻的一個示例。圖10-18顯示的是視頻記錄屏幕。
1593 
1594 程序清單10-13  記錄視頻
1595 
1596 public override void ViewDidLoad ()
1597 
1598 {
1599 
1600   base.ViewDidLoad ();
1601 
1602 
1603   UIButton button = UIButton.FromType(UIButtonType.RoundedRect);
1604 
1605   button.Frame = new RectangleF(0f, 30f, 320, 40f);
1606 
1607   button.SetTitle("Record Video", UIControlState.Normal);
1608 
1609   button.TouchUpInside += delegate(object sender, EventArgs e) {
1610 
1611 
1612      var cameraType = UIImagePickerControllerSourceType.Camera;
1613 
1614      if(HasVideoSupport())
1615 
1616      {
1617 
1618         UIImagePickerController picker = new UIImagePickerController();
1619 
1620         picker.SourceType = cameraType;
1621 
1622         picker.MediaTypes = new []{"public.movie"};
1623 
1624         picker.Delegate = new MyImagePickerDelegate(this);
1625 
1626         this.PresentModalViewController(picker, true);
1627 
1628      }
1629 
1630      else
1631 
1632      {
1633 
1634         using (var alert = new UIAlertView("Whoops",
1635 
1636                           "No video support found", null, "Ok!", null))
1637 
1638         {
1639 
1640            alert.Show();
1641 
1642         }
1643 
1644      }
1645 
1646   };
1647 
1648   this.View.AddSubview(button);
1649 
1650 }
1651 
1652 
1653 ...
1654 
1655 
1656 bool HasVideoSupport()
1657 
1658 {
1659 
1660   var cameraType = UIImagePickerControllerSourceType.Camera;
1661 
1662   var cameraSupport =
1663 
1664                  UIImagePickerController.IsSourceTypeAvailable(cameraType);
1665 
1666   return (!cameraSupport) ? false :
1667 
1668          UIImagePickerController.AvailableMediaTypes(cameraType)
1669 
1670                                        .Contains("public.movie");
1671 
1672 }
1673 
1674 
167510-18  
1676 
1677 在記錄視頻時,還能夠設置視頻記錄的質量。質量越低,那麼獲得的視頻文件越小。能夠像下面的代碼這樣使用UIImagePickerControllerQualityType枚舉設置圖像選取器的VideoQuality屬性:
1678 
1679 picker.VideoQuality =  UIImagePickerControllerQualityType.Low;
1680 
1681 該枚舉提供3個質量選項:High、Medium和Low。視頻記錄中使用的默認設置是Medium。在記錄視頻時可使用的另一個屬性是VideoMaximumDuration,這個屬性用於設置記錄視頻的最長持續時間(單位爲秒)。視頻最長能夠是10分鐘,記錄視頻的默認時間值也是10分鐘。
1682 
1683 10.2.5  編輯視頻
1684 
1685 採用與經過UIImagePickerController編輯圖像相同的方式,在記錄或選取視頻時也能夠將AllowEditing屬性設置爲true。這樣,從圖像選取器中選取了視頻之後,就可以有一個接口對視頻進行裁剪。與編輯圖像時不一樣,在完成編輯時,只會使用NSDictionary中的UIImagePickerCon-trollerMediaURL鍵得到臨時裁剪或編輯的視頻(而不是原始視頻),該鍵在選擇或記錄視頻後可用。臨時建立的視頻最終會被設備自動地清除。UIImagePickerControllerMediaURL對象屬於NSUrl類型,須要將該視頻對象強制轉換爲NSUrl類型來提取定位該文件所需的Path屬性。圖10-19顯示了圖像選取器視頻編輯器的外觀。
1686 
1687 
168810-19
1689 
1690 可是,視頻選取器不是編輯視頻最值得推薦的方式。對於編輯視頻而言,最好使用專門的UIVideoEditorController類做爲替代。該視頻編輯器控制器爲您提供了一個編輯窗口,它相似於圖像選取器所使用的編輯窗口。然而,注意到用戶有兩個選項能夠選擇:Cancel和Save。UIVideoEditorController類對此提供了3個不一樣的事件:
1691 
1692 UserCancelled  當用戶單擊Cancel按鈕時處理這個事件。
1693 
1694 Saved  當用戶單擊Save按鈕時處理該事件。
1695 
1696 Failed  當產生沒法預料的錯誤時會引起該事件,例如視頻的格式沒法編輯這樣的錯誤。
1697 
1698 Saved事件返回編輯好的視頻文件的路徑,Failed事件返回一個NSError對象,UserCancelled事件不會返回任何額外的信息。若是但願得到原始文件的路徑,那麼能夠將發送方強制轉換爲UIVideoEditorController對象,而後使用該對象的VideoPath屬性。
1699 
1700 
1701 視頻編輯器只能用在直屏模式中
1702 
1703 
1704 
1705 
1706 有了視頻編輯器之後,經過分別設置VideoQuality和VideoMaximumDuration屬性,就能夠將編輯好的視頻設置爲較低的質量和強制編輯好的視頻具備最大時間長度。
1707 
1708 建立視頻編輯界面是至關直觀的。實例化一個新的UIVideoEditorController,將VideoPath設置爲但願編輯的視頻的路徑,而後將視頻編輯器做爲一個模態視圖展現。由於沒法知道運行該應用程序的iPhone是否支持對視頻進行編輯,因此須要使用視頻編輯器的靜態方法CanEditVideoAtPath。傳入視頻路徑,若是該視頻能夠編輯,那麼該方法就返回true。程序清單10-14給出了一個建立專用視頻編輯器界面的示例,圖10-20給出了UIVideoEditorController界面的顯示外觀。
1709 
1710 程序清單10-14  使用專用視頻編輯器界面
1711 
1712 if(UIVideoEditorController.CanEditVideoAtPath(ChosenVideoPath))
1713 
1714 {
1715 
1716   var videoEditor = new UIVideoEditorController();
1717 
1718   videoEditor.VideoPath = ChosenVideoPath;
1719 
1720   videoEditor.Saved += delegate(object sender, UIPathEventArgs e) {
1721 
1722      this.DismissModalViewControllerAnimated(true);
1723 
1724      // Handle edited video with e.Path
1725 
1726   };
1727 
1728   videoEditor.Failed += delegate(object sender, NSErrorEventArgs e) {
1729 
1730      this.DismissModalViewControllerAnimated(true);
1731 
1732      // Handle error here with e.Error
1733 
1734   };
1735 
1736   videoEditor.UserCancelled += delegate(object sender, EventArgs e) {
1737 
1738      this.DismissModalViewControllerAnimated(true);
1739 
1740      // Handle cancel
1741 
1742   };
1743 
1744   this.PresentModalViewController(videoEditor, true);
1745 
1746 }
1747 
1748 
1749 圖10-20
1750 
1751 10.2.6  將視頻保存到相冊
1752 
1753 在將圖像保存到相冊時,要使用UIImage類上的靜態方法保存文件。由於對視頻文件的全部引用都使用路徑而不是內存中的對象,因此UIVideo靜態類提供了將視頻保存到相冊中所需的方法。視頻功能僅限於特定的設備,所以在將視頻保存到相冊以前,須要檢查一下該設備是否可以真正將視頻保存到其相冊中。靜態方法IsCompatibleWithSavedPhotosAlbum提供了這種功能,若是傳入能夠保存到相冊的視頻的路徑,那麼該方法就會返回true。
1754 
1755 爲了將視頻保存到相冊中,一旦經過檢查肯定該設備確實能夠保存視頻,那麼就可使用UIVideo類上的靜態方法SaveToPhotosAlbum。將但願保存的視頻的路徑傳入該方法,當保存視頻之後會觸發一個回調函數。程序清單10-15給出了完成這些任務的代碼。
1756 
1757 程序清單10-15  將視頻保存到相冊
1758 
1759 var videoPath = videoSavePath;
1760 
1761 if(UIVideo.IsCompatibleWithSavedPhotosAlbum(videoPath))
1762 
1763 {
1764 
1765   UIVideo.SaveToPhotosAlbum(videoPath, delegate (string path,
1766 
1767                                                  NSError errors)
1768 
1769   {
1770 
1771      using (var alert = new UIAlertView("Success", "Video saved!",
1772 
1773                                         null, "Ok!", null))
1774 
1775      {
1776 
1777         alert.Show();
1778 
1779      }
1780 
1781   });
1782 
1783 }
1784 
1785 
1786 24、CoreText基礎-字體必修課
1787 
1788 
1789 轉自:http://www.dreamingwish.com/dream-2011/coretext-ji-chu-font-basis.html
1790 
1791 介紹一些字體的術語,以及對應的英文名稱
1792 
1793 字體(Font):是一系列字號、樣式和磅值相同的字符(例如:10磅黑體Palatino)。現多被視爲字樣的同義詞
1794 
1795 字面(Face):是全部字號的磅值和格式的綜合
1796 
1797 字體集(Font family):是一組相關字體(例如:Franklin family包括Franklin Gothic、Fran-klinHeavy和Franklin Compressed)
1798 
1799 磅值(Weight):用於描述字體粗度。典型的磅值,從最粗到最細,有極細、細、book、中等、半粗、粗、較粗、極粗
1800 
1801 樣式(Style):字形有三種形式:Roman type是直體;oblique type是斜體;utakuc type是斜體兼曲線(比Roman type更像書法體)。
1802 
1803 x高度(X height):指小寫字母的平均高度(以x爲基準)。磅值相同的兩字母,x高度越大的字母看起來比x高度小的字母要大
1804 
1805 Cap高度(Cap height):與x高度類似。指大寫字母的平均高度(以C爲基準)
1806 
1807 下行字母(Descender):例如在字母q中,基線如下的字母部分叫下伸部分
1808 
1809 上行字母(Ascender):x高度以上的部分(好比字母b)叫作上伸部分
1810 
1811 基線(Baseline):一般在x、v、b、m下的那條線
1812 
1813 描邊(Stroke):組成字符的線或曲線。能夠加粗或改變字符形狀
1814 
1815 襯線(Serif):用來使字符更可視的一條水平線。如字母左上角和下部的水平線。
1816 
1817 無襯線(Sans Serif):可讓排字員不使用襯線裝飾。
1818 
1819 方形字(Block):這種字體的筆畫使字符看起來比無襯線字更顯眼,但還不到常見的襯線字的程度。例如Lubalin Graph就是方形字,這種字看起來好像是木頭塊刻的同樣
1820 
1821 手寫體腳本(Calligraphic script):是一種仿效手寫體的字體。例如Murray Hill或者Fraktur字體
1822 
1823 藝術字(Decorative):像繪畫般的字體
1824 
1825 Pi符號(Pisymbol):非標準的字母數字字符的特殊符號。例如Wingdings和Mathematical Pi
1826 
1827 連寫(Ligature):是一系列連寫字母如fi、fl、ffi或ffl。因爲字些字母形狀的緣由常常被連寫,故排字員已習慣將它們連寫。
1828 
1829 
1830 
1831 25、準確計算CoreText高度的方法
1832 
1833 - (int)getAttributedStringHeightWithString:(NSAttributedString *)  string  WidthValue:(int) width
1834 {
1835    int total_height = 0;
1836    
1837    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)string);    //string 爲要計算高度的NSAttributedString
1838    CGRect drawingRect = CGRectMake(0, 0, width, 1000);  //這裏的高要設置足夠大
1839    CGMutablePathRef path = CGPathCreateMutable();
1840    CGPathAddRect(path, NULL, drawingRect);
1841    CTFrameRef textFrame = CTFramesetterCreateFrame(framesetter,CFRangeMake(0,0), path, NULL);
1842    CGPathRelease(path);
1843    CFRelease(framesetter);
1844    
1845    NSArray *linesArray = (NSArray *) CTFrameGetLines(textFrame);
1846    
1847    CGPoint origins[[linesArray count]];
1848    CTFrameGetLineOrigins(textFrame, CFRangeMake(0, 0), origins);
1849    
1850    int line_y = (int) origins[[linesArray count] -1].y;  //最後一行line的原點y座標
1851    
1852    CGFloat ascent;
1853    CGFloat descent;
1854    CGFloat leading;
1855    
1856    CTLineRef line = (CTLineRef) [linesArray objectAtIndex:[linesArray count]-1];
1857    CTLineGetTypographicBounds(line, &ascent, &descent, &leading);
1858    
1859    total_height = 1000 - line_y + (int) descent +1;    //+1爲了糾正descent轉換成int小數點後捨去的值
1860    
1861    CFRelease(textFrame);
1862    
1863    return total_height;
1864    
1865 }
1866 
1867  
1868 
1869 //關於line座標位置y爲下圖黑線所在位置 descent爲黑線下部分字體的高度
1870 
1871 //關於字體各部分高度說明  http://ios-iphone.diandian.com/post/2012-03-29/18055023  
1872 
1873 
1874 26、自定義拷貝、粘貼窗口
1875 
18761)、重寫canBecomeFirstResponder方法
1877 
1878   - (BOOL)canBecomeFirstResponder{
1879   
1880   [super canBecomeFirstResponder];
1881   return YES;
1882 }
1883 
18842)、建立自定義UIMenuController
1885 
1886   UIMenuItem *share = [[UIMenuItem alloc] initWithTitle:@"分享" action:@selector(share:)];
1887    UIMenuItem *email = [[UIMenuItem alloc] initWithTitle:@"郵件" action:@selector(email:)];
1888    UIMenuItem *print = [[UIMenuItem alloc] initWithTitle:@"打印" action:@selector(print:)];
1889 
1890    UIMenuController *menu = [UIMenuController sharedMenuController];
1891    [menu setMenuItems:[NSArray arrayWithObjects:share, email,print, nil]];
1892    [menu setTargetRect:self.frame inView:self.superview];
1893    [menu setMenuVisible:YES animated:YES];
1894 
18953)、判斷顯示哪一個menu
1896 
1897 - (BOOL)canPerformAction:(SEL)action withSender:(id)sender
1898 {
1899   [super canPerformAction:action withSender:sender];
1900  
1901   if ( action == @selector(share:) || action == @selector(email:) || action == @selector(print:))
1902   {
1903       return YES;    
1904   }
1905   else
1906   {
1907       return NO;
1908   }
1909 }
1910 
1911  
1912 
1913 
1914 27、iOS本地推送通知方法
1915 
1916   
1917 可在應用後臺執行時,本地彈出推送通知,也能夠定時觸發推送。
1918 
1919 - (void)applicationDidEnterBackground:(UIApplication *)application
1920 {
1921    
1922    UIDevice* device = [UIDevice currentDevice];
1923    
1924    BOOL backgroundSupported = NO;
1925    
1926    if ([device respondsToSelector:@selector(isMultitaskingSupported)])
1927    {    
1928        backgroundSupported = device.multitaskingSupported;
1929    }
1930    if (backgroundSupported && _bgTask==UIBackgroundTaskInvalid)
1931    {
1932        UIApplication *app = [UIApplication sharedApplication];
1933        
1934        _bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
1935        }];  
1936        
1937        
1938        dispatch_async(dispatch_get_main_queue(), ^{
1939            
1940            while (app.applicationState==UIApplicationStateBackground && _bgTask!=UIBackgroundTaskInvalid  && [app backgroundTimeRemaining] > 10)  
1941            {
1942                [NSThread sleepForTimeInterval:1];
1943                NSLog(@"background task %d left left  time %d.", _bgTask, (int)[app backgroundTimeRemaining]);
1944                                
1945                if ([app backgroundTimeRemaining] < 580)
1946                {
1947                    UILocalNotification *localNotif = [[UILocalNotification alloc] init];
1948                    if (localNotif)
1949                    {
1950                        localNotif.alertBody = [NSString stringWithString:@"測試本地通知消息,後臺提示功能。"];
1951                        localNotif.alertAction = NSLocalizedString(@"查看", nil);
1952                        localNotif.soundName = UILocalNotificationDefaultSoundName;
1953                        localNotif.applicationIconBadgeNumber = 1;            
1954                        [application presentLocalNotificationNow:localNotif];
1955                        [localNotif release];
1956                        break;
1957                    }
1958                }
1959            }
1960            
1961            NSLog(@"background task %d finished.", _bgTask);     
1962            [app endBackgroundTask:_bgTask];
1963            _bgTask = UIBackgroundTaskInvalid;   
1964               
1965        });      
1966    }
1967 
1968 }
1969 
1970 28、CoreText繪製文本出現行間距不等及解決辦法
1971 
1972 
1973 轉自: http://willonboy.tk/?p=1163
1974 
1975 
1976 
1977 
1978 
1979 
1980 
1981 
1982 
1983 
1984 
1985 
1986 
1987 
1988 
1989 
1990 
1991  
1992 
1993 
1994 最終在http://www.cocoanetics.com/2012/02/radar-coretext-line-spacing-bug/
1995 
1996 找到了DTCoreText庫
1997 
1998 
1999 Radar: 「CoreText Line Spacing Bug」 b 05, 2012
2000 
2001 I finally got around to report an annoying bug in CoreText that has been bugging us in DTCoreText until I wrote a method to correct line origins as a workaround. rdar://10810114
2002 
2003 The annoying thing about this bug is that it adds visual noise to otherwise pristinely rendered text. Especially on larger font sizes you see that additional space appears before each CTLine that ends with a paragraph break (\n).
2004 
2005 UPDATE: This is a duplicate of rdar://9931615.
2006 
2007 
2008 
2009 CoreText Line Spacing BugSummary
2010 
2011 CoreText inserts too much space before any line that ends with a \n. This extra space depends on the font and font size. On large print this causes visual noise by not being uniform.
2012 
2013 Steps to Reproduce
2014 
2015 Create a CTFrame from a CTFrameSetter with a string that is long enough to wrap and that contains paragraph breaks. Use a non-UI font, like for example AriaMT.
2016 
2017 Expected Results
2018 
2019 Line origins should be spaced by exactly the same distance for identical text and identical attributes.
2020 
2021 Actual Results
2022 
2023 Each line that ends with a paragraph break is shifted down. With the system UI font, size 54 baselines are spaced exactly 64 pixels apart. With ArialMT, size 54, baseline spacing differs between 62 and 65.
2024 
2025 Regression
2026 
2027 This has been a bug since before iOS 4.3.
2028 
2029 Notes
2030 
2031 This does not occur with all fonts, Using a system font the spacing is precisely correct. I have attached a project to demonstrate the issue. See TextView.m.
2032 
2033 It appears that the text metrics for an (invisible) paragraph glyph are miscalculated. Since the glyph is not visible you’d expect neither and ascender nor descender value. But instead the descender is too large. If you walk through the entire line and get the maximum ascenders and descenders the value is correct if you omit the \n in this calculation.
2034 
2035 In short: A trailing \n messes up the font metrics for the entire CTLine.
2036 
2037 Attachment: CoreTextLineOrigins Demo Project
相關文章
相關標籤/搜索