溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

IOS開發(fā)有用的小知識(shí)點(diǎn)有哪些

發(fā)布時(shí)間:2021-12-24 15:19:16 來源:億速云 閱讀:95 作者:小新 欄目:移動(dòng)開發(fā)

這篇文章給大家分享的是有關(guān)IOS開發(fā)有用的小知識(shí)點(diǎn)有哪些的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。

1、獲取系統(tǒng)語言設(shè)置

NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];

NSArray *languages = [userDefault objectForKey:@"AppleLanguages"];

NSString *preferredLang = [languages objectAtIndex:0];

2、緩存路徑下文件大小

- (unsigned long long int) cacheFolderSize

{

NSFileManager *_manager = [NSFileManager defaultManager];

NSArray *_cachePaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
                       NSUserDomainMask, YES);

NSString *_cacheDirectory = [_cachePaths objectAtIndex:];

NSArray *_cacheFileList;

NSEnumerator *_cacheEnumerator;

NSString *_cacheFilePath;

unsigned long long int _cacheFolderSize = ;

_cacheFileList = [ _manager subpathsAtPath:_cacheDirectory];

_cacheEnumerator = [_cacheFileList objectEnumerator];

while (_cacheFilePath = [_cacheEnumerator nextObject])

{

NSDictionary *_cacheFileAttributes = [_managerfileAttributesAtPath:

[_cacheDirectory  stringByAppendingPathComponent:_cacheFilePath]

traverseLink:YES];

_cacheFolderSize += [_cacheFileAttributes fileSize];

}

// 單位是字節(jié)

return _cacheFolderSize;

}

3、Popover push 時(shí) Frame無法改變解決辦法

在popover中的ViewController中實(shí)現(xiàn):

- (void)viewWillAppear:(BOOL)animated
{

CGSize size = CGSizeMake(320, 480); // size of view in popover

self.contentSizeForViewInPopover = size;

[super viewWillAppear:animated];

}

4、tableview滑動(dòng)導(dǎo)致NSTimer和委托回調(diào)停止解決辦法

/ /請(qǐng)求回調(diào)

NSURLRequest * 請(qǐng)求 = ...

scheduleInRunLoop :[ NSRunLoop currentRunLoop ]
                     forMode :NSRunLoopCommonModes ]
[ 連接開始] / /定時(shí)器回調(diào)

NSTimer * updateTimer = [NSTimer scheduledTimerWithTimeInterval:0.01f目標(biāo):自我選擇:選擇(updatePencent)的UserInfo:無重復(fù):是];

* NSRunLoop主要= [NSRunLoop currentRunLoop]
[主要addTimer:updateTimer forMode:NSRunLoopCommonModes];

5、手勢(shì)識(shí)別類

UIGestureRecognizer

6、SFHFKeychainUtils 存儲(chǔ)信息

蘋果SDK自帶的就有密碼保護(hù),使用方法很簡(jiǎn)單,如下:

1、引入Security.frameWork框架。

2、引入頭文件:SFHKeychainUtils.h.

3、存密碼:

[SFHFKeychainUtils storeUsername:@"dd" andPassword:@"aa"forServiceName:SERVICE_NAMEupdateExisting:1 error:nil];

[SFHFKeychainUtils deleteItemForUsername:@"dd" andServiceName:SERVICE_NAME error:nil];

4、取密碼:

NSString *passWord = [SFHFKeychainUtils getPasswordForUsername:@"dd"andServiceName:SERVICE_NAMEerror:nil];

7、missing required architecture i386 in file 解決辦法

在TargetInfo里面修改 Framework Search Pasths 刪除里面內(nèi)容就可以了。

8、view 放大縮小動(dòng)畫效果

//創(chuàng)建縮小了的視圖
myWeiBoImageVC = [[UIViewController alloc] init];
myWeiBoImageVC.view.clipsToBounds = YES;
myWeiBoImageVC.view.alpha = 0.0;
myWeiBoImageVC.view.frame = CGRectMake(64, 0, 1024-64, 768-20);
[self.view addSubview:myWeiBoImageVC.view];

CGAffineTransform newTransform =
CGAffineTransformScale(myWeiBoImageVC.view.transform, 0.1, 0.1);
[myWeiBoImageVC.view setTransform:newTransform];
myWeiBoImageVC.view.center = CGPointMake(670, 100);

[self performSelector:@selector(p_w_picpathViewControllerBigAnimation)];

//放大剛剛創(chuàng)建縮小后的視圖
- (void)p_w_picpathViewControllerBigAnimation{

 [UIView beginAnimations:@"p_w_picpathViewBig" context:nil];
 [UIView setAnimationDuration:0.5];  
 CGAffineTransform newTransform =      CGAffineTransformConcat(myWeiBoImageVC.view.transform, CGAffineTransformInvert(myWeiBoImageVC.view.transform));
 [myWeiBoImageVC.view setTransform:newTransform];
 myWeiBoImageVC.view.alpha = 1.0;
 myWeiBoImageVC.view.center = CGPointMake(416, 510);
 [UIView commitAnimations];

}

//縮小視圖 隱藏

- (void)p_w_picpathViewControllerSmallAnimation{

 [UIView beginAnimations:@"p_w_picpathViewSmall" context:nil];
 [UIView setAnimationDuration:0.5];
 CGAffineTransform newTransform = CGAffineTransformScale(myWeiBoImageVC.view.transform, 0.1, 0.1);
 [myWeiBoImageVC.view setTransform:newTransform];
 myWeiBoImageVC.view.center = CGPointMake(670, 100);
 [UIView commitAnimations];

}

9、UIScrollView 控制View縮放

allImageScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 768, 1024)];
allImageScrollView.minimumZoomScale = 0.3;
allImageScrollView.maximumZoomScale = 1.0;
allImageScrollView.backgroundColor = [UIColor clearColor];
allImageScrollView.delegate = self;
[self.view addSubview:allImageScrollView];

mPicStatusesViewController = [[PicStatusesViewController alloc] init];
[allImageScrollView addSubview:mPicStatusesViewController.view];

//UIScrollView Delegete 實(shí)現(xiàn)

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView

{
 return mPicStatusesViewController.view; //返回ScrollView上添加的需要縮放的視圖
}

- (void)scrollViewDidZoom:(UIScrollView *)scrollView

