計算總行數\總頁數
總數 : 2476
每頁顯示的最大數量 : 35
總頁數 : (2476 + 35 - 1) / 35
pagesCount = (總數 + 每頁顯示的最大數量 - 1) / 每頁顯示的最大數量
總數 : 1660
每一行顯示的最大數量 : 30
總行數 : (1660 + 30 - 1) / 30
rowsCount = (總數 + 每行顯示的最大數量 - 1) / 每行顯示的最大數量
查找字符串的常見方法
// 如果range.location == 0, 說明是以searchString開頭
// 如果range.location == NSNotFound或者range.length == 0, 說明沒找到對應的字符串
- (NSRange)rangeOfString:(NSString *)searchString;
// 是否以str開頭
- (BOOL)hasPrefix:(NSString *)str;
// 是否以str結尾
- (BOOL)hasSuffix:(NSString *)str;
// 是否包含了str(不管頭部\中間\尾部)
- (BOOL)containsString:(NSString *)str;
reloadData
tableView的更新方法,底層原理原來位置在哪,更新后自動定位到哪,不會改變位置,以后更新tableView的時候,不要用MJ_header beginRefresh,用tableView的reloadData方法,可以增加界面的流程性
NSUserDefault保存報錯
我原來認為NSUserDefaults存不了數組,又換成了字典,但是還是報錯,最后求助網友大神解決了,是我里邊的數據結構有"<null>",而NSUserDefaults是不能被成功解析并存入的,所有在存入之前需要將里邊的"<null>"改成""即可。
用代碼修改圖片顏色
- 1.首先需要是Xcode的assets里面的圖片.
- 2.在屬性面板里可以看到Render As,選擇Template Image.
- 3.在使用圖片的視圖中利用tintColor控制圖片顏色(比如UIImageView,UIButton).
UITabBarController的設置
UITabBarController系統默認的選中顏色是藍色,設置tintColor屬性,改變選中標簽的顏色
使用自定義圖片來設置tabBar,使用initWithTitle:image:tag:方法,蘋果官方文檔說明圖片的大小為30*30,Retina屏為60*60(stackoverflow上有大神指出,UITabBarItem圖標的最佳尺寸是48*32)
關于UIBezierpath
UIBezierPath 有個原生的方法- (void)appendPath:(UIBezierPath *)bezierPath, 這個方法作用是倆個路徑有疊加的部分則會鏤空.
設置UITabBar的tabBarItem的文字和圖片
//設置圖片居中,這里的4.5,根據實際中間按鈕圖片大小來決定
Vc.tabBarItem.imageInsets = UIEdgeInsetsMake(4.5, 0, -4.5, 0);
//設置不顯示文字,將title的位置設置成無限遠,就看不到了
Vc.tabBarItem.titlePositionAdjustment = UIOffsetMake(0, MAXFLOAT);
設置圖片拉伸
[self.msgBackGoundImageView setHighlightedImage:[[UIImage imageNamed:@"bg_chat_me"] resizableImageWithCapInsets:UIEdgeInsetsMake(20, 20, 8, 20) resizingMode:UIImageResizingModeStretch]];
oc源碼中經常出現的值
1 << 5
2的5次方
給動畫設置key
1. [self.imageView.layer addAnimation:animaGroup forKey:@"Animation"];
//動畫開始時- (void)animationDidStart:(CAAnimation *)anim{
if ([anim isEqual:[self.imageView.layer animationForKey:@"Animation"]]) {
NSLog(@"動畫組執行了");
}
}
2.[transformAnima setValue:@"TransformAnima" forKey:@"AnimationKey"];
if ([[anim valueForKey:@"AnimationKey"]isEqualToString:@"PositionAnima"]) {
NSLog(@"位置移動動畫執行結束");
} else if ([[anim valueForKey:@"AnimationKey"]isEqualToString:@"TransformAnima"]){
NSLog(@"旋轉動畫執行結束");
}}
``
##邊緣拖動
```objc
//UIScreenEdgePanGestureRecognizer跟pan(平移)手勢差不多,需要從邊緣進行拖動,在控制器轉換的時候是有用的
runtime關聯對象
objc_setAssociatedObject(self, &key, object, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
關聯對象中的對象相當于字典中的value,key相當于字典中的key。根據key可以取到你關聯的對象
presentationLayer
CALayer *layer = subView.layer.presentationLayer; //圖片的顯示層
每個圖層屬性的顯示值都被存儲在一個叫做呈現圖層的獨立圖層當中,他可以通過-presentationLayer方法來訪問。這個呈現圖層實際上是模型圖層的復制,但是它的屬性值代表了在任何指定時刻當前外觀效果。換句話說,你可以通過呈現圖層的值來獲取當前屏幕上真正顯示出來的值
#-如果你在實現一個基于定時器的動畫,而不僅僅是基于事務的動畫,這個時候準確地知道在某一時刻圖層顯示在什么位置就會對正確擺放圖層很有用了。
#-如果你想讓你做動畫的圖層響應用戶輸入,你可以使用-hitTest:來判斷指定圖層是否被觸摸,這時候對呈現圖層而不是模型圖層調用-hitTest:會顯得更有意義,因為呈現圖層代表了用戶當前看到的圖層位置,而不是當前動畫結束之后的位置。
//手機截屏
在iOS7 以前, 獲取一個UIView的快照有以下步驟: 首先創建一個UIGraphics的圖像上下文,然后將視圖的layer渲染到該上下文中,從而取得一個圖像,最后關閉圖像上下文,并將圖像顯示在UIImageView中。現在我們只需要一行代碼就可以完成上述步驟了:
[view snapshotViewAfterScreenUpdates:NO];
//設置背景為某張圖片
UIImage *launchImage = [UIImage imageNamed:@"圖片名稱"];
self.backgroundColor = [UIColor colorWithPatternImage:launchImage];
//contents是layer的一個屬性
transitionLayer.contents = (id)_imageView.layer.contents;
iOS根據陀螺儀等傳感器獲得夾角等數據
__weak typeof(self) weakSelf = self;
if ([self.motionManager isDeviceMotionAvailable]) {
[self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue]
withHandler:^(CMDeviceMotion * _Nullable motion,
NSError * _Nullable error) {
//獲取這個然后使用這個角度進行view旋轉,可以實現view保持水平的效果,設置一個圖片可以測試
double rotation = atan2(motion.gravity.x, motion.gravity.y) - M_PI;
weakSelf.arImageView.transform = CGAffineTransformMakeRotation(rotation);
//2. Gravity 獲取手機的重力值在各個方向上的分量,根據這個就可以獲得手機的空間位置,傾斜角度等
double gravityX = motion.gravity.x;
double gravityY = motion.gravity.y;
double gravityZ = motion.gravity.z;
//獲取手機的傾斜角度(zTheta是手機與水平面的夾角, xyTheta是手機繞自身旋轉的角度):
double zTheta = atan2(gravityZ,sqrtf(gravityX*gravityX+gravityY*gravityY))/M_PI*180.0;
double xyTheta = atan2(gravityX,gravityY)/M_PI*180.0;
}];
}
忽略某種類型的警告
BuildSeting -> Other Warning Flags -> -Wno-documentation
VR全息實景技術的實現
捕捉寵物小精靈
- 左右方向靠的是地圖定位利用didUpdateHeading
// 已經更新到用戶設備朝向時調用 左右定位
- 上下方向靠的是陀螺儀z軸偏移角度CMMotionManager
到處走
- 左右方向靠的是地圖定位,location Lat,Lng 計算夾角
tabBar只有圖片沒有文字
//設置圖片居中,這里的4.5,根據實際中間按鈕圖片大小來決定
Vc.tabBarItem.imageInsets = UIEdgeInsetsMake(4.5, 0, -4.5, 0);
//設置不顯示文字,將title的位置設置成無限遠,就看不到了
Vc.tabBarItem.titlePositionAdjustment = UIOffsetMake(0, MAXFLOAT);
SDImageCache是怎么做數據管理的?
SDImageCache分兩個部分,一個是內存層面的,一個是硬盤層面的。
內存層面的相當是個緩存器,以Key-Value的形式存儲圖片。當內存不夠的時候會清除所有緩存圖片。
用搜索文件系統的方式做管理,文件替換方式是以時間為單位,剔除時間大于一周的圖片文件。
當SDWebImageManager向SDImageCache要資源時,先搜索內存層面的數據,如果有直接返回,沒有的話去訪問磁盤,將圖片從磁盤讀取出來,然后做Decoder,將圖片對象放到內存層面做備份,再返回調用層。
數組倒序
[array reverseObjectEnumerator]
顯式動畫和隱式動畫
1、隱式動畫通過隱式事務實現動畫 。( 除顯式事務外,任何對于CALayer屬性的修改,都是隱式事務.這樣的事務會在run-loop中被提交. )
//此方法傳入NO啟動隱式動畫
[CATransaction setDisableActions:NO];
2、顯式動畫有多種實現方式,顯式事務是一種實現顯式動畫的方式。 ( 通過明確的調用begin,commit來提交動畫 )
//開始動畫
[CATransaction begin];
//顯式事務默認開啟動畫效果,kCFBooleanTrue關閉
[CATransaction setValue:(id)kCFBooleanFalse forKey:kCATransactionDisableActions];
//動畫執行時間
[CATransaction setValue:[NSNumber numberWithFloat:5.0f] forKey:kCATransactionAnimationDuration];
//開始提交執行動畫
[CATransaction commit];
在UITableView滾動到最底端的時候自動加載數據
當scrollview scroll的時候,可以根據判斷條件判斷此時的tableview已經滑到了最底端,以下是判斷條件 那個scrollview就是tableview
scrollView.contentOffset.y + (scrollView.frame.size.height) > scrollView.contentSize.height
就表示已經到底部了 可以進行在判斷條件內執行更多了
LaunchScreen.storyboard設置啟動頁黑屏
將啟動圖放在根目錄下就好了
系統定位方案
如果能夠接受GPS信息,那么優先采用GPS定位,否則采用WiFi或者蜂窩基站定位,在WiFi和蜂窩基站之間優先使用WiFi,如果無法使用WiFi才使用蜂窩基站定位
隱藏導航條底部的黑線
[self.navigationController.navigationBar setShadowImage:[UIImage imageWithColor:[UIColor clearColor]]];
CAShapeLayer
* CAShapeLayer的動畫都是對屬性strokeEnd的操作
CABasicAnimation *basic = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
basic.duration = 1.0;
basic.fromValue = @(0.1f);
basic.toValue = @(1.0f);
[_shapeLayer addAnimation:basic forKey:@"basic"];
關于輸入框隨鍵盤彈出而上移
* tableView或者scrollView的滾動而取消編輯的行為,全部放到
- scrollViewWillBeginDragging方法中,因為,鍵盤彈出后,再設置scrollView的滾動 -> contentOffset,不調用此方法,而調用scrollViewDidScroll方法
textView或者label,設置點擊位置高亮原理
//設置了textView的selectedRange為NSRange類型,selectedTextRange,為UITextRange類型,textView的范圍判斷是這樣判斷的
// 給定指定的range, 返回range對應的字符串的rect
// 返回數組的原因是因為文字可能換行
self.tv.selectedRange = spec.range;
NSArray *rects = [self.tv selectionRectsForRange:self.tv.selectedTextRange];
self.tv.selectedRange = NSMakeRange(0, 0);
for (UITextSelectionRect *selectionRect in rects) {
CGRect rect = selectionRect.rect;
if (rect.size.width == 0 || rect.size.height == 0) continue;
if (CGRectContainsPoint(rect, point)) {
return YES;
}
else
{
return NO;
}
}
TextKit
// MARK: -懶加載
/*
只要textStorage中的內容發生變化, 就可以通知layoutManager重新布局
layoutManager重新布局需要知道繪制到什么地方, 所以layoutManager就會文textContainer繪制的區域
*/
// 這里先講解三種類的關系:
//1、NSTextStorage保存并管理UITextView顯示的文字信息,并且可以靈活的修改文字屬性
//2、NSLayoutManager用于管理NSTextStorage中文字內容的排版布局
//3、NSTextContainer定義一個矩形區域用于存放已經進行了排版并設置好屬性的文字
fileprivate func setupSystem()
{
// 1.將layoutManager添加到textStorage
textStorage.addLayoutManager(layoutManager)
// 2.將textContainer添加到layoutManager
layoutManager.addTextContainer(textContainer)
}
override func layoutSubviews() {
super.layoutSubviews()
// 3.指定區域
textContainer.size = bounds.size
}
mutablePointer ->指針
縮放的本質是修改transform,而修改transform不會影響到view的bounds只有frame會受到影響
任何輸入控件都有兩個屬性(inputView 鍵盤,inputAccessoryView 工具條)
collectionView中cell之間有空隙原因
1、
minimumInteritemSpacing 和 minimumLineSpacing 都帶“ minimum ”前綴,說明是最小間距,但是并不保證 item 之間的間距一定是最小,取決于 autolayout 布局時, spacing = (屏幕 width -(itemWidth * itemNum) - contentInset.left - contentInset.right)/(itemNum - 1),spacing 的值是否為 0.5 的倍數
2、
似乎 cell.width 必須是整數,如果為小數的話就會有空隙
UIView彈簧動畫和關鍵幀動畫
1、彈性動畫
[UIView animateWithDuration:1. delay:0. usingSpringWithDamping:.4 initialSpringVelocity:5. options:(UIViewAnimationOptionCurveEaseIn) animations:^{
} completion:^(BOOL finished) {
}];
2、關鍵幀動畫
[UIView addKeyframeWithRelativeStartTime:0. relativeDuration:.25 animations:^{
}];
[UIView animateKeyframesWithDuration:1.5 delay:0 options:(UIViewKeyframeAnimationOptionAllowUserInteraction) animations:^{
} completion:^(BOOL finished) {
}];
兩種transform動畫的變化
CGAffineTransformConcat就是把兩種變化效果聯系起來,有個動態的過渡過程
約束設置(技巧)
1、類似textview,collectionView,tableView,scrollView,這種類型的控件,設置約束時,不要自己去計算高度,要使用他們的contentSize屬性去完成高度的計算,方便快捷(取巧)。
2、cell中有圖片排布的cell高度計算,不要在tableView的代理方法
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
來進行高度計算,麻煩而且顯得技術差。
我們應該在cell中使用 Masonry 代碼更新圖片或者其他控件的高度,動態更新,最后調用cell的【self layoutifNeed】方法,刷新cell高度
/// collectionView的高度用這個,不要用contentSize.height
self.LayoutH.constant = self.collectionView.collectionViewLayout.collectionViewContentSize.height + 20;
自定義轉場動畫時注意細節
- 1、present/dismiss 遵守<UIViewControllerTransitioningDelegate>協議, 轉場實現四個方法,分別需要-> 轉場時動畫對象和手勢對象。
self.transitioningDelegate = self;
self.modalPresentationStyle = UIModalPresentationCustom;
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source{
return [XWPresentOneTransition transitionWithTransitionType:XWPresentOneTransitionTypePresent];
}
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed{
return [XWPresentOneTransition transitionWithTransitionType:XWPresentOneTransitionTypeDismiss];
}
- (id<UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id<UIViewControllerAnimatedTransitioning>)animator{
return _interactiveDismiss.interation ? _interactiveDismiss : nil;
}
- (id<UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id<UIViewControllerAnimatedTransitioning>)animator{
XWInteractiveTransition *interactivePresent = [_delegate interactiveTransitionForPresent];
return interactivePresent.interation ? interactivePresent : nil;
}
2、而push/pop遵守<UINavigationControllerDelegate>代理方法,根據UINavigationControllerOperation類型不同進行判斷。
self.navigationController.delegate = pushVC;
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{
_operation = operation;
//分pop和push兩種情況分別返回動畫過渡代理相應不同的動畫操作
return [XWPageCoverTransition transitionWithType:operation == UINavigationControllerOperationPush ? XWPageCoverTransitionTypePush : XWPageCoverTransitionTypePop];
}
- (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController{
if (_operation == UINavigationControllerOperationPush) {
XWInteractiveTransition *interactiveTransitionPush = [_delegate interactiveTransitionForPush];
return interactiveTransitionPush.interation ? interactiveTransitionPush : nil;
}else{
return _interactiveTransitionPop.interation ? _interactiveTransitionPop : nil;
}
}
類似自定義轉場效果(沒有手勢而已)
//制造出和自定義轉場動畫相似的效果
UIImageView *imgV =[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, SXSCREEN_W, SXSCREEN_H)];
imgV.image = [self getImage];
UIWindow *window = [UIApplication sharedApplication].keyWindow;
[window addSubview:imgV];
[self.navigationController popViewControllerAnimated:NO];
imgV.alpha = 1.0;
[UIView animateWithDuration:0.3 animations:^{
imgV.frame = CGRectMake(0, SXSCREEN_H/2, SXSCREEN_W, 0);
imgV.alpha = 0.0;
} completion:^(BOOL finished) {
[imgV removeFromSuperview];
}];
iOS富文本和html字符串互轉
//html字符串轉換為富文本
NSString *htmlStr = @"我的<span style='color:red'>aafaf微</span>我的<span style='color:red'>aafaf微</span>";
NSAttributedString *att = [[NSAttributedString alloc] initWithData:[htmlStr dataUsingEncoding:NSUnicodeStringEncoding] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType} documentAttributes:nil error:nil];
//富文本轉換為html(最后相當于整個網頁代碼,會有css等)
NSDictionary *dic = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute:@(NSUnicodeStringEncoding)};
NSData *data = [att dataFromRange:NSMakeRange(0, att.length) documentAttributes:dic error:nil];
NSString *str = [[NSString alloc] initWithData:data encoding:NSUnicodeStringEncoding];
NSCache緩存(還是YYCahce比較好用)
* 1 NSCache和NSMutableDictionary的相同點與區別:
相同點:
NSCache和NSMutableDictionary功能用法基本是相同的。
區別:
NSCache是線程安全的,NSMutableDictionary線程不安全
NSCache線程是安全的,Mutable開發的類一般都是線程不安全的
當內存不足時NSCache會自動釋放內存(所以從緩存中取數據的時候總要判斷是否為空)
NSCache可以指定緩存的限額,當緩存超出限額自動釋放內存
緩存限額:
1) 緩存數量
@property NSUInteger countLimit;
2) 緩存成本
@property NSUInteger totalCostLimit;
蘋果給NSCache封裝了更多的方法和屬性,比NSMutableDictionary的功能要強大很多
網易新聞圖文混排實現猜想
1、根據網易接口返回的數據,自己編寫處理HTML代碼,進行圖文混排,這樣處理的好處在于可以自己編寫js或者css代碼,修改屬性,進行圖片緩存處理,保證圖片不會多次加載,方便管理。
webView加載圖片緩存問題,解決方法有兩種
1、在webView中加入js腳本,加載時拿到圖片地址,用SDWbeImage下載下來后,再調用腳本展示圖片。
2、通過NSURLProtocol,在加載時判斷有無圖片,有的話生成一個NSURLResponse對象,將圖片放進去,沒有的話,就去請求數據。
百度地圖中的問題。
1、解決了百度地圖起點與自己位置重疊時,自己位置將起點位置遮擋問題。在自定義大頭針代碼中加上這句,效果類似滴滴。
self.layer.zPosition = -1;
2、自定義annotation 和annotationView 以保證數據儲存和展示
3、百度地圖中
1.UIView和核心動畫區別?
核心動畫只能添加到CALayer
核心動畫一切都是假象,并不會改變真實的值。
app內購解決方案
內購,簡單說明一下,如果你購買的商品,是在本app中使用和消耗的,就一定要用內購,否則會被拒絕上線,例如:游戲幣,在線書籍,app中使用的道具等。如果購買的就是普通的商品,例如淘寶買東西等,就不需要用內購,想怎么玩都自己說了算。
1、如果一定要用支付寶的話就審核的時候用內購,上線以后后臺改配置用支付寶,不過這樣抓到的話會死的比較慘,就算采用這種方法還是要有購物的,要不然還是會被拒,說集成了支付寶沒用
2、外跳瀏覽器支付 不會被拒,對于外跳的 蘋果審核一般很少管
支付寶支付完成后的驗簽(同步異步)
驗簽是支付寶與后臺服務器的工作,手機端不用管。
1、同步即項目中使用的獲取到結果后調用后臺接口,我們可以拿到驗簽的結果。但是訂單的狀態是由后臺更改的,后臺說成功就是成功。
2、異步即支付寶調用支付時訂單order中的一個參數,notify_url,調用一個url,傳給后臺一些參數,進行驗證,驗證結構我們拿不到,但是,我們只需要顯示支付成功,訂單的狀態從后臺獲取就可以了。
iOS開發支付寶支付成功以后的回調問題
如果手機中安裝了支付寶,會走AppDelegate中的方法,但是我里面的log始終不打印,是不是和回調的notifyURL有關系呢
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
[[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
NSLog(@"result = %@",resultDic);
/*這里面不走*/
}];
return YES;
}
上面的這個方法走過之后,調用支付寶時的回調方法也會走,這個是問什么呢
[[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
NSLog(@"reslut = %@",resultDic);
}];
當客戶端調用支付寶軟件的時候,進入到支付寶,然后用home鍵進入后臺,把自己的客戶端給殺死,,此時在進入支付寶繼續支付,支付完成后,會進入appdelegate中調用openURL的方法,再次打開客戶端,block里面的結果此時就可以拿到了。
- http://www.cocoachina.com/bbs/read.php?tid-322784-page-1.html
支付寶支付和微信支付的區別和相同點
相同點:支付寶和微信支付完成后都會對商戶服務器有一個異步通知即notify_url。個人觀點:就算有異步通知,也應該請求服務器對訂單是否支付成功進行驗證。
不同點:1、支付寶沒有訂單查詢接口,而微信可以對訂單是否支付成功進行查詢。
2、支付寶支付成功之后的驗證操作方式只能是通知,而微信可以使用代理,通過代理進行驗證之后的操作。
雙擊定點圖片放大
UITapGestureRecognizer *)doubleTap
CGPoint point = [doubleTap locationInView:doubleTap.view];
CGFloat touchX = point.x;
CGFloat touchY = point.y;
touchX *= 1/self.scrollview.zoomScale;
touchY *= 1/self.scrollview.zoomScale;
touchX += self.scrollview.contentOffset.x;
touchY += self.scrollview.contentOffset.y;
CGRect zoomRect = [self zoomRectForScale:self.scrollview.maximumZoomScale withCenter:CGPointMake(touchX, touchY)];
[self.scrollview zoomToRect:zoomRect animated:YES];
- (CGRect)zoomRectForScale:(CGFloat)scale withCenter:(CGPoint)center
{
CGFloat height = self.frame.size.height / scale;
CGFloat width = self.frame.size.width / scale;
CGFloat x = center.x - width * 0.5;
CGFloat y = center.y - height * 0.5;
return CGRectMake(x, y, width, height);
}
NavicationControll中設置控件y值問題
Navbar的translucent屬性影響高度設置,還有設置圖片背景圖片,相當于設置translucent屬性為NO,從而影響設置y值問題。
1、設置的圖片有值時,y值會改變,//iOS7及以后的版本支持,self.view.frame.origin.y會下移64像素至navigationBar下方。在控制器中設置self.edgesForExtendedLayout = UIRectEdgeNone時,y值會回到0。
2、設置的圖片沒有時,即[UIImage new],這個時候y值還是0的狀態(這種情況需要注意,框架改變透明度也是利用runtime增加了屬性,對背景圖片設置[UIImage new]做到的)
//設置背景圖片會導致y值下移64,但是[UIImage new]不會改變y值
類似QQ空間效果實現原理
不能設置為tableViewHeader,因為,header的話也會隨著tableView的下拉而移動,要實現的話需要[tableView addSubview imageView],tableivew 設置內邊距為圖片高度,的方法來實現。
tableHeaderView與viewForHeaderInSection是不同的,不要混淆
tableHeaderView的高度并不是heightFroRowInSection獲取的,tableview -> headerView和footerView是自己設置的,不是代理方法獲取的,不是同一個東西
打開QQ指定聊天窗口
NSString *string = [NSString stringWithFormat:@"mqq://im/chat?chat_type=crm&uin=136279559&version=1&src_type=web"];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:string]];
app登錄頁面與主界面的切換
根據QQ界面顯示情況,登錄界面與主界面切換(登錄,退出),代碼實現為
self.view.window.rootViewController = rootVC;
而我之前的實現都是顯示登錄界面后再跳轉到別的界面,這樣體驗效果不好,之后的實現方式都換成這種。
視頻播放器
1、MPMoviePlayerController(可以自定義大小,工能足夠強大,封裝的很好,很難自定義樣式)
2、MPMoviePlayerViewController(全屏播放)
3、AVPlayer(播放狀態,進度,需要自己設置觀察者,需要借助AVPlayerLayer對象, 根據player創建圖層, 添加到視圖上否則只有聲音沒有圖像)
AVPlayer監聽的4中狀態分別為
- 1 status 預播放狀態,有三種情況
- 2 loadedTimeRanges 緩沖進度
- 3 playbackBufferEmpty seekToTime后,緩沖數據為空,而且有效時間內數據無法補充,播放失敗
- 4 playbackLikelyToKeepUp seekToTime后,可以正常播放,相當于readyToPlay,一般拖動滑竿菊花轉,到了這個這個狀態菊花隱藏
本地通知與遠程推送
##本地通知
* 在iOS中如果點擊一個彈出通知(或者鎖屏界面滑動查看通知),默認會自動打開當前應用。
由于通知由系統調度那么此時進入應用有兩種情況:
如果應用程序已經完全退出那么此時會調用
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法;<br>
如果此時應用程序還在運行(無論是在前臺還是在后臺)則會調用
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification方法接收消息參數。
##遠程推送
此函數無論是程序被殺死還是處于后臺,只要用戶點擊了通知,都會被調用,因此如果是iOS7,則不必在didFinishLaunchingWithOptions中做處理,只在下面函數做處理即可,此時應避免在didFinishLaunchingWithOptions函數中也做重復處理。
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
// userInfo
}
ios 10 之后蘋果有
//iOS10特有
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
iOS10系統的更新,蘋果給了我們2個代理方法來處理通知的接收和點擊事件,這兩個方法在<UNUserNotificationCenterDelegate>的協議中,
- http://www.lxweimin.com/p/bcece05517fc
- http://www.lxweimin.com/p/ad43bc1a970a
- http://www.lxweimin.com/p/f5337e8f336d
webView后退是否刷新
- UIWebView很弱,而且前進后退的時候還會reload
- WKWebView倒是不錯,性能各方面都和Safari差不多,也沒有這些reload的問題。不過WK的網絡請求不能通過NSURLProtocol攔截,經過同事“很不細致的調研”發現WK的網絡請求是跨進程