1
獲取系統語言設置
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];
}
// 單位是字節
return
_cacheFolderSize;
}
3Popover push 時 Frame沒法改變解決辦法
在popover中的ViewController中實現:
- (
void
)viewWillAppear:(BOOL)animated
{
CGSize size = CGSizeMake(
320
,
480
);
// size of view in popover
self.contentSizeForViewInPopover = size;
[
super
viewWillAppear:animated];
}
4tableview滑動致使NSTimer和委託回調中止解決辦法
/ /請求回調
NSURLRequest * 請求 = ...
scheduleInRunLoop :[ NSRunLoop currentRunLoop ]
forMode :NSRunLoopCommonModes ]
[ 鏈接開始] / /定時器回調
NSTimer * updateTimer = [NSTimer scheduledTimerWithTimeInterval:
0
.01f目標:自我選擇:選擇(updatePencent)的UserInfo:無重複:是];
* NSRunLoop主要= [NSRunLoop currentRunLoop]
[主要addTimer:updateTimer forMode:NSRunLoopCommonModes];
5
手勢識別類
UIGestureRecognizer
6SFHFKeychainUtils 存儲信息
蘋果SDK自帶的就有密碼保護,使用方法很簡單,以下:
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];
7missing required architecture i386 in file 解決辦法
在TargetInfo裏面修改 Framework Search Pasths 刪除裏面內容就能夠了。
8view 放大縮小動畫效果
//建立縮小了的視圖
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
(imageViewControllerBigAnimation)];
//放大剛剛建立縮小後的視圖
- (
void
)imageViewControllerBigAnimation{
[UIView beginAnimations:@
"imageViewBig"
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
)imageViewControllerSmallAnimation{
[UIView beginAnimations:@
"imageViewSmall"
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];
}
9UIScrollView 控制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 實現
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return
mPicStatusesViewController.view;
//返回ScrollView上添加的須要縮放的視圖
}
- (
void
)scrollViewDidZoom:(UIScrollView *)scrollView
{
//縮放操做中被調用
}
- (
void
)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(
float
)scale
{
//縮放結束後被調用
}
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
、谷歌地圖翻起動畫效果
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;
//添加四個邊陰影
_imgvPhoto.layer.shadowColor = [UIColor blackColor].CGColor;
_imgvPhoto.layer.shadowOffset = CGSizeMake(
0
,
0
);
_imgvPhoto.layer.shadowOpacity =
0.5
;
_imgvPhoto.layer.shadowRadius =
10.0
;
//添加兩個邊陰影
_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動畫實現飄雪效果
viewDidLoad事件中,增長一個圖片及定時器並啓動,這裏的pic請在頭文件中定義。
-(
void
)viewDidLoad{
[
super
viewDidLoad];
self.pic = [UIImage imageNamed:@
"snow.png"
];
//初始化圖片
//啓動定時器,實現飄雪效果
[NSTimer scheduledTimerWithTimeInterval:(
0.2
) target:self selector:
@selector
(ontime) userInfo:nil repeats:YES];
}
而後再實現定時器定時調用的ontime方法:
-(
void
)ontime{
UIImageView *view = [[UIImageView alloc] initWithImage:pic];
//聲明一個UIImageView對象,用來添加圖片
view.alpha =
0.5
;
//設置該view的alpha爲0.5,半透明的
int
x = round(random()
20
);
//隨機獲得該圖片的x座標
int
y = round(random()
20
);
//這個是該圖片移動的最後座標x軸的
int
s = round(random())+
10
;
//這個是定義雪花圖片的大小
int
sp =
1
/round(random()
0
)+
1
;
//這個是速度
view.frame = CGRectMake(x, -
50
, s, s);
//雪花開始的大小和位置
[self.view addSubview:view];
//添加該view
[UIView beginAnimations:nil context:view];
//開始動畫
[UIView setAnimationDuration:
10
*sp];
//設定速度
view.frame = CGRectMake(y,
500
, s, s);
//設定該雪花最後的消失座標
[UIView setAnimationDelegate:self];
[UIView commitAnimations];
}
14
、配置Xcode 看程序崩潰信息
1
、在xcode中的左側目錄中找到Executables 打開
2
、雙擊和工程名同樣的文件。
3
、在打開的文件中的Arguments選項,在下面的框中加入Name: NSZombieEnabled 設置value爲YES。
15
、程序中發送郵件和檢測設備郵箱是否被配置
-(
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:@
"發送失敗"
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:@
"請配置您的郵箱"
delegate:selfcancelButtonTitle:@
"取消"
otherButtonTitles:@
"好的"
,nil];
[isEmailalert show];
}
16
、程序啓動畫面大小
iOS設備如今有三種不一樣的分辨率:iPhone 320x480、iPhone
4
640x960、iPad 768x1024。之前程序的啓動畫面(圖片)只要準備一個 Default.png 就能夠了,可是如今變得複雜多了。下面就是 CocoaChina 會員作得總結
若是一個程序,既支持iPhone又支持iPad,那麼它須要包含下面幾個圖片:
Default-Portrait.png iPad專用豎向啓動畫面 768x1024或者768x1004
Default-Landscape.png iPad專用橫向啓動畫面 1024x768或者1024x748
Default-PortraitUpsideDown.png iPad專用豎向啓動畫面(Home按鈕在屏幕上面),可省略 768x1024或者768x1004
Default-LandscapeLeft.png iPad專用橫向啓動畫面,可省略 1024x768或者1024x748
Default-LandscapeRight.png iPad專用橫向啓動畫面,可省略 1024x768或者1024x748
Default.png iPhone默認啓動圖片,若是沒有提供上面幾個iPad專用啓動圖片,則在iPad上運行時也使用Default.png(不推薦) 320x480或者320x460
Default
@2x
.png iPhone4啓動圖片640x960或者640x920
爲了在iPad上使用上述的啓動畫面,你還須要在info.plist中加入key: UISupportedInterfaceOrientations。同時,加入值UIInterfaceOrientationPortrait, UIInterfacOrientationPortraitUpsideDown, UIInterfaceOrientationLandscapeLeft, UIInterfaceOrientationLandscapeRight
17
、ASIHTTPRequest實現斷點下載
- (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:)];
[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 啓動本地app
在plist文件中加入URL types 結構以下圖,在Safari中地址欄輸入 設置的字符串,好比設置的是
QQ,地址欄輸入 QQ:
// 就能夠起點本地應用。
19
、拖到視頻進度與滑動手勢衝突解決辦法
#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
、建立並保存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
、屏幕旋轉時從新彈出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(系統設置中須要將wifi提示打開)
UIAppFonts 內嵌字體(http:
//www.minroad.com/?p=412 有詳細介紹)
UIApplicationExitsOnSuspend 程序是否在後臺運行,本身在進入後臺的時候exit(
0
)是很傻的辦法
UIBackgroundModes 後臺運行時的服務,具體看iOS4的後臺介紹
UIDeviceFamily array類型(
1
爲iPhone和iPod touch設備,
2
爲iPad)
UIFileSharingEnabled 開啓itunes共享document文件夾
UILaunchImageFile 至關於Default.png(改名而已)
UIPrerenderedIcon icon上是否有高光
UIRequiredDeviceCapabilities 設備須要的功能(具體點擊這裏查看)
UIStatusBarHidden 狀態欄隱藏(和程序內的區別是在於顯示Default.png已經生效)
UIStatusBarStyle 狀態欄類型
UIViewEdgeAntialiasing 是否開啓抗鋸齒
CFBundleDisplayName app顯示名
CFBundleIconFile、CFBundleIconFiles 圖標
CFBundleName 與CFBundleDisplayName的區別在於這個是短名,
16
字符以內
CFBundleVersion 版本
CFBundleURLTypes 自定義url,用於利用url彈回程序
CFBundleLocalizations 本地資源的本地化語言,用於itunes頁面左下角顯示本地話語種
CFBundleDevelopmentRegion 也是本地化相關,若是用戶所在地沒有相應的語言資源,則用這個key的value來做爲默認
最後附上官方文檔,全部的key都有,看英文原版纔是正路:)點我進入
24
、xcode工程內添加多個Target
轉自:http:
//blog.sina.com.cn/s/blog_682dc7810100pv8t.html
啥叫多Targets, 有啥用!
相信不少人都注意到XCode中,
有個Target的概念.
這在不少地方都有所體現,
好比打開一個工程後, 左側的列表中有Targets一項, 而在工程界面的頂部菜單中,
project裏面也有多個涉及到Target的項目,
那麼這個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.
簡單的理解的話,
能夠認爲一個target對應一個新的product(基於同一份代碼的狀況下). 但都一份代碼了, 弄個新product作啥呢?
折騰這個有意思麼?
其實這不是單純的瞎折騰,
雖然代碼是同一份, 但編譯設置(好比編譯條件), 以及包含的資源文件卻能夠有很大的差異. 因而即便同一份代碼,
產出的product也可能大不相同.
咱們來舉幾個典型的應用多Targets的狀況吧,
好比完整版和lite版; 好比同一個遊戲的
20
關,
30
關,
50
關版; 再或者好比同一個遊戲換些資源和名字就當新遊戲賣的(喂喂,
你在教些什麼...)
Targets之間, 什麼相同, 什麼不一樣!
既然是利用同一份代碼產出不一樣的product,
那麼到底不一樣Target之間存在着什麼樣的差別呢?
要解釋這個問題,
咱們就要來看看一個Target指定了哪些內容.
從XCode左側的列表中,
咱們能夠看到一個Target包含了Copy Bundle Resources, Compile Sources, Link
Binary With Libraries. 其中
Copy
Bundle Resources 是指生成的product的.app內將包含哪些資源文件
Compile
Sources 是指將有哪些源代碼被編譯
Link
Binary With Libraries 是指編譯過程當中會引用哪些庫文件
經過Copy
Bundle Resources中內容的不一樣設置, 咱們可讓不一樣的product包含不一樣的資源, 包括程序的主圖標等,
而不是把XCode的工程中列出的資源一股腦的包含進去.
而這還不是一個target所指定的所有內容.
每一個target可使用一個獨立,
不一樣的Info.plist文件.
咱們都知道,
這個Info.plist文件內定義了一個iPhone項目的不少關鍵性內容, 好比程序名稱,
最終生成product的全局惟一id等等.
並且不一樣的target還能夠定義完整的差別化的編譯設置,
從簡單的調整優化選項, 到增長條件編譯所使用的編譯條件, 以致於所使用的base SDK均可以差別化指定.
建立第二個Target!
爲何是第二個?
由於第一個就是建立好工程後的默認Target呀! (廢話這麼多, 拖走...)
建立target有多種方法,
咱們能夠從現有的target上覆製出一份, 而後略加改動, 也能夠徹底新建一個target出來. 但其實說穿了,
兩個方法大同小異
首先咱們來看看利用複製的方法建立target
利用複製建立target
咱們在XCode左側的列表中,
展開 Targets 項, 在現有的target上, 右鍵選擇
"Duplicate"
, 或者選中現有target後,
在頂部菜單的Edit內選擇
"Duplicate"
也能夠.
此時咱們就獲得了一個新的target,
而在Resource裏面也會獲得一個 xxxx copy.plist. 這個新的target與原有的target是徹底一致的,
餘下的就是一些差別化的修改, 這個咱們後面再說
建立全新的target
相似複製的方法,
咱們能夠在左側的列表中不少地方按下右鍵菜單, 均可以看到Add中會有
"New Target..."
一項,
而在工程頂部菜單的Project內, 也能夠看到這個
"New Target..."
的身影.
點擊後,
首先會讓你選擇target的類型, 既然我一直所指的都是程序自己, 那麼天然選擇Application了(至於其餘的嘛,
有興趣的本身研究吧, 好比咱們能夠把程序中的部分提取成一個Static Library).
Next後,
會讓你輸入一個新的Target的名字, 而不像複製的方法中, 默認生成 xxxxx copy這樣的target名.
可是這樣生成出的Target幾乎是空的.
Copy Bundle Resources, Compile Sources, Link Binary With
Libraries裏面都沒有任何內容. 編譯設置也是徹底原始的狀態.
能夠經過拖拽內容到這些target的設置中,
以及調整編譯選項來完成Target的配置.
Target中部份內容的修改方法!
其實這段的部份內容,
在非多Targets的工程中也可能會用獲得.
因爲修改基本都是在工程/編譯設置中完成,
所以沒有特殊狀況, 就再也不聲明瞭, 打開target對應的工程/編譯設置的方法能夠採用在該target上右鍵, 選擇get
info來作到.
生成的product名稱的修改:
Packing段內的Product Name一項
Info.plist文件名:
Packing段內的Info.plist File一項, 好比複製出來的target以爲那個xxxxx
copy.plist太傻就能夠在這裏改
條
件編譯: 增長一個User-Defined Setting(Target
"xxxx"
Info的build頁的左下角那個齒輪中能夠看到這個內容), 在Other C Flag裏面填入,
好比要定義一個叫作LITE_VERSION的define值, 咱們能夠寫上
"-DLITE_VERSION"
或
"-DLITE_VERSION=1"
. 那麼在程序中就能夠用
#
if
defined(LITE_VERSION)
#
else
#endif
這樣的條件編譯來部分差別化代碼了
也許有些朋友記得我在代碼區貼過的檢測破解版的代碼,
其中有一種檢測方法就是看info.plist是文本仍是二進制的, 那麼咱們可否建議一個模擬破解的target,
直接生成文本的info.plist以便測試呢?
固然能夠,
在packing段內, 有一項叫
"Info.plist Output Encoding"
, 默認值是Binary,
咱們只要選成xml, 那麼生成出的product.app內的info.plist就直接是文本樣式的了.
另
外, 向Copy Bundle Resources, Compile Sources, Link Binary With
Libraries內添加/刪除文件, 能夠在要改動的文件上, 選擇get info, 而且切換到Target頁,
勾選要引用這個文件的target便可. 好比icon.png能夠指定給默認target, 而icon_lite.png指定給lite
verion的target
大體就是如此吧, 懶得抓圖了. 各位將就吧. 想到什麼須要補充的, 我會加入
另外
一個英文教程:http:
//www.codza.com/free-iphone-app-version-from-the-same-xcode-project
25
、詳解IOS SDK兼容性引導
轉自: http:
//mobile.51cto.com/iphone-284052.htm
IOS SDK兼容性引導是本文要介紹的內容,主要是基於IOS SDK基礎的開發介紹說明如何應用於XCode工程的基於IOS SDK開發的技術。來看詳細內容講解。
1
、用(weakly linked)弱鏈接類、方法和函數來支持在不一樣版本之間的程序運行
2
、弱鏈接整個框架(framework)
3
、爲不一樣的IOS SDK選擇不一樣的編譯條件
4
、在代碼中找出過期API的使用
5
、肯定在運行時操做系統和框架(framework)的版本
一 、在IOS中使用弱鏈接類
在工程中使用類的弱鏈接的時候必須確保這些類在運行時的可用性,要不會引發動態鏈接的錯誤。
在IOS4.
2
之後的版本都是使用NSObject
class
的方法來檢測弱鏈接在運行時態的可用性,這種簡單高效的機制使用了NS_CLASS_AVAILABLE的可用性宏。
檢測最近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.
}
若是你在不確保是否已經可使用類方法的時候你可使用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.
}
2、在方法,函數和符號中使用弱鏈接
和使用類的弱鏈接同樣,在使用它以前要確保方法函數和符號在運行時的可用性,要不在編譯的時候會報錯動態鏈接錯誤,假設你想使用新版本IOS
SDK的特性可是又想可以運行在低版本的SDK中,那麼就要對早期的版本設置相應的開發target,在Object-c中
instancesRespondToSelector:
方法告訴咱們所給的方法是否可用,例如:使用availableCaptureModesForCameraDevice:這個方法(在
4.0
之後纔是可
用的),咱們能夠這樣使用它。
1
、檢查一個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 image capture.
}
判斷一個弱鏈接的C函數是否可用,只要判斷函數的地址是否返回爲NULL,以CGColorCreateGenericCMYK 函數爲例,咱們能夠像如下那樣使用。
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方法是否可用,比較明確的爲地址是否爲NULL或零。你不能使用反運算符(!)來否認一個函數的可用性
檢測一個 external(extern)常量或一個通知的名字應當比較它的地址(address)--而不是符號的名稱, 判斷是否爲NULL or nil
3、弱鏈接整個Framework
好比一個在高版本中才出現的Framework,想在低版本使用他的特性。那你就必須弱鏈接那個使用的Framework,詳見官方的圖解---(其實就是在添加進去的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
4、條件編譯
for
不一樣的SDK
若是你不止基於一個IOS SDK編譯,你就可能須要爲base
sdk使用條件化,可使用在Availability.h中的定義。這個.h文件存在於系統的文件夾/usr/include的文件夾下,例如想在
Mac OS X v10.
5
(而不是IOS)中使用函數 CGColorCreateGenericCMYK
使用預處理指令
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
}
5、尋找出在程序中使用的以過期的實例
在IOS或Mac
OS中有時候API會過期,可是過期不表明着那些就從Library或framework中刪除,可是在使用的過程當中會報出warning,而且在不遠的
未來可能會被Apple從中移除。例如咱們在code中使用了過期的函數 HPurge那麼就會報出以下
'HPurge'
is deprecated (declared at /Users/steve/MyProject/main.c:
51
)
因此咱們應當在工程中查找出以下的警告而且修改。
6、肯定操做系統和Framework的版本
在運行時檢查IOS的版本
NSString *osVersion = [[UIDevice currentDevice] systemVersion];
在運行時檢查Mac OS X用Gestalt function 和 系統版本常量
另外,對於許多的Framework你能夠在運行時檢查指定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全局常量
小結:詳解IOS SDK兼容性引導的內容介紹玩玩了,但願經過本文的學習能對你有所幫助!
原文地址:http:
//blog.csdn.net/diyagoanyhacker/article/details/6673344
26
、NSDate 與 NSString 轉換
將字符串 「Fri Nov
11
09
:
06
:
27
+
0800
2011
」 轉換成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轉換成字符串:
NSDate *date = [NSDate date];
NSString * dateString = [format stringFromDate:date];
//字符串轉換成NSDate 須要設置NSLocale 不然真機上會失敗。
27
、數組中存儲數據查詢
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 總結
(
1
) NSAttributedString
NSAttributedString 能夠將一段文字中的部分文字設置單獨的字體和顏色。
與UITouch結合能夠實現點擊不一樣文字觸發不一樣事件的交互功能。
主要方法:
- (
void
)addAttribute:(NSString *)name value:(id)value range:(NSRange)range;
能夠設置某段文字的字體名稱,顏色,下滑線等信息。
- (
void
)removeAttribute:(NSString *)name range:(NSRange)range;
移除以前設置的字體屬性值。
- (
void
)addAttributes:(NSDictionary *)attrs range:(NSRange)range;
存儲某段文字包含的信息(包括字體屬性或其它,也能夠存儲一些自定義的信息)
- (NSDictionary *)attributesAtIndex:(NSUInteger)location effectiveRange:(NSRangePointer)range;
經過location來獲取某段文字中以前存儲的信息NSDictionary
//設置字體
CTFontRef aFont = CTFontCreateWithName((CFStringRef)textFont.fontName, textFont.pointSize, NULL);
if
(!aFont)
return
;
CTFontRef newFont = CTFontCreateCopyWithSymbolicTraits(aFont,
0.0
, NULL, kCTFontItalicTrait, kCTFontBoldTrait);
//將默認黑體字設置爲其它字體
[self removeAttribute:(NSString*)kCTFontAttributeName range:textRange];
[self addAttribute:(NSString*)kCTFontAttributeName value:(id)newFont range:textRange];
CFRelease(aFont);
CFRelease(newFont);
//設置字體顏色
[self removeAttribute:(NSString*)kCTForegroundColorAttributeName range:textRange];
[self addAttribute:(NSString*)kCTForegroundColorAttributeName value:(id)textColor.CGColor range:textRange];
//設置對齊 換行
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);
//圖像方向轉換
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 中的部分文字
相關方法:
CFArrayRef CTFrameGetLines (CTFrameRef frame )
//獲取包含CTLineRef的數組
void
CTFrameGetLineOrigins(
CTFrameRef frame,
CFRange range,
CGPoint origins[] )
//獲取全部CTLineRef的原點
CFRange CTLineGetStringRange (CTLineRef line )
//獲取line中文字在整段文字中的Range
CFArrayRef CTLineGetGlyphRuns (CTLineRef line )
//獲取line中包含全部run的數組
CFRange CTRunGetStringRange (CTRunRef run )
//獲取run在整段文字中的Range
CFIndex CTLineGetStringIndexForPosition(
CTLineRef line,
CGPoint position )
//獲取點擊處position文字在整段文字中的index
CGFloat CTLineGetOffsetForStringIndex(
CTLineRef line,
CFIndex charIndex,
CGFloat* secondaryOffset )
//獲取整段文字中charIndex位置的字符相對line的原點的x值
主要步驟:
1
)計算並存儲文字中保含的全部表情文字及其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
) 根據保存的表情文字的Range計算表情圖片的Frame
textFrame 經過CTFrameGetLines 獲取全部line的數組 lineArray
遍歷lineArray中的line經過CTLineGetGlyphRuns獲取line中包含run的數組 runArray
遍歷runArray中的run 經過CTRunGetStringRange獲取run的Range
判斷表情文字的location是否在run的Range
若是在 經過CTLineGetOffsetForStringIndex獲取x的值 y的值爲line原點的值
4
)Draw表情圖片到計算獲取到的Frame
(
3
)點擊文字觸發事件
主要步驟:
1
) 根據touch事件獲取點point
2
) textFrame 經過CTFrameGetLineOrigins獲取全部line的原點
3
) 比較point和line原點的y值獲取點擊處於哪一個line
4
) line、point 經過CTLineGetStringIndexForPosition獲取到點擊字符在整段文字中的 index
5
) NSAttributedString 經過index 用方法-(NSDictionary *)attributesAtIndex:(NSUInteger)location effectiveRange:(NSRangePointer)range 能夠獲取到點擊到的NSAttributedString中存儲的NSDictionary
6
) 經過NSDictionary中存儲的信息判斷點擊的哪一種文字類型分別處理
23
、視頻播放、編輯
轉載: http:
//www1.huachu.com.cn/read/readbookinfo.asp?sectionid=1000006772
對於不一樣的設備,視頻功能是各不相同的。全部的設備都可以回放視頻,可是僅有iPhone 3GS設備有記錄視頻的能力。對於每一個設備而言,都存在API可以讓您檢測哪些功能是可用的和哪些功能是不可用的,這樣就可以針對使用視頻功能的全部用戶建立優秀的用戶體驗。這一節內容討論如何才能將視頻集成到應用程序中,以及如何才能使用特定的設備記錄視頻。
10.2
.
1
播放視頻
iPhone SDK提供了一個簡單的控制器來在應用程序中播放視頻。MPMoviePlayerController類位於MonoTouch.MediaPlayer名稱空間中,它提供了播放影片、準備播放影片和中止播放影片的功能。程序清單
10
-
9
說明了如何開始播放視頻。第一行代碼顯示的是實例化一個新的影片播放器對象,並將視頻內容文件路徑傳入其構造函數內。第二行代碼簡單地調用了Play方法,該方法顯示影片播放器並開始播放視頻。
程序清單
10
-
9
播放視頻文件
var player =
new
MPMoviePlayerController(NSUrl.FromFilename(
"video.mp4"
));
player.Play();
若是但願使用外部視頻,並以漸進方式下載視頻,而不是直接播放設備上的視頻,那麼就要使用NSUrl的FromString方法,而不是使用FromFilename,並將視頻的URL地址傳入其中。固然,須要使用本身的外部視頻替換這裏的URL字符串。
var player =
new
MPMoviePlayerController(videoUrl);
player.Play();
您也許會注意到,在視頻開始播放以前有一個短暫的緩衝週期。這就是所謂的預加載過程。能夠設置視頻播放器上的通知,在視頻已經開始預加載時讓其引起一條消息,這樣就可以顯示加載屏幕,而後在預加載完成後開始顯示視頻。當視頻完成播放或者用戶改變視頻的縮放比例時,也可使用通知引起消息。
使用NSNotificationCenter類的DefaultCenter屬性添加觀察者,從而在通知產生時引起這些消息。能夠將觀察者看做將事件添加到特定動做上的一種方式,使用字符串做爲建立這些事件的方式,而不是使用您也許已經熟悉的C#內的強類型事件。對於本示例而言,只須要使用通知MPMoviePlayerContentPreloadDidFinishNotification和MPMoviePlayerPlaybackDid- FinishNotification。另外一個通知名爲MPMoviePlayerScalingModeDidChangeNotification。還要添加兩個NSObject類型的類變量,它們能夠做爲預加載和回放完成的觀察者。使用AddObserver方法,爲每一個觀察者傳入一個動做方法,當通知被調用時這些動做方法就會運行。可使用Lambda表達式之內聯方式放置這段代碼。當預加載通知被激活之後,只須要開始播放視頻,所以能夠調用MPMoviePlayerController上的Play方法;當回放通知激活之後,須要移除觀察者,並清除影片播放器實例。可使用活動指示器確保讓用戶知道當應用程序啓動時正在預加載視頻。程序清單
10
-
10
給出了完成這項工做的示例代碼。一樣,須要確保改變第
8
行代碼中的URL,讓其指向選擇的外部視頻。
程序清單
10
-
10
使用影片播放器觀察者
MPMoviePlayerController moviePlayer;
NSObject didFinishPreload, didFinishPlayback;
public
override
void
ViewDidLoad()
{
base.ViewDidLoad ();
moviePlayer =
new
MPMoviePlayerController(videoUrl);
activityIndicator.StartAnimating();
var centre = NSNotificationCenter.DefaultCenter;
var preloadFinish =
"MPMoviePlayerContentPreloadDidFinishNotification"
;
didFinishPreload = centre.AddObserver(preloadFinish,
(notify) => {
Console.WriteLine (
"Start playing movie"
);
activityIndicator.StopAnimating();
moviePlayer.Play();
});
var playbackFinished =
"MPMoviePlayerPlaybackDidFinishNotification"
;
didFinishPlayback = centre.AddObserver(playbackFinished,
(notify) => {
Console.WriteLine (
"Movie finished, Clean up"
);
centre.RemoveObserver(didFinishPreload);
centre.RemoveObserver(didFinishPlayback);
activityIndicator.Hidden =
true
;
moviePlayer.Dispose();
moviePlayer =
null
;
}); }
}
10.2
.
2
定製視頻播放器
影片播放器提供的功能是至關有限的,僅容許對兩個屬性根據須要進行調整,這兩個屬性是ScalingMode和MovieControlMode。
縮放模式對播放影片的長寬比進行設置。可用的長寬比選項爲Fill、AspectFill、AspectFit和None。
Fill選項用於讓視頻填滿整個屏幕,這樣視頻的邊緣會與屏幕吻合,可是可能沒法保持原有的長寬比。
AspectFill選項在視頻填滿整個屏幕時不會扭曲視頻,可是確實會對視頻進行裁剪,這樣視頻纔可以無縫地填滿這個屏幕。
AspectFit選項會保留視頻原有的長寬比,並讓視頻的邊緣儘量地與屏幕吻合,但若是視頻不是徹底吻合,那麼可能會露出背景視圖。
None選項不會調整視頻,而是按照視頻自身的大小進行播放。
使用MPMovieScalingMode枚舉,能夠將ScalingMode設置爲這個列表中的任何選項。參見圖
10
-
10
~圖
10
-
13
,其中給出了每一種縮放模式的示例。播放器的背景設置爲藍色(在這些圖中,背景是以淺灰色打印版本進行顯示的),所以能夠看到視頻大小和播放器大小之間的差別。注意,在這個示例中,Aspect Fit和Fill視頻是同樣的。這是由於視頻的當前長寬比容許視頻的邊緣與屏幕吻合,而無須改變長寬比。
圖
10
-
10
圖
10
-
11
圖
10
-
12
圖
10
-
13
另一個能夠針對視頻播放器修改的屬性是MovieControlMode。使用MPMovieControlMode枚舉,能夠將控件模式設置爲Default、Hidden或VolumeOnly。圖
10
-
14
和圖
10
-
15
給出了Default和VolumeOnly控件模式。Hidden模式隱藏了屏幕上全部默認的動做;若是但願讓本身提供的用戶界面位於視頻的上方,那麼該模式就頗有用。
圖
10
-
14
圖
10
-
15
影片播放器自己是做爲一個關鍵窗口出如今屏幕上的。爲了將自定義界面添加到影片播放器關鍵窗口的上方,能夠從應用程序中具備的窗口列表內獲取該關鍵窗口的引用(關鍵窗口在本質上是窗口框架內能夠得到的最頂層的可見視圖)。而後能夠簡單地將子視圖添加到影片播放器關鍵窗口中。由於影片播放器是以橫屏模式出現的,因此必須對疊加視圖進行變換,從而使其可以與橫屏模式匹配。程序清單
10
-
11
說明了如何使用代碼實現此處提到的全部內容。
程序清單
10
-
11
在視頻播放器上疊加視圖
public
MPMoviePlayerController mPlayer;
public
override
void
ViewDidLoad ()
{
base.ViewDidLoad ();
var button = UIButton.FromType(UIButtonType.RoundedRect);
button.Frame =
new
RectangleF(0f, 20f, 320f, 40f);
button.SetTitle(
"Play Video"
, UIControlState.Normal);
button.TouchUpInside += delegate(object sender, EventArgs e)
{
PlayMovie ();
var windows = UIApplication.SharedApplication.Windows;
if
(windows.Count() >
1
)
{
var moviePlayerWindow = UIApplication.SharedApplication.KeyWindow;
var customView =
new
MyOverlayView(
this
);
moviePlayerWindow.AddSubview(customView);
}
};
this
.View.AddSubview(button);
}
void
PlayMovie ()
{
var url = NSUrl.FromFilename(
"video.mp4"
);
mPlayer =
new
MPMoviePlayerController(url);
mPlayer.Play();
}
...
public
class
MyOverlayView : UIView
{
public
MyOverlayView (MainViewController mvc)
{
this
.Frame =
new
RectangleF(0f, 0f, 320f, 480f);
this
.Transform = CGAffineTransform.MakeRotation((
float
)(Math.PI /
2
));
UIButton button = UIButton.FromType(UIButtonType.RoundedRect);
button.SetTitle(
"Pause"
, UIControlState.Normal);
button.Frame =
new
RectangleF(65f, 360f, 190f, 32f);
button.TouchUpInside += delegate(object sender, EventArgs e) {
Console.WriteLine (
"Paused the video"
);
mvc.mPlayer.Pause();
};
this
.AddSubview(button);
}
}
圖
10
-
16
顯示的是在程序清單
10
-
11
中建立的疊加視圖。
圖
10
-
16
10.2
.
3
選取視頻
爲了讓用戶能夠從存儲在設備上的視頻列表中選取視頻,可使用UIImagePickerController,在本章前面已經使用過該類。由於面向iPhone的視頻功能很是相似於攝像頭功能,因此看到視頻功能屬於UIImagePickerController類的組成部分並不使人感到驚奇。在程序清單
10
-
6
中,咱們使用IsSourceTypeAvailable方法來肯定設備是否具備攝像頭。由於視頻功能僅限於iPhone3GS模型,因此只是弄清楚是否存在攝像頭並不足夠。這時就須要使用UIImagePickerController類上的AvailableMediaTypes靜態方法。
AvailableMediaTypes方法以源類型做爲輸入,返回設備上可用媒體類型的數組。圖像的媒體類型爲
public
.image,而視頻的媒體類型爲
public
.movie。若是該方法返回
public
.movie類型,那麼能夠將UIImagePickerController實例的MediaTypes屬性設置爲僅有
public
.movie媒體類型。程序清單
10
-
12
給出了以這種方式設置的選取器。
程序清單
10
-
12
使用圖像選取器控制器選取視頻
if
(HasVideoSupport())
{
UIImagePickerController picker =
new
UIImagePickerController();
picker.SourceType = UIImagePickerControllerSourceType.PhotoLibrary;
picker.MediaTypes =
new
[]{
"public.movie"
};
picker.Delegate =
new
MyImagePickerDelegate(
this
);
this
.PresentModalViewController(picker,
true
);
}
else
{
using (var alert =
new
UIAlertView(
"Whoops"
,
"No video support found"
,
null
,
"Ok!"
,
null
))
{
alert.Show();
}
}
...
bool HasVideoSupport()
{
var cameraType = UIImagePickerControllerSourceType.Camera;
var cameraSupport =
UIImagePickerController.IsSourceTypeAvailable(cameraType);
return
(!cameraSupport) ?
false
:
UIImagePickerController.AvailableMediaTypes(cameraType)
.Contains(
"public.movie"
);
}
在顯示該選取器時,注意到您只看到了視頻,由於視頻是能夠選取的惟一的媒體類型。圖
10
-
17
說明了如何顯示只選取視頻的選取器。
圖
10
-
17
在選取視頻之後,該選取器使用與圖像選取器相同的回調:FinishedPickingMedia。NSDictionary帶有兩個鍵:UIImagePickerControllerMediaURL和UIImagePickerControllerMediaType。媒體URL包含一個指向所選擇視頻的臨時位置的NSUrl對象。這就是您能夠處理視頻的地方—— 要麼將視頻移動到Documents文件夾中,要麼經過其餘方式使用視頻。臨時視頻存儲在應用程序的tmp文件夾中,OS在認爲合適的時候會將其清除。
10.2
.
4
記錄視頻
使用iPhone記錄視頻很是相似於使用iPhone進行拍照。在前一個示例中,能夠僅將源類型設置爲攝像頭而不是圖片庫的默認源類型,全部這些設置都是爲了記錄視頻而不是拍攝照片。固然,這就是假設您已經使用AvailableMediaTypes方法驗證了該設備能夠記錄視頻。注意,攝像頭控件會發生變化,從而反映出是記錄視頻而不是拍攝照片。做爲可選項,能夠選擇經過將ShowsCameraControls設置爲
false
來隱藏攝像頭控件;然而,在編寫本書的時候,若是不使用默認的攝像頭控件,那麼尚未方式能夠經過編程來記錄視頻。程序清單
10
-
13
是設置UIImagePickerController以記錄視頻的一個示例。圖
10
-
18
顯示的是視頻記錄屏幕。
程序清單
10
-
13
記錄視頻
public
override
void
ViewDidLoad ()
{
base.ViewDidLoad ();
UIButton button = UIButton.FromType(UIButtonType.RoundedRect);
button.Frame =
new
RectangleF(0f, 30f,
320
, 40f);
button.SetTitle(
"Record Video"
, UIControlState.Normal);
button.TouchUpInside += delegate(object sender, EventArgs e) {
var cameraType = UIImagePickerControllerSourceType.Camera;
if
(HasVideoSupport())
{
UIImagePickerController picker =
new
UIImagePickerController();
picker.SourceType = cameraType;
picker.MediaTypes =
new
[]{
"public.movie"
};
picker.Delegate =
new
MyImagePickerDelegate(
this
);
this
.PresentModalViewController(picker,
true
);
}
else
{
using (var alert =
new
UIAlertView(
"Whoops"
,
"No video support found"
,
null
,
"Ok!"
,
null
))
{
alert.Show();
}
}
};
this
.View.AddSubview(button);
}
...
bool HasVideoSupport()
{
var cameraType = UIImagePickerControllerSourceType.Camera;
var cameraSupport =
UIImagePickerController.IsSourceTypeAvailable(cameraType);
return
(!cameraSupport) ?
false
:
UIImagePickerController.AvailableMediaTypes(cameraType)
.Contains(
"public.movie"
);
}
圖
10
-
18
在記錄視頻時,還能夠設置視頻記錄的質量。質量越低,那麼獲得的視頻文件越小。能夠像下面的代碼這樣使用UIImagePickerControllerQualityType枚舉設置圖像選取器的VideoQuality屬性:
picker.VideoQuality = UIImagePickerControllerQualityType.Low;
該枚舉提供
3
個質量選項:High、Medium和Low。視頻記錄中使用的默認設置是Medium。在記錄視頻時可使用的另一個屬性是VideoMaximumDuration,這個屬性用於設置記錄視頻的最長持續時間(單位爲秒)。視頻最長能夠是
10
分鐘,記錄視頻的默認時間值也是
10
分鐘。
10.2
.
5
編輯視頻
採用與經過UIImagePickerController編輯圖像相同的方式,在記錄或選取視頻時也能夠將AllowEditing屬性設置爲
true
。這樣,從圖像選取器中選取了視頻之後,就可以有一個接口對視頻進行裁剪。與編輯圖像時不一樣,在完成編輯時,只會使用NSDictionary中的UIImagePickerCon-trollerMediaURL鍵得到臨時裁剪或編輯的視頻(而不是原始視頻),該鍵在選擇或記錄視頻後可用。臨時建立的視頻最終會被設備自動地清除。UIImagePickerControllerMediaURL對象屬於NSUrl類型,須要將該視頻對象強制轉換爲NSUrl類型來提取定位該文件所需的Path屬性。圖
10
-
19
顯示了圖像選取器視頻編輯器的外觀。
圖
10
-
19
可是,視頻選取器不是編輯視頻最值得推薦的方式。對於編輯視頻而言,最好使用專門的UIVideoEditorController類做爲替代。該視頻編輯器控制器爲您提供了一個編輯窗口,它相似於圖像選取器所使用的編輯窗口。然而,注意到用戶有兩個選項能夠選擇:Cancel和Save。UIVideoEditorController類對此提供了
3
個不一樣的事件:
UserCancelled 當用戶單擊Cancel按鈕時處理這個事件。
Saved 當用戶單擊Save按鈕時處理該事件。
Failed 當產生沒法預料的錯誤時會引起該事件,例如視頻的格式沒法編輯這樣的錯誤。
Saved事件返回編輯好的視頻文件的路徑,Failed事件返回一個NSError對象,UserCancelled事件不會返回任何額外的信息。若是但願得到原始文件的路徑,那麼能夠將發送方強制轉換爲UIVideoEditorController對象,而後使用該對象的VideoPath屬性。
視頻編輯器只能用在直屏模式中
有了視頻編輯器之後,經過分別設置VideoQuality和VideoMaximumDuration屬性,就能夠將編輯好的視頻設置爲較低的質量和強制編輯好的視頻具備最大時間長度。
建立視頻編輯界面是至關直觀的。實例化一個新的UIVideoEditorController,將VideoPath設置爲但願編輯的視頻的路徑,而後將視頻編輯器做爲一個模態視圖展現。由於沒法知道運行該應用程序的iPhone是否支持對視頻進行編輯,因此須要使用視頻編輯器的靜態方法CanEditVideoAtPath。傳入視頻路徑,若是該視頻能夠編輯,那麼該方法就返回
true
。程序清單
10
-
14
給出了一個建立專用視頻編輯器界面的示例,圖
10
-
20
給出了UIVideoEditorController界面的顯示外觀。
程序清單
10
-
14
使用專用視頻編輯器界面
if
(UIVideoEditorController.CanEditVideoAtPath(ChosenVideoPath))
{
var videoEditor =
new
UIVideoEditorController();
videoEditor.VideoPath = ChosenVideoPath;
videoEditor.Saved += delegate(object sender, UIPathEventArgs e) {
this
.DismissModalViewControllerAnimated(
true
);
// Handle edited video with e.Path
};
videoEditor.Failed += delegate(object sender, NSErrorEventArgs e) {
this
.DismissModalViewControllerAnimated(
true
);
// Handle error here with e.Error
};
videoEditor.UserCancelled += delegate(object sender, EventArgs e) {
this
.DismissModalViewControllerAnimated(
true
);
// Handle cancel
};
this
.PresentModalViewController(videoEditor,
true
);
}
圖
10
-
20
10.2
.
6
將視頻保存到相冊
在將圖像保存到相冊時,要使用UIImage類上的靜態方法保存文件。由於對視頻文件的全部引用都使用路徑而不是內存中的對象,因此UIVideo靜態類提供了將視頻保存到相冊中所需的方法。視頻功能僅限於特定的設備,所以在將視頻保存到相冊以前,須要檢查一下該設備是否可以真正將視頻保存到其相冊中。靜態方法IsCompatibleWithSavedPhotosAlbum提供了這種功能,若是傳入能夠保存到相冊的視頻的路徑,那麼該方法就會返回
true
。
爲了將視頻保存到相冊中,一旦經過檢查肯定該設備確實能夠保存視頻,那麼就可使用UIVideo類上的靜態方法SaveToPhotosAlbum。將但願保存的視頻的路徑傳入該方法,當保存視頻之後會觸發一個回調函數。程序清單
10
-
15
給出了完成這些任務的代碼。
程序清單
10
-
15
將視頻保存到相冊
var videoPath = videoSavePath;
if
(UIVideo.IsCompatibleWithSavedPhotosAlbum(videoPath))
{
UIVideo.SaveToPhotosAlbum(videoPath, delegate (string path,
NSError errors)
{
using (var alert =
new
UIAlertView(
"Success"
,
"Video saved!"
,
null
,
"Ok!"
,
null
))
{
alert.Show();
}
});
}
24
、CoreText基礎-字體必修課
轉自:http:
//www.dreamingwish.com/dream-2011/coretext-ji-chu-font-basis.html
介紹一些字體的術語,以及對應的英文名稱
字體(Font):是一系列字號、樣式和磅值相同的字符(例如:
10
磅黑體Palatino)。現多被視爲字樣的同義詞
字面(Face):是全部字號的磅值和格式的綜合
字體集(Font family):是一組相關字體(例如:Franklin family包括Franklin Gothic、Fran-klinHeavy和Franklin Compressed)
磅值(Weight):用於描述字體粗度。典型的磅值,從最粗到最細,有極細、細、book、中等、半粗、粗、較粗、極粗
樣式(Style):字形有三種形式:Roman type是直體;oblique type是斜體;utakuc type是斜體兼曲線(比Roman type更像書法體)。
x高度(X height):指小寫字母的平均高度(以x爲基準)。磅值相同的兩字母,x高度越大的字母看起來比x高度小的字母要大
Cap高度(Cap height):與x高度類似。指大寫字母的平均高度(以C爲基準)
下行字母(Descender):例如在字母q中,基線如下的字母部分叫下伸部分
上行字母(Ascender):x高度以上的部分(好比字母b)叫作上伸部分
基線(Baseline):一般在x、v、b、m下的那條線
描邊(Stroke):組成字符的線或曲線。能夠加粗或改變字符形狀
襯線(Serif):用來使字符更可視的一條水平線。如字母左上角和下部的水平線。
無襯線(Sans Serif):可讓排字員不使用襯線裝飾。
方形字(Block):這種字體的筆畫使字符看起來比無襯線字更顯眼,但還不到常見的襯線字的程度。例如Lubalin Graph就是方形字,這種字看起來好像是木頭塊刻的同樣
手寫體腳本(Calligraphic script):是一種仿效手寫體的字體。例如Murray Hill或者Fraktur字體
藝術字(Decorative):像繪畫般的字體
Pi符號(Pisymbol):非標準的字母數字字符的特殊符號。例如Wingdings和Mathematical Pi
連寫(Ligature):是一系列連寫字母如fi、fl、ffi或ffl。因爲字些字母形狀的緣由常常被連寫,故排字員已習慣將它們連寫。
25
、準確計算CoreText高度的方法
- (
int
)getAttributedStringHeightWithString:(NSAttributedString *) string WidthValue:(
int
) width
{
int
total_height =
0
;
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)string);
//string 爲要計算高度的NSAttributedString
CGRect drawingRect = CGRectMake(
0
,
0
, width,
1000
);
//這裏的高要設置足夠大
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, drawingRect);
CTFrameRef textFrame = CTFramesetterCreateFrame(framesetter,CFRangeMake(
0
,
0
), path, NULL);
CGPathRelease(path);
CFRelease(framesetter);
NSArray *linesArray = (NSArray *) CTFrameGetLines(textFrame);
CGPoint origins[[linesArray count]];
CTFrameGetLineOrigins(textFrame, CFRangeMake(
0
,
0
), origins);
int
line_y = (
int
) origins[[linesArray count] -
1
].y;
//最後一行line的原點y座標
CGFloat ascent;
CGFloat descent;
CGFloat leading;
CTLineRef line = (CTLineRef) [linesArray objectAtIndex:[linesArray count]-
1
];
CTLineGetTypographicBounds(line, &ascent, &descent, &leading);
total_height =
1000
- line_y + (
int
) descent +
1
;
//+1爲了糾正descent轉換成int小數點後捨去的值
CFRelease(textFrame);
return
total_height;
}
//關於line座標位置y爲下圖黑線所在位置 descent爲黑線下部分字體的高度
26
、自定義拷貝、粘貼窗口
(
1
)、重寫canBecomeFirstResponder方法
- (BOOL)canBecomeFirstResponder{
[
super
canBecomeFirstResponder];
return
YES;
}
(
2
)、建立自定義UIMenuController
UIMenuItem *share = [[UIMenuItem alloc] initWithTitle:@
"分享"
action:
@selector
(share:)];
UIMenuItem *email = [[UIMenuItem alloc] initWithTitle:@
"郵件"
action:
@selector
(email:)];
UIMenuItem *print = [[UIMenuItem alloc] initWithTitle:@
"打印"
action:
@selector
(print:)];
UIMenuController *menu = [UIMenuController sharedMenuController];
[menu setMenuItems:[NSArray arrayWithObjects:share, email,print, nil]];
[menu setTargetRect:self.frame inView:self.superview];
[menu setMenuVisible:YES animated:YES];
(
3
)、判斷顯示哪一個menu
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
[
super
canPerformAction:action withSender:sender];
if
( action ==
@selector
(share:) || action ==
@selector
(email:) || action ==
@selector
(print:))
{
return
YES;
}
else
{
return
NO;
}
}
27
、iOS本地推送通知方法
可在應用後臺執行時,本地彈出推送通知,也能夠定時觸發推送。
- (
void
)applicationDidEnterBackground:(UIApplication *)application
{
UIDevice* device = [UIDevice currentDevice];
BOOL backgroundSupported = NO;
if
([device respondsToSelector:
@selector
(isMultitaskingSupported)])
{
backgroundSupported = device.multitaskingSupported;
}
if
(backgroundSupported && _bgTask==UIBackgroundTaskInvalid)
{
UIApplication *app = [UIApplication sharedApplication];
_bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
}];
dispatch_async(dispatch_get_main_queue(), ^{
while
(app.applicationState==UIApplicationStateBackground && _bgTask!=UIBackgroundTaskInvalid && [app backgroundTimeRemaining] >
10
)
{
[NSThread sleepForTimeInterval:
1
];
NSLog(@
"background task %d left left time %d."
, _bgTask, (
int
)[app backgroundTimeRemaining]);
if
([app backgroundTimeRemaining] <
580
)
{
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if
(localNotif)
{
localNotif.alertBody = [NSString stringWithString:@
"測試本地通知消息,後臺提示功能。"
];
localNotif.alertAction = NSLocalizedString(@
"查看"
, nil);
localNotif.soundName = UILocalNotificationDefaultSoundName;
localNotif.applicationIconBadgeNumber =
1
;
[application presentLocalNotificationNow:localNotif];
[localNotif release];
break
;
}
}
}
NSLog(@
"background task %d finished."
, _bgTask);
[app endBackgroundTask:_bgTask];
_bgTask = UIBackgroundTaskInvalid;
});
}
}
28
、CoreText繪製文本出現行間距不等及解決辦法
轉自: http:
//willonboy.tk/?p=1163
最終在http:
//www.cocoanetics.com/2012/02/radar-coretext-line-spacing-bug/
找到了DTCoreText庫