{
 //縮放操作中被調(diào)用
}

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale

{
 //縮放結(jié)束后被調(diào)用
}

10、iOS3.2 播放視頻

NSString *urlString = [NSString stringWithString:@"視頻url"];

NSURL *movieUrl = [[NSURL alloc] initWithString:urlString];

MPMoviePlayerController *myMoviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:movieUrl];
myMoviePlayer.view.frame = CGRectMake(250, 250, 350, 350);
[self.view addSubview:myMoviePlayer.view];  
myMoviePlayer.shouldAutoplay = YES;
myMoviePlayer.scalingMode= MPMovieScalingModeAspectFit;
[myMoviePlayer play];

11、谷歌地圖翻起動(dòng)畫效果

CATransition *animation = [CATransition animation];
 [animation setDelegate:self];
 [animation setDuration:0.35];
 [animation setTimingFunction:UIViewAnimationCurveEaseInOut];
 if (!curled){

animation.type = @"pageCurl";
   animation.fillMode = kCAFillModeForwards;
   animation.endProgress = 0.40;
 } else {
   animation.type = @"pageUnCurl";
   animation.fillMode = kCAFillModeBackwards;
   animation.startProgress = 0.30;
 }
 [animation setRemovedOnCompletion:NO];
 [self.view exchangeSubviewAtIndex:0 withSubviewAtIndex:1];

 [self.view.layer addAnimation:animation forKey:@"pageCurlAnimation"];

12、給View添加陰影 和邊框

UIImageView *imgvPhoto = [UIImageView alloc] init];

//添加邊框
 CALayer *layer = [_imgvPhoto layer];
 layer.borderColor = [[UIColor whiteColor] CGColor];
 layer.borderWidth = 5.0f;
//添加四個(gè)邊陰影
 _imgvPhoto.layer.shadowColor = [UIColor blackColor].CGColor;
 _imgvPhoto.layer.shadowOffset = CGSizeMake(0, 0);
 _imgvPhoto.layer.shadowOpacity = 0.5;
 _imgvPhoto.layer.shadowRadius = 10.0;
//添加兩個(gè)邊陰影
 _imgvPhoto.layer.shadowColor = [UIColor blackColor].CGColor;
 _imgvPhoto.layer.shadowOffset = CGSizeMake(4, 4);
 _imgvPhoto.layer.shadowOpacity = 0.5;
 _imgvPhoto.layer.shadowRadius = 2.0;

13、使用NSTimer與UIView動(dòng)畫實(shí)現(xiàn)飄雪效果

viewDidLoad事件中,增加一個(gè)圖片及定時(shí)器并啟動(dòng),這里的pic請(qǐng)?jiān)陬^文件中定義。

-(void)viewDidLoad{
[super viewDidLoad];
self.pic = [UIImage p_w_picpathNamed:@"snow.png"];//初始化圖片
//啟動(dòng)定時(shí)器,實(shí)現(xiàn)飄雪效果
[NSTimer scheduledTimerWithTimeInterval:(0.2) target:self selector:@selector(ontime) userInfo:nil repeats:YES];
}

然后再實(shí)現(xiàn)定時(shí)器定時(shí)調(diào)用的ontime方法:
-(void)ontime{
UIImageView *view = [[UIImageView alloc] initWithImage:pic];//聲明一個(gè)UIImageView對(duì)象,用來添加圖片
view.alpha = 0.5;//設(shè)置該view的alpha為0.5,半透明的
int x = round(random()20);//隨機(jī)得到該圖片的x坐標(biāo)
int y = round(random()20);//這個(gè)是該圖片移動(dòng)的最后坐標(biāo)x軸的
int s = round(random())+10;//這個(gè)是定義雪花圖片的大小
int sp = 1/round(random()0)+1;//這個(gè)是速度
view.frame = CGRectMake(x, -50, s, s);//雪花開始的大小和位置
[self.view addSubview:view];//添加該view
[UIView beginAnimations:nil context:view];//開始動(dòng)畫
[UIView setAnimationDuration:10*sp];//設(shè)定速度
view.frame = CGRectMake(y, 500, s, s);//設(shè)定該雪花最后的消失坐標(biāo)
[UIView setAnimationDelegate:self];
[UIView commitAnimations];
}

14、配置Xcode 看程序崩潰信息

1、在xcode中的左側(cè)目錄中找到Executables 打開

2、雙擊和工程名一樣的文件。

3、在打開的文件中的Arguments選項(xiàng),在下面的框中加入Name: NSZombieEnabled 設(shè)置value為YES。

15、程序中發(fā)送郵件和檢測(cè)設(shè)備郵箱是否被配置

-(void)addEmail{

Class mailClass = (NSClassFromString(@"MFMailComposeViewController"));

if (mailClass != nil){

if ([mailClass canSendMail]){

[self displayComposerSheet];

}else{

[self launchMailAppOnDevice];

}

}else{

[self launchMailAppOnDevice];

}

}

-(void)displayComposerSheet

{

MFMailComposeViewController *controller = [[MFMailComposeViewController alloc] init];

controller.navigationBar.tag = 1002;

[self.navigationController.navigationBar setNeedsDisplay];

controller.mailComposeDelegate = self;

[controller setSubject:@"意見反饋"];

[controller setToRecipients:[[NSArray alloc] initWithObjects:@"555@cifco.net.cn",nil]];

NSString *emailBody = nil;

[controller setMessageBody:emailBody isHTML:YES];

[self presentModalViewController:controller animated:YES];

[controller release];

}

#pragma mark mailComposeDelegate ----

- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error

{

if (result == MFMailComposeResultSent)

{

[self dismissModalViewControllerAnimated:YES];

}

if (result == MFMailComposeResultSaved)

{

[self dismissModalViewControllerAnimated:YES];

}

if (result == MFMailComposeResultFailed)

{

Emailalert = [[UIAlertView alloc] initWithTitle:@"" message:@"發(fā)送失敗" delegate:selfcancelButtonTitle:@"知道了" otherButtonTitles:nil];

[Emailalert show];

}

if (result == MFMailComposeResultCancelled)

{

[self dismissModalViewControllerAnimated:YES];

}

}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex

{

if(alertView == Emailalert)

{

if (buttonIndex == )

{

[self dismissModalViewControllerAnimated:YES];

}

}else

{

if (buttonIndex == )

{

//[self dismissModalViewControllerAnimated:YES];

}else

{

NSString *recipients = @"mailto:theonelgq@gmail.com?cc=theone_liuguoqing@163.com&subject=text";

NSString *body = @"&body=text!";

NSString *email = [NSString stringWithFormat:@"%@%@", recipients, body];

email = [email stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:email]];

}

}

}

#pragma mark -

#pragma mark Workaround

-(void)launchMailAppOnDevice

{

isEmailalert = [[UIAlertView alloc] initWithTitle:@"警告" message:@"請(qǐng)配置您的郵箱" delegate:selfcancelButtonTitle:@"取消" otherButtonTitles:@"好的",nil];

[isEmailalert show];

}

16、程序啟動(dòng)畫面大小

iOS設(shè)備現(xiàn)在有三種不同的分辨率:iPhone 320x480、iPhone 4 640x960、iPad 768x1024。以前程序的啟動(dòng)畫面(圖片)只要準(zhǔn)備一個(gè) Default.png 就可以了,但是現(xiàn)在變得復(fù)雜多了。下面就是 CocoaChina 會(huì)員做得總結(jié)

如果一個(gè)程序,既支持iPhone又支持iPad,那么它需要包含下面幾個(gè)圖片:

Default-Portrait.png iPad專用豎向啟動(dòng)畫面 768x1024或者768x1004

Default-Landscape.png iPad專用橫向啟動(dòng)畫面 1024x768或者1024x748

Default-PortraitUpsideDown.png iPad專用豎向啟動(dòng)畫面(Home按鈕在屏幕上面),可省略 768x1024或者768x1004

Default-LandscapeLeft.png iPad專用橫向啟動(dòng)畫面,可省略 1024x768或者1024x748

Default-LandscapeRight.png iPad專用橫向啟動(dòng)畫面,可省略 1024x768或者1024x748

Default.png iPhone默認(rèn)啟動(dòng)圖片,如果沒有提供上面幾個(gè)iPad專用啟動(dòng)圖片,則在iPad上運(yùn)行時(shí)也使用Default.png(不推薦) 320x480或者320x460

Default@2x.png iPhone4啟動(dòng)圖片640x960或者640x920

為了在iPad上使用上述的啟動(dòng)畫面,你還需要在info.plist中加入key: UISupportedInterfaceOrientations。同時(shí),加入值UIInterfaceOrientationPortrait, UIInterfacOrientationPortraitUpsideDown, UIInterfaceOrientationLandscapeLeft, UIInterfaceOrientationLandscapeRight

17、ASIHTTPRequest實(shí)現(xiàn)斷點(diǎn)下載

- (IBAction)URLFetchWithProgress:(id)sender

{

[startButton setTitle:@"Stop" forState:UIControlStateNormal];

[startButton addTarget:self action:@selector(stopURLFetchWithProgress:)forControlEvents:UIControlEventTouchUpInside];

NSString*tempFile = [[[[NSBundle mainBundle] bundlePath]stringByDeletingLastPathComponent]stringByAppendingPathComponent:@"MemexTrails_1.0b1.zip.download"];

if ([[NSFileManager defaultManager] fileExistsAtPath:tempFile]) {

[[NSFileManager defaultManager] removeItemAtPath:tempFile error:nil];

}

[self resumeURLFetchWithProgress:self];

}

- (IBAction)stopURLFetchWithProgress:(id)sender

{

networkQueue = [[ASINetworkQueue alloc] init];

timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:selfselector:@selector(updateBandwidthUsageIndicator) userInfo:nil repeats:YES];

timer = nil;

[startButton setTitle:@"Stop" forState:UIControlStateNormal];

[startButton addTarget:self action:@selector(URLFetchWithProgress:)forControlEvents:UIControlEventTouchUpInside];

[networkQueue cancelAllOperations];

[resumeButton setEnabled:YES];

}

- (IBAction)resumeURLFetchWithProgress:(id)sender

{

[resumeButton setEnabled:NO];

[startButton setTitle:@"Start" forState:UIControlStateNormal];

[startButton addTarget:self action:@selector(stopURLFetchWithProgress:)forControlEvents:UIControlEventTouchUpInside];

[networkQueue cancelAllOperations];

[networkQueue setShowAccurateProgress:YES];

[networkQueue setDownloadProgressDelegate:progressIndicator];

[networkQueue setDelegate:self];

[networkQueue setRequestDidFinishSelector:@selector(URLFetchWithProgressComplete:)];

ASIHTTPRequest*request=[[[ASIHTTPRequest alloc] initWithURL:[NSURLURLWithString:@"http://9991.net/blog/mp3/2.mp3"]] autorelease];

[request setDownloadDestinationPath:[[[[NSBundle mainBundle] bundlePath]

stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"MemexTrails_1.0b1.mp3"]];

[request setTemporaryFileDownloadPath:[[[[NSBundle mainBundle] bundlePath]stringByDeletingLastPathComponent]stringByAppendingPathComponent:@"MemexTrails_1.0b1.zip.down"]];

[request setAllowResumeForFileDownloads:YES];

[networkQueue addOperation:request];

[networkQueue go];

}

- (void)URLFetchWithProgressComplete:(ASIHTTPRequest *)request

{

if ([request error]) {

fileLocation.text=[NSString stringWithFormat:@"An error occurred:%@",[[[requesterror] userInfo] objectForKey:@"Title"]];

} else {

fileLocation.text=[NSString stringWithFormat:@"File downloaded to %@",[requestdownloadDestinationPath]];

}

[startButton setTitle:@"Start" forState:UIControlStateNormal];

[startButton addTarget:self action:@selector(URLFetchWithProgress:)forControlEvents:UIControlEventTouchUpInside];

}

- (IBAction)throttleBandwidth:(id)sender

{

if ([(UIButton *)sender state] ==YES) {

[ASIHTTPRequest setMaxBandwidthPerSecond:ASIWWANBandwidthThrottleAmount];

} else {

[ASIHTTPRequest setMaxBandwidthPerSecond:];

}

}

18、Safari 啟動(dòng)本地app

在plist文件中加入U(xiǎn)RL types 結(jié)構(gòu)如下圖,在Safari中地址欄輸入 設(shè)置的字符串,比如設(shè)置的是

QQ,地址欄輸入 QQ:// 就可以起點(diǎn)本地應(yīng)用。

19、拖到視頻進(jìn)度與滑動(dòng)手勢(shì)沖突解決辦法

#pragma mark -
#pragma mark UIGestureRecognizerDelegate

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
 UIView *touchView = touch.view;

 if ([touchView isKindOfClass:[UISlider class]])
 {
   return NO;
 }
 else
 {
   return YES;
 }
}

20、創(chuàng)建并保存Cookie的方法


   NSString *cookieString = [NSString stringWithString:[headers objectForKey:@"Cookie"]];

   NSMutableDictionary *cookieProperties = [[NSMutableDictionary alloc] init];
   [cookieProperties setValue:cookieString forKey:NSHTTPCookieValue];
   [cookieProperties setValue:@"QQCookie" forKey:NSHTTPCookieName];
   [cookieProperties setValue:@".QQ.com" forKey:NSHTTPCookieDomain];
   [cookieProperties setValue:[NSDate dateWithTimeIntervalSinceNow:60*60] forKey:NSHTTPCookieExpires];
   [cookieProperties setValue:@"/" forKey:NSHTTPCookiePath];
   NSHTTPCookie *newcookie = [[NSHTTPCookie alloc] initWithProperties:cookieProperties];

   [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:newcookie];

21、popover橫豎屏位置改變解決辦法

1、 delegate中 處理

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
 userImageShow = NO;

 if ([popoverController isEqual:myPopover])
 {
   [myPopover release];
   myPopover = nil;
 }
}

2、屏幕旋轉(zhuǎn)時(shí)重新彈出Popover

if (myPopover)

{

if ((self.interfaceOrientation ==
   UIInterfaceOrientationLandscapeLeft) || (self.interfaceOrientation ==
   UIInterfaceOrientationLandscapeRight))
  {
     [myPopover presentPopoverFromRect:CGRectMake(10,180, 1, 1)
                       inView:self.view
              permittedArrowDirections:UIPopoverArrowDirectionRight
                      animated:YES];
  }
  else
  {
     [myPopover presentPopoverFromRect:CGRectMake(20,180, 1, 1)
                       inView:self.view
              permittedArrowDirections:UIPopoverArrowDirectionRight
                      animated:YES];
  }

}

22、plist各種key值含義

原文:http://www.minroad.com/?p=434



UIRequiresPersistentWiFi 在程序中彈出wifi選擇的key(系統(tǒng)設(shè)置中需要將wifi提示打開)
UIAppFonts 內(nèi)嵌字體(https://cache.yisu.com/upload/information/20200311/45/197695.jpg(更名而已)
UIPrerenderedIcon icon上是否有高光
UIRequiredDeviceCapabilities 設(shè)備需要的功能(具體點(diǎn)擊這里查看)
UIStatusBarHidden 狀態(tài)欄隱藏(和程序內(nèi)的區(qū)別是在于顯示Default.png已經(jīng)生效)
UIStatusBarStyle 狀態(tài)欄類型
UIViewEdgeAntialiasing 是否開啟抗鋸齒
CFBundleDisplayName app顯示名
CFBundleIconFile、CFBundleIconFiles 圖標(biāo)
CFBundleName 與CFBundleDisplayName的區(qū)別在于這個(gè)是短名,16字符之內(nèi)
CFBundleVersion 版本
CFBundleURLTypes 自定義url,用于利用url彈回程序
CFBundleLocalizations 本地資源的本地化語言,用于itunes頁面左下角顯示本地話語種
CFBundleDevelopmentRegion 也是本地化相關(guān),如果用戶所在地沒有相應(yīng)的語言資源,則用這個(gè)key的value來作為默認(rèn)
最后附上官方文檔,所有的key都有,看英文原版才是正路:)點(diǎn)我進(jìn)入

24、xcode工程內(nèi)添加多個(gè)Target

轉(zhuǎn)自:http://blog.sina.com.cn/s/blog_682dc7810100pv8t.html

啥叫多Targets, 有啥用!

相信很多人都注意到XCode中,
有個(gè)Target的概念.
 這在很多地方都有所體現(xiàn),
比如打開一個(gè)工程后, 左側(cè)的列表中有Targets一項(xiàng), 而在工程界面的頂部菜單中,
project里面也有多個(gè)涉及到Target的項(xiàng)目,
那么這個(gè)Target到底是什么呢?
 Apple的人是這樣說的:

引用

Targets that define the products to build. A
target organizes the files and instructions needed to build a
product into a sequence of build actions that can be taken.

簡(jiǎn)單的理解的話,

可以認(rèn)為一個(gè)target對(duì)應(yīng)一個(gè)新的product(基于同一份代碼的情況下). 但都一份代碼了, 弄個(gè)新product做啥呢?

折騰這個(gè)有意思么?

其實(shí)這不是單純的瞎折騰,

雖然代碼是同一份, 但編譯設(shè)置(比如編譯條件), 以及包含的資源文件卻可以有很大的差別. 于是即使同一份代碼,

產(chǎn)出的product也可能大不相同.

我們來舉幾個(gè)典型的應(yīng)用多Targets的情況吧,

比如完整版和lite版; 比如同一個(gè)游戲的20關(guān), 30關(guān), 50關(guān)版; 再或者比如同一個(gè)游戲換些資源和名字就當(dāng)新游戲賣的(喂喂,

你在教些什么...)

Targets之間, 什么相同, 什么不同!

既然是利用同一份代碼產(chǎn)出不同的product,

那么到底不同Target之間存在著什么樣的差異呢?

要解釋這個(gè)問題,

我們就要來看看一個(gè)Target指定了哪些內(nèi)容.

從XCode左側(cè)的列表中,

我們可以看到一個(gè)Target包含了Copy Bundle Resources, Compile Sources, Link

Binary With Libraries. 其中

Copy

Bundle Resources 是指生成的product的.app內(nèi)將包含哪些資源文件

Compile

Sources 是指將有哪些源代碼被編譯

Link

Binary With Libraries 是指編譯過程中會(huì)引用哪些庫文件

通過Copy

Bundle Resources中內(nèi)容的不同設(shè)置, 我們可以讓不同的product包含不同的資源, 包括程序的主圖標(biāo)等,

而不是把XCode的工程中列出的資源一股腦的包含進(jìn)去.

而這還不是一個(gè)target所指定的全部?jī)?nèi)容.

每個(gè)target可以使用一個(gè)獨(dú)立,

不同的Info.plist文件.

我們都知道,

這個(gè)Info.plist文件內(nèi)定義了一個(gè)iPhone項(xiàng)目的很多關(guān)鍵性內(nèi)容, 比如程序名稱,

最終生成product的全局唯一id等等.

而且不同的target還可以定義完整的差異化的編譯設(shè)置,

從簡(jiǎn)單的調(diào)整優(yōu)化選項(xiàng), 到增加條件編譯所使用的編譯條件, 以至于所使用的base SDK都可以差異化指定.

創(chuàng)建第二個(gè)Target!

為什么是第二個(gè)?

因?yàn)榈谝粋€(gè)就是創(chuàng)建好工程后的默認(rèn)Target呀! (廢話這么多, 拖走...)

創(chuàng)建target有多種方法,

我們可以從現(xiàn)有的target上復(fù)制出一份, 然后略加改動(dòng), 也可以完全新建一個(gè)target出來. 但其實(shí)說穿了,

兩個(gè)方法大同小異

首先我們來看看利用復(fù)制的方法創(chuàng)建target

利用復(fù)制創(chuàng)建target

我們?cè)赬Code左側(cè)的列表中,

展開 Targets 項(xiàng), 在現(xiàn)有的target上, 右鍵選擇 "Duplicate", 或者選中現(xiàn)有target后,

在頂部菜單的Edit內(nèi)選擇"Duplicate"也可以.

此時(shí)我們就得到了一個(gè)新的target,

而在Resource里面也會(huì)得到一個(gè) xxxx copy.plist. 這個(gè)新的target與原有的target是完全一致的,

余下的就是一些差異化的修改, 這個(gè)我們后面再說

創(chuàng)建全新的target

類似復(fù)制的方法,

我們可以在左側(cè)的列表中很多地方按下右鍵菜單, 都可以看到Add中會(huì)有"New Target..."一項(xiàng),

而在工程頂部菜單的Project內(nèi), 也可以看到這個(gè)"New Target..."的身影.

點(diǎn)擊后,

首先會(huì)讓你選擇target的類型, 既然我一直所指的都是程序本身, 那么自然選擇Application了(至于其他的嘛,

有興趣的自己研究吧, 比如我們可以把程序中的部分提取成一個(gè)Static Library).

Next后,

會(huì)讓你輸入一個(gè)新的Target的名字, 而不像復(fù)制的方法中, 默認(rèn)生成 xxxxx copy這樣的target名.

但是這樣生成出的Target幾乎是空的.

Copy Bundle Resources, Compile Sources, Link Binary With

Libraries里面都沒有任何內(nèi)容. 編譯設(shè)置也是完全原始的狀態(tài).

可以通過拖拽內(nèi)容到這些target的設(shè)置中,

以及調(diào)整編譯選項(xiàng)來完成Target的配置.

Target中部分內(nèi)容的修改方法!

其實(shí)這段的部分內(nèi)容,

在非多Targets的工程中也可能會(huì)用得到.

由于修改基本都是在工程/編譯設(shè)置中完成,

因此沒有特殊情況, 就不再聲明了, 打開target對(duì)應(yīng)的工程/編譯設(shè)置的方法可以采用在該target上右鍵, 選擇get

info來做到.

生成的product名稱的修改:

Packing段內(nèi)的Product Name一項(xiàng)

Info.plist文件名:

Packing段內(nèi)的Info.plist File一項(xiàng), 比如復(fù)制出來的target覺得那個(gè)xxxxx

copy.plist太傻就可以在這里改

件編譯: 增加一個(gè)User-Defined Setting(Target "xxxx"

Info的build頁的左下角那個(gè)齒輪中可以看到這個(gè)內(nèi)容), 在Other C Flag里面填入,

比如要定義一個(gè)叫做LITE_VERSION的define值, 我們可以寫上 "-DLITE_VERSION" 或

"-DLITE_VERSION=1". 那么在程序中就可以用

#if

defined(LITE_VERSION)

#else

#endif

這樣的條件編譯來部分差異化代碼了

也許有些朋友記得我在代碼區(qū)貼過的檢測(cè)破解版的代碼,

其中有一種檢測(cè)方法就是看info.plist是文本還是二進(jìn)制的, 那么我們能否建議一個(gè)模擬破解的target,

直接生成文本的info.plist以便測(cè)試呢?

當(dāng)然可以,

在packing段內(nèi), 有一項(xiàng)叫"Info.plist Output Encoding", 默認(rèn)值是Binary,

我們只要選成xml, 那么生成出的product.app內(nèi)的info.plist就直接是文本樣式的了.

外, 向Copy Bundle Resources, Compile Sources, Link Binary With

Libraries內(nèi)添加/刪除文件, 可以在要改動(dòng)的文件上, 選擇get info, 并且切換到Target頁,

勾選要引用這個(gè)文件的target即可. 比如icon.png可以指定給默認(rèn)target, 而icon_lite.png指定給lite

verion的target

大致就是如此吧, 懶得抓圖了. 各位將就吧. 想到什么需要補(bǔ)充的, 我會(huì)加入

另外

一個(gè)英文教程:http://www.codza.com/free-iphone-app-version-from-the-same-xcode-project

25、詳解IOS SDK兼容性引導(dǎo)

轉(zhuǎn)自: http://mobile.51cto.com/iphone-284052.htm

IOS SDK兼容性引導(dǎo)是本文要介紹的內(nèi)容,主要是基于IOS SDK基礎(chǔ)的開發(fā)介紹說明如何應(yīng)用于XCode工程的基于IOS SDK開發(fā)的技術(shù)。來看詳細(xì)內(nèi)容講解。

1、用(weakly linked)弱連接類、方法和函數(shù)來支持在不同版本之間的程序運(yùn)行

2、弱連接整個(gè)框架(framework)

3、為不同的IOS SDK選擇不同的編譯條件

4、在代碼中找出過時(shí)API的使用

5、確定在運(yùn)行時(shí)操作系統(tǒng)和框架(framework)的版本

一 、在IOS中使用弱連接類

在工程中使用類的弱連接的時(shí)候必須確保這些類在運(yùn)行時(shí)的可用性,要不會(huì)引起動(dòng)態(tài)連接的錯(cuò)誤。

在IOS4.2以后的版本都是使用NSObject class的方法來檢測(cè)弱連接在運(yùn)行時(shí)態(tài)的可用性,這種簡(jiǎn)單高效的機(jī)制使用了NS_CLASS_AVAILABLE的可用性宏。

檢測(cè)最近release的framework還不支持NS_CLASS_AVAILABLE的宏

在支持NS_CLASS_AVAILABLE的宏framework的條件編譯中,可以如下的使用

  • if ([UIPrintInteractionController class]) {

  • // Create an instance of the class and use it.

  • } else {

  • // Alternate code path to follow when the

  • // class is not available.

  • }

如果你在不確保是否已經(jīng)可以使用類方法的時(shí)候你可以使用NSClassFromString 方法來判斷,使用方法如下:

  • Class cls = NSClassFromString (@"NSRegularExpression");

  • if (cls) {

  • // Create an instance of the class and use it.

  • } else {

  • // Alternate code path to follow when the

  • // class is not available.

  • }

二、在方法,函數(shù)和符號(hào)中使用弱連接

和使用類的弱連接一樣,在使用它之前要確保方法函數(shù)和符號(hào)在運(yùn)行時(shí)的可用性,要不在編譯的時(shí)候會(huì)報(bào)錯(cuò)動(dòng)態(tài)連接錯(cuò)誤,假設(shè)你想使用新版本IOS
SDK的特性但是又想能夠運(yùn)行在低版本的SDK中,那么就要對(duì)早期的版本設(shè)置相應(yīng)的開發(fā)target,在Object-c中
instancesRespondToSelector:
方法告訴我們所給的方法是否可用,例如:使用availableCaptureModesForCameraDevice:這個(gè)方法(在4.0以后才是可
用的),我們可以這樣使用它。

1、檢查一個(gè)Object-c方法的可用性

  • if ([UIImagePickerController instancesRespondToSelector:

  • @selector (availableCaptureModesForCameraDevice:)]) {

  • // Method is available for use.

  • // Your code can check if video capture is available and,

  • // if it is, offer that option.

  • } else {

  • // Method is not available.

  • // Alternate code to use only still p_w_picpath capture.

  • }

判斷一個(gè)弱連接的C函數(shù)是否可用,只要判斷函數(shù)的地址是否返回為NULL,以CGColorCreateGenericCMYK 函數(shù)為例,我們可以像以下那樣使用。

2、檢查C方法的可用性

  • if (CGColorCreateGenericCMYK != NULL) {

  • CGColorCreateGenericCMYK (0.1,0.5.0.0,1.0,0.1);

  • } else {

  • // Function is not available.

  • // Alternate code to create a color object with earlier technology

  • }

要檢測(cè)一個(gè)C方法是否可用,比較明確的為地址是否為NULL或零。你不能使用反運(yùn)算符(!)來否定一個(gè)函數(shù)的可用性

檢測(cè)一個(gè) external(extern)常量或一個(gè)通知的名字應(yīng)當(dāng)比較它的地址(address)--而不是符號(hào)的名稱, 判斷是否為NULL or nil

三、弱連接整個(gè)Framework

比如一個(gè)在高版本中才出現(xiàn)的Framework,想在低版本使用他的特性。那你就必須弱連接那個(gè)使用的Framework,詳見官方的圖解---(其實(shí)就是在添加進(jìn)去的Framework的 required 改成 optional)

  • http://developer.apple.com/library/ios/#documentation/DeveloperTools/Conceptual/XcodeProjectManagement/

  • 130-Files_in_Projects/project_files.html#//apple_ref/doc/uid/TP40002666-SW4

四、條件編譯for不同的SDK

如果你不止基于一個(gè)IOS SDK編譯,你就可能需要為base
sdk使用條件化,可以使用在Availability.h中的定義。這個(gè).h文件存在于系統(tǒng)的文件夾/usr/include的文件夾下,例如想在
Mac OS X v10.5(而不是IOS)中使用函數(shù) CGColorCreateGenericCMYK

使用預(yù)處理指令for條件編譯

  • #ifdef __MAC_OS_X_VERSION_MAX_ALLOWED

  • // code only compiled when targeting Mac OS X and not iOS

  • // note use of 1050 instead of __MAC_10_5

  • #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050

  • if (CGColorCreateGenericCMYK != NULL) {

  • CGColorCreateGenericCMYK(0.1,0.5.0.0,1.0,0.1);

  • } else {

  • #endif

  • // code to create a color object with earlier technology

  • #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050

  • }

  • #endif

  • #endif

  • }

五、尋找出在程序中使用的以過時(shí)的實(shí)例

在IOS或Mac
OS中有時(shí)候API會(huì)過時(shí),但是過時(shí)不代表著那些就從Library或framework中刪除,但是在使用的過程中會(huì)報(bào)出warning,并且在不遠(yuǎn)的
將來可能會(huì)被Apple從中移除。例如我們?cè)赾ode中使用了過時(shí)的函數(shù) HPurge那么就會(huì)報(bào)出如下

  • 'HPurge' is deprecated (declared at /Users/steve/MyProject/main.c:51)

所以我們應(yīng)當(dāng)在工程中查找出如下的警告并且修改。

六、確定操作系統(tǒng)和Framework的版本

在運(yùn)行時(shí)檢查IOS的版本

  • NSString *osVersion = [[UIDevice currentDevice] systemVersion];

在運(yùn)行時(shí)檢查Mac OS X用Gestalt function 和 系統(tǒng)版本常量

另外,對(duì)于許多的Framework你可以在運(yùn)行時(shí)檢查指定Framework的版本。

例如:Application Kit(NSApplication.h)定義了NSAppKitVersionNumber常量---可以用來檢查Application Kit Framework的版本

  • APPKIT_EXTERN double NSAppKitVersionNumber;

  • #define NSAppKitVersionNumber10_0 577

  • #define NSAppKitVersionNumber10_1 620

  • #define NSAppKitVersionNumber10_2 663

  • #define NSAppKitVersionNumber10_2_3 663.6

  • #define NSAppKitVersionNumber10_3 743

  • #define NSAppKitVersionNumber10_3_2 743.14

  • #define NSAppKitVersionNumber10_3_3 743.2

  • #define NSAppKitVersionNumber10_3_5 743.24

  • #define NSAppKitVersionNumber10_3_7 743.33

  • #define NSAppKitVersionNumber10_3_9 743.36

  • #define NSAppKitVersionNumber10_4 824

  • #define NSAppKitVersionNumber10_4_1 824.1

  • #define NSAppKitVersionNumber10_4_3 824.23

  • #define NSAppKitVersionNumber10_4_4 824.33

  • #define NSAppKitVersionNumber10_4_7 824.41

  • #define NSAppKitVersionNumber10_5 949

  • #define NSAppKitVersionNumber10_5_2 949.27

  • #define NSAppKitVersionNumber10_5_3 949.33

所以我們可以像如下使用:

  • if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_0) {

  • /* On a 10.0.x or earlier system */

  • } else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_1) {

  • /* On a 10.1 - 10.1.x system */

  • } else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_2) {

  • /* On a 10.2 - 10.2.x system */

  • } else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_3) {

  • /* On 10.3 - 10.3.x system */

  • } else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_4) {

  • /* On a 10.4 - 10.4.x system */

  • } else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_5) {

  • /* On a 10.5 - 10.5.x system */

  • } else {

  • /* 10.6 or later system */

  • }

跟以上一樣在 NSObjCRuntime.h中用定義了NSFoundationVersionNumber全局常量

小結(jié):詳解IOS SDK兼容性引導(dǎo)的內(nèi)容介紹玩玩了,希望通過本文的學(xué)習(xí)能對(duì)你有所幫助!

原文地址:http://blog.csdn.net/diyagoanyhacker/article/details/6673344

26、NSDate 與 NSString 轉(zhuǎn)換

1、將字符串 “Fri Nov 11 09:06:27 +0800 2011” 轉(zhuǎn)換成Date:

NSDateFormatter *format = [[NSDateFormatter alloc] init];
 NSLocale *enLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en-US"];
 [format setLocale:enLocale];
 [enLocale release];
 [format setDateFormat:@"EEE MMM dd HH:mm:ss ZZZ yyyy"];
 NSDate *dateTime = [format dateFromString:message];

將Date轉(zhuǎn)換成字符串:

NSDate *date = [NSDate date];
 NSString * dateString = [format stringFromDate:date];

//字符串轉(zhuǎn)換成NSDate 需要設(shè)置NSLocale 否則真機(jī)上會(huì)失敗。

2、獲取當(dāng)前時(shí)間,轉(zhuǎn)化成字符串

NSDateFormatter * formatter = [[NSDateFormatteralloc]init];

 formatter.dateStyle = NSDateFormatterMediumStyle;

 formatter.timeStyle = NSDateFormatterMediumStyle;

 formatter.locale = [NSLocalecurrentLocale];

self.timeLabel.text = [formatterstringFromDate:[NSDatedate]];

3、獲取月、日、年、時(shí)、分、秒

NSDateFormatter *formatter =[[[NSDateFormatteralloc] init] autorelease];

 formatter.dateStyle = NSDateFormatterMediumStyle;

 formatter.timeStyle = NSDateFormatterMediumStyle;

 formatter.locale = [NSLocalecurrentLocale];

NSDate *date = [NSDatedate];

 [formatter setTimeStyle:NSDateFormatterMediumStyle];

NSCalendar *calendar = [[[NSCalendaralloc] initWithCalendarIdentifier:NSGregorianCalendar]autorelease];

NSDateComponents *comps = [[[NSDateComponentsalloc] init] autorelease];

NSInteger unitFlags = NSYearCalendarUnit |

NSMonthCalendarUnit |

NSDayCalendarUnit |

NSWeekdayCalendarUnit |

NSHourCalendarUnit |

NSMinuteCalendarUnit |

NSSecondCalendarUnit;

//int week=0;

comps = [calendar components:unitFlags fromDate:date];

int week = [comps weekday];

int year=[comps year];

int month = [comps month];

int day = [comps day];

 [formatter setDateStyle:NSDateFormatterMediumStyle];

//  //This sets the label with the updated time.

int hour = [comps hour];

int min = [comps minute];

int sec = [comps second];

NSLog(@"day%d",day);

NSLog(@"hour%d",hour);

NSLog(@"min%d",min);

NSLog(@"sec%d",sec);

27、數(shù)組中存儲(chǔ)數(shù)據(jù)查詢

NSMutableDictionary *userDic1 = [NSMutableDictionary dictionaryWithCapacity:10];
 NSMutableDictionary *userDic2 = [NSMutableDictionary dictionaryWithCapacity:10];
 [userDic1 setValue:@"Li" forKey:@"name"];
 [userDic2 setValue:@"Wang" forKey:@"name"];

 NSArray *userArray = [NSArray arrayWithObjects:userDic1,userDic2,nil];
 NSPredicate *namePredicate = [NSPredicate predicateWithFormat:@"SELF.name contains[cd] %@ ",@"L"];

 NSMutableArray *searchArray = [NSMutableArray arrayWithArray:[userArray filteredArrayUsingPredicate:namePredicate]];

 NSLog(@"searchArray == %@",searchArray);

28、CoreText 總結(jié)

(1) NSAttributedString

NSAttributedString 可以將一段文字中的部分文字設(shè)置單獨(dú)的字體和顏色。

與UITouch結(jié)合可以實(shí)現(xiàn)點(diǎn)擊不同文字觸發(fā)不同事件的交互功能。

主要方法:

- (void)addAttribute:(NSString *)name value:(id)value range:(NSRange)range;

可以設(shè)置某段文字的字體名稱,顏色,下滑線等信息。

- (void)removeAttribute:(NSString *)name range:(NSRange)range;

移除之前設(shè)置的字體屬性值。

- (void)addAttributes:(NSDictionary *)attrs range:(NSRange)range;

存儲(chǔ)某段文字包含的信息(包括字體屬性或其它,也可以存儲(chǔ)一些自定義的信息)

- (NSDictionary *)attributesAtIndex:(NSUInteger)location effectiveRange:(NSRangePointer)range;

通過location來獲取某段文字中之前存儲(chǔ)的信息NSDictionary

//設(shè)置字體
 CTFontRef aFont = CTFontCreateWithName((CFStringRef)textFont.fontName, textFont.pointSize, NULL);
 if (!aFont) return;
 CTFontRef newFont = CTFontCreateCopyWithSymbolicTraits(aFont, 0.0, NULL, kCTFontItalicTrait, kCTFontBoldTrait);  //將默認(rèn)黑體字設(shè)置為其它字體
 [self removeAttribute:(NSString*)kCTFontAttributeName range:textRange];
 [self addAttribute:(NSString*)kCTFontAttributeName value:(id)newFont range:textRange];
 CFRelease(aFont);
 CFRelease(newFont);

 //設(shè)置字體顏色
 [self removeAttribute:(NSString*)kCTForegroundColorAttributeName range:textRange];
 [self addAttribute:(NSString*)kCTForegroundColorAttributeName value:(id)textColor.CGColor range:textRange];

 //設(shè)置對(duì)齊 換行
 CTTextAlignment coreTextAlign = kCTLeftTextAlignment;
 CTLineBreakMode coreTextLBMode = kCTLineBreakByCharWrapping;
 CTParagraphStyleSetting paraStyles[2] =
 {
   {.spec = kCTParagraphStyleSpecifierAlignment, .valueSize = sizeof(CTTextAlignment), .value = (const void*)&coreTextAlign},
   {.spec = kCTParagraphStyleSpecifierLineBreakMode, .valueSize = sizeof(CTLineBreakMode), .value = (const void*)&coreTextLBMode},
 };
 CTParagraphStyleRef aStyle = CTParagraphStyleCreate(paraStyles, 2);
 [self removeAttribute:(NSString*)kCTParagraphStyleAttributeName range:textRange];
 [self addAttribute:(NSString*)kCTParagraphStyleAttributeName value:(id)aStyle range:textRange];
 CFRelease(aStyle);

(2)Draw NSAttributedString



 CGContextRef cgc = UIGraphicsGetCurrentContext();
 CGContextSaveGState(cgc);

 //圖像方向轉(zhuǎn)換
 CGContextConcatCTM(cgc, CGAffineTransformScale(CGAffineTransformMakeTranslation(0, self.bounds.size.height), 1.f, -1.f));

 CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)weiBoText);
 drawingRect = self.bounds;
 CGMutablePathRef path = CGPathCreateMutable();
 CGPathAddRect(path, NULL, drawingRect);
 textFrame = CTFramesetterCreateFrame(framesetter,CFRangeMake(0,0), path, NULL);
 CGPathRelease(path);
 CFRelease(framesetter);

 CTFrameDraw(textFrame, cgc);
 CGContextRestoreGState(cgc);

(3)圖文混排

CTFrameRef textFrame   // coreText 的 frame

CTLineRef   line       // coreText 的 line

CTRunRef   run       // line 中的部分文字

相關(guān)方法:


 CFArrayRef CTFrameGetLines  (CTFrameRef frame )   //獲取包含CTLineRef的數(shù)組

void CTFrameGetLineOrigins(
 CTFrameRef frame,
 CFRange range,
 CGPoint origins[] ) //獲取所有CTLineRef的原點(diǎn)

CFRange CTLineGetStringRange (CTLineRef line )  //獲取line中文字在整段文字中的Range

CFArrayRef CTLineGetGlyphRuns (CTLineRef line )  //獲取line中包含所有run的數(shù)組

CFRange CTRunGetStringRange (CTRunRef run )   //獲取run在整段文字中的Range

CFIndex CTLineGetStringIndexForPosition(
 CTLineRef line,
 CGPoint position )  //獲取點(diǎn)擊處position文字在整段文字中的index

CGFloat CTLineGetOffsetForStringIndex(
 CTLineRef line,
 CFIndex charIndex,
 CGFloat* secondaryOffset ) //獲取整段文字中charIndex位置的字符相對(duì)line的原點(diǎn)的x值

主要步驟:

1)計(jì)算并存儲(chǔ)文字中保含的所有表情文字及其Range

2)替換表情文字為指定寬度的NSAttributedString

CTRunDelegateCallbacks callbacks;
 callbacks.version = kCTRunDelegateVersion1;
 callbacks.getAscent = ascentCallback;
 callbacks.getDescent = descentCallback;
 callbacks.getWidth = widthCallback;
 callbacks.dealloc = deallocCallback;

 CTRunDelegateRef runDelegate = CTRunDelegateCreate(&callbacks, NULL);
 NSDictionary *attrDictionaryDelegate = [NSDictionary dictionaryWithObjectsAndKeys:
                     (id)runDelegate, (NSString*)kCTRunDelegateAttributeName,
                     [UIColor clearColor].CGColor,(NSString*)kCTForegroundColorAttributeName,
                     nil];

 NSAttributedString *faceAttributedString = [[NSAttributedString alloc] initWithString:@"*" attributes:attrDictionaryDelegate];

 [weiBoText replaceCharactersInRange:faceRange withAttributedString:faceAttributedString];
 [faceAttributedString release];

3) 根據(jù)保存的表情文字的Range計(jì)算表情圖片的Frame

textFrame 通過CTFrameGetLines 獲取所有l(wèi)ine的數(shù)組 lineArray

遍歷lineArray中的line通過CTLineGetGlyphRuns獲取line中包含run的數(shù)組 runArray

遍歷runArray中的run 通過CTRunGetStringRange獲取run的Range

判斷表情文字的location是否在run的Range

如果在 通過CTLineGetOffsetForStringIndex獲取x的值 y的值為line原點(diǎn)的值

4)Draw表情圖片到計(jì)算獲取到的Frame

(3)點(diǎn)擊文字觸發(fā)事件

主要步驟:

1) 根據(jù)touch事件獲取點(diǎn)point

2)  textFrame 通過CTFrameGetLineOrigins獲取所有l(wèi)ine的原點(diǎn)

3) 比較point和line原點(diǎn)的y值獲取點(diǎn)擊處于哪個(gè)line

4) line、point 通過CTLineGetStringIndexForPosition獲取到點(diǎn)擊字符在整段文字中的  index

5) NSAttributedString 通過index 用方法-(NSDictionary *)attributesAtIndex:(NSUInteger)location effectiveRange:(NSRangePointer)range 可以獲取到點(diǎn)擊到的NSAttributedString中存儲(chǔ)的NSDictionary

6) 通過NSDictionary中存儲(chǔ)的信息判斷點(diǎn)擊的哪種文字類型分別處理

感謝各位的閱讀!關(guān)于“IOS開發(fā)有用的小知識(shí)點(diǎn)有哪些”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

ios
AI