1、概述
UIKit框架中有年夜量的控件供開辟者應用,在IOS開辟中不只可以直接應用這些控件還可以在這些控件的基本長進行擴大打造本身的控件。在這個系列中假如每一個控件都引見一遍確切沒有需要,所謂授人以魚不如授人以漁,這裡會盡量讓年夜家明確個中的道理,找一些典范的控件停止解釋,如許一來年夜家便可以舉一反三。明天我們重要來看一下UIScrollView的內容:
2、UIView
在熟習UIScrollView之前很有需要說一下UIView的內容。在上一篇文章也簡略的對UIView停止了引見,然則因為那篇文章的重要內容是給年夜家一個IOS開辟的整體印象,是以並沒有體系的引見。別的因為UIScrollView的父類是UIView,一切在評論辯論UIScrollView之前也很有需要把UIView的常識給彌補上,如許年夜家在應用UIScrollView的某些辦法時也不至於無從下手。
既然UIView是一切控件的父類,那末關於一些經常使用的辦法我們很有需要弄清晰,其其實Xcode中要懂得一個類有哪些屬性和辦法特殊簡略,只需按住apple鍵點擊類名便可以定位到這個類中檢查相干界說(在往後的開辟中我們會常常這麼來做,究竟要記住IOS開辟中一切的API是不實際的,有些API我們可以經由過程這類辦法來查找),例如我們可以檢查這個類的內容:
固然UIView的界說文件(.h文件)也是相當長的,我們假如全體截圖也沒成心義。這裡列出經常使用的屬性和辦法。
留意下面一切的地位屬性都是絕對於其父控件而言(不是絕對於屏幕而言),多半屬性比擬簡略這裡不再具體說明,我們重點說明一下autoresizingMask、transform屬性。
3、autoresizingMask
autoresizingMask這個屬性普通我們停止屏幕扭轉的時刻常常用到,它的值是一個列舉類型:
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) { UIViewAutoresizingNone = 0, //不停止主動調劑 UIViewAutoresizingFlexibleLeftMargin = 1 << 0, //主動調劑與superview左邊間隔,右邊間隔堅持不變 UIViewAutoresizingFlexibleWidth = 1 << 1, //主動調劑控件本身寬度,包管與superview閣下間隔不變 UIViewAutoresizingFlexibleRightMargin = 1 << 2, //主動調劑與superview右邊間隔,左邊間隔堅持不變 UIViewAutoresizingFlexibleTopMargin = 1 << 3, //主動調劑與superview頂部間隔,底部間隔堅持不變 UIViewAutoresizingFlexibleHeight = 1 << 4, //主動調劑控件本身高度,包管與superview高低間隔不變 UIViewAutoresizingFlexibleBottomMargin = 1 << 5 //主動調劑與superview底部間隔,頂部間隔堅持不變 };
經由過程正文年夜家應當年夜概懂得每一個列舉值的意義,然則我們曉得列舉常常停止按位或操作(“|”),例如假如autoresizingMask=UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleLeftMargin那末iOS若何處置呢?此時會主動調劑右邊的間隔和控件本身寬度,右邊間隔不變,同時包管左邊間隔和控件寬度一致比例的調劑(延伸或延長)。例如在iPhone 5中,假如一個按鈕假定本身寬度為200,閣下側間隔均為60(左邊和寬度比例3:10),當從豎屏扭轉到橫屏的時刻(此時寬度由320變成568,留意假如有狀況欄則寬度變成568-20=548),因為右邊邊距不變成60,依據比例左邊邊距應當是(568-60)*(3/13)=117,寬度為:(568-60)*(10/13)=391。
請看上面的代碼(上面例子經由過程純代碼方法創立iOS運用,而且自界說一個KCMainViewController):
AppDelegate.m
// // AppDelegate.m // UIViewAndUIScrollView // // Created by Kenshin Cui on 14-2-23. // Copyright (c) 2014年 Kenshin Cui. All rights reserved. // #import "AppDelegate.h" #import "KCMainViewController.h" #import "KCTransformViewController.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window=[[UIWindow alloc]initWithFrame:[UIScreen mainScreen].applicationFrame]; KCMainViewController *mainController=[[KCMainViewController alloc]init]; self.window.rootViewController=mainController; self.window.backgroundColor=[UIColor colorWithRed:249/255.0 green:249/255.0 blue:249/255.0 alpha:1]; [self.window makeKeyAndVisible]; return YES; } - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - (void)applicationDidEnterBackground:(UIApplication *)application { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - (void)applicationWillEnterForeground:(UIApplication *)application { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - (void)applicationDidBecomeActive:(UIApplication *)application { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } @end
KCMainViewController.m
// // KCMainViewController.m // UIViewAndUIScrollView // // Created by Kenshin Cui on 14-2-23. // Copyright (c) 2014年 Kenshin Cui. All rights reserved. // #import "KCMainViewController.h" @interface KCMainViewController (){ UIButton *_btn; //公有變量 } @end @implementation KCMainViewController - (void)viewDidLoad { [super viewDidLoad]; //添加一個Button _btn=[[UIButton alloc]initWithFrame:CGRectMake(60, 100, 200, 50)]; _btn.backgroundColor=[UIColor orangeColor]; [_btn setTitle:@"Hello,world!" forState:UIControlStateNormal]; _btn.autoresizingMask=UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleLeftMargin; [self.view addSubview:_btn]; } #pragma mark 屏幕扭轉事宜 -(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{ NSLog(@"%@",NSStringFromCGRect(_btn.frame)); } @end
在下面的代碼中設置了window的配景為灰色,固然下面有一個UIView然則我們可以看到終究後果是灰色的,這解釋UIView默許是通明的。別的界說了一個公有成員變量_btn,這類界說方法年夜家今後會常常用到。
運轉後果:
豎屏
橫屏
留意下面履行前請先隱蔽iOS狀況欄目,全局隱蔽iO狀況欄的辦法:
1.在info.plist 中設置Status bar is initially hidden為YES
2.在info.plist中設置View controller-based status bar appearance 為NO
4、transform
transform我們普通稱為形變屬性,其實質是經由過程矩陣變更轉變控件的年夜小、地位、角度等,這裡我們經由過程一個例子來看一下詳細的操作,鄙人面的例子中我們也會看到UIImageView控件的經常使用操作。
KCTransformViewController.m
// // KCTransformViewController.m // UIViewAndUIScrollView // // Created by Kenshin Cui on 14-2-23. // Copyright (c) 2014年 Kenshin Cui. All rights reserved. // #import "KCTransformViewController.h" //界說rgb色彩 #define NORMAL_COLOR [UIColor colorWithRed:75/255.0 green:160/255.0 blue:253/255.0 alpha:1] #define HIGHLIGHTED_COLOR [UIColor colorWithRed:197/255.0 green:221/225.0 blue:249/225.0 alpha:1] //按鈕操作 typedef void(^ ButtonHandle)(); @interface KCTransformViewController (){ UIImageView *_imageView;//圖片控件 UIButton *_btnRotation;//扭轉按鈕 UIButton *_btnScale;//縮放按鈕 UIButton *_btnTranslate;//挪動按鈕 } @end @implementation KCTransformViewController - (void)viewDidLoad { [super viewDidLoad]; [self addImageView]; [self addRotationButton]; [self addScaleButton]; [self addTranslateButton]; } #pragma mark 添加圖片控件 -(void)addImageView{ //直接應用圖片稱號,體系會主動到資本文件中找到對應的文件 UIImage *image=[UIImage imageNamed:@"promo_ios8.png"]; //假如應用initWithImage停止初始化則控件年夜小會主動設置成圖片年夜小 _imageView=[[UIImageView alloc]initWithImage:image]; _imageView.frame=CGRectMake(20, 20, 280, 154); //設置內容填充形式為等比例填充 _imageView.contentMode=UIViewContentModeScaleaspectFit; //self.view就是每一個視圖掌握器中的view屬性 [self.view addSubview:_imageView]; } #pragma mark 添加扭轉按鈕 -(void)addRotationButton{ _btnRotation=[self getButton]; _btnRotation.frame=CGRectMake(20, 400, 280, 30); [_btnRotation setTitle:@"扭轉" forState:UIControlStateNormal]; //添加按鈕點擊事宜 [_btnRotation addTarget:self action:@selector(rotation:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:_btnRotation]; } #pragma mark 添加縮放按鈕 -(void)addScaleButton{ //在下面一個按鈕地位的基本上確認以後地位 CGRect scaleButtonFrame=_btnRotation.frame; scaleButtonFrame.origin.y+=40; _btnScale =[self getButton]; _btnScale.frame=scaleButtonFrame; [_btnScale setTitle:@"縮放" forState:UIControlStateNormal]; //添加按鈕點擊事宜 [_btnScale addTarget:self action:@selector(scale:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:_btnScale]; } #pragma mark 添加挪動按鈕 -(void)addTranslateButton{ CGRect translateButtonFrame=_btnScale.frame; translateButtonFrame.origin.y+=40; _btnTranslate =[self getButton]; _btnTranslate.frame=translateButtonFrame; [_btnTranslate setTitle:@"挪動" forState:UIControlStateNormal]; [_btnTranslate addTarget:self action:@selector(translate:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:_btnTranslate]; } #pragma mark 圖片扭轉辦法,留意參數中的btn表現以後點擊按鈕 -(void)rotation:(UIButton *)btn{ [self animation:^{ //留意扭轉角度必需是弧度,不是角度 CGFloat angle=M_PI_4;//M開首的宏都是和數學(Math)相干的宏界說,M_PI_4表現四分之派,M_2_PI表現2派 //應用CGAffineTransformMakeRotation取得一個扭轉角度形變 //然則須要留意tranform的扭轉不會主動在本來的角度長進行疊加,所以上面的辦法扭轉一次今後再點擊按鈕不會扭轉了 //_imageView.transform=CGAffineTransformMakeRotation(angle); //應用CGAffineTransformRotate在本來的基本上發生一個新的角度(固然也能夠界說一個全局變量本身累加) _imageView.transform=CGAffineTransformRotate(_imageView.transform, angle); }]; } #pragma mark 圖片縮放辦法 -(void)scale:(UIButton *)btn{ // [self animation:^{ // CGFloat scalleOffset=0.9; // //_imageView.transform=CGAffineTransformMakeScale(scalleOffset, scalleOffset); // _imageView.transform= CGAffineTransformScale(_imageView.transform, scalleOffset, scalleOffset); // }]; //平日我們應用UIView的靜態辦法完成動畫而不是本身寫一個辦法 [UIView animateWithDuration:0.5 animations:^{ CGFloat scalleOffset=0.9; //_imageView.transform=CGAffineTransformMakeScale(scalleOffset, scalleOffset); _imageView.transform= CGAffineTransformScale(_imageView.transform, scalleOffset, scalleOffset); }]; } #pragma mark 圖片挪動辦法 -(void)translate:(UIButton *)btn{ [self animation:^{ CGFloat translateY=50; //_imageView.transform=CGAffineTransformMakeTranslation(0, translateY); _imageView.transform=CGAffineTransformTranslate(_imageView.transform, 0, translateY); }]; } #pragma mark 動畫履行辦法,留意這裡可使用UIView的animateWithDuration辦法取代這裡只是為了演示 -(void)animation:(ButtonHandle)handle{ //開端動畫 [UIView beginAnimations:@"animation" context:nil]; //設置動畫履行時光 [UIView setAnimationDuration:0.5]; handle(); //履行動畫操作 [UIView commitAnimations]; } #pragma mark 獲得一個按鈕,同一按鈕款式 -(UIButton *)getButton{ UIButton *button =[[UIButton alloc]init ]; //設置正常狀況下字體色彩 [button setTitleColor:NORMAL_COLOR forState:UIControlStateNormal]; //設置高亮狀況下的字體色彩 [button setTitleColor:HIGHLIGHTED_COLOR forState:UIControlStateHighlighted]; return button; } @end
1)、取得CGAffineTransform有多種辦法,例如應用CGAffineTransformMake,然則關於矩陣操作絕對比擬費事,現實上iOS曾經為我們預備好了三個辦法:CGAffineTransformMakeRotation(扭轉)、CGAffineTransformMakeScale(縮放)、CGAffineTransformMakeTranslation(挪動);
2)、transform停止扭轉、縮放、挪動的時刻不是在本來的基本上增量形變的,是以假如須要連續在本來的基本上扭轉、縮放、挪動那末每次須要在本來的基本上增長或削減。固然,我們可以界說一個全局變量停止累加,然則現實上iOS曾經為我們供給好了三個對應的辦法,分離用於在本來的角度、縮放、挪動地位的基本上做出修正:CGAffineTransformRotate、CGAffineTransformScale、CGAffineTransformTranslate;
3)、Objc語律例定不許可直接修正一個對象的構造體屬性的成員,只能給這個屬性直接賦值為一個構造體類型,例如下面的代碼中假如寫成“_btnRotation.frame.origin.x=380;”是不准確的;
4)、下面的代碼中我們用到了UIView的動畫相干辦法,在iOS開辟中動畫開辟異常簡略,並且動畫和邏輯處置是完整分別的,只需在兩個動畫辦法之間修正一個控件的屬性那末現代碼履行時就會主動添加動畫後果,為了溫習後面的block這裡我們完成了一個相似於animation辦法,相似於UIView的animateWithDuration靜態辦法的功效,僅僅為了解釋它的完成道理,現實開辟中可以直接挪用animateWithDuration便可(並且它有多種重載);
運轉後果:
留意在iOS開辟中推舉應用png圖片,iOS會對png圖片停止優化。
5、UIScrollView
經由過程下面的引見信任年夜家關於UIView的根本操作應當比擬熟習了,那末上面就看一下UIView的子控件UIScrollView 。望文生義,這是一個可以處置轉動操作的視圖,UIScrollView在開辟進程中應用很頻仍,並且它也常常作為其他控件的子控件,例如UITableView就繼續自UIScrollView。 我們照樣先看一下UIScrollView的經常使用屬性和辦法:
contentSize、contentInset、contentOffset在開辟中會常常應用,為了贊助年夜家懂得這裡以圖形的情勢展示三者之間的關系:
關於下面列出的幾個辦法,我們有需要說一下它們的履行次序:
a.假如我們拖動一個UIScrollView中的子控件挪動的時刻它的履行次序以下:開端拖拽,轉動,轉動…,停滯拖拽,將要停滯轉動,轉動,轉動…,停滯轉動。
白色部門有能夠履行也有能夠不履行,症結看你拖拽的停滯的時刻是忽然停滯照樣有一段慣性讓他持續履行(就似乎剎車一樣,假如是急剎車就沒有前面的慣性滑動了,假如是漸漸踩剎車能夠會有一段滑動間隔)。然則不論怎樣樣轉動事宜會一向履行,是以假如在這個事宜中停止某種操作必定要留意機能。
b.假如我們縮放UIScrollView的子控件的時刻它的履行次序以下:開端縮放,轉動,轉動…,停滯縮放。異樣在這個進程中轉動事宜會一向挪用(固然假如縮放進程中手指有其余舉措也能夠會觸發其他事宜,這個年夜家可以本身領會一下)。
上面我們簡略做一個例子
KCScrollViewController.h
// // KCScrollViewController.h // UIViewAndUIScrollView // // Created by Kenshin Cui on 14-2-23. // Copyright (c) 2014年 Kenshin Cui. All rights reserved. // #import <UIKit/UIKit.h> @interface KCScrollViewController : UIViewController @property (nonatomic,strong) UIScrollView *scrollView; @property (nonatomic,strong) UIImageView *imageView; @end
KCScrollViewController.m
// // KCScrollViewController.m // UIViewAndUIScrollView // // Created by Kenshin Cui on 14-2-23. // Copyright (c) 2014年 Kenshin Cui. All rights reserved. // #import "KCScrollViewController.h" //完成UIScrollView署理 @interface KCScrollViewController ()<UIScrollViewDelegate> @end @implementation KCScrollViewController - (void)viewDidLoad { [super viewDidLoad]; //添加scrollView控件 //留意UIScreen代表以後屏幕對象,其applicationFrame是以後屏幕內容區域 _scrollView =[[UIScrollView alloc]initWithFrame:[UIScreen mainScreen].applicationFrame]; //_scrollView.backgroundColor=[UIColor redColor]; _scrollView.contentMode=UIViewContentModeScaleToFill; [self.view addSubview:_scrollView]; //添加圖片控件 UIImage *image=[UIImage imageNamed:@"wwdc14-labs-hero-background.jpg"]; _imageView=[[UIImageView alloc]initWithImage:image]; [_scrollView addSubview:_imageView]; //contentSize必需設置,不然沒法轉動,以後設置為圖片年夜小 _scrollView.contentSize=_imageView.frame.size; //完成縮放:maxinumZoomScale必需年夜於minimumZoomScale同時完成viewForZoomingInScrollView辦法 _scrollView.minimumZoomScale=0.6; _scrollView.maximumZoomScale=3.0; //設置署理 _scrollView.delegate=self; //邊距,不屬於內容部門,內容坐標(0,0)指的是內容的左上角不包含界限 //_scrollView.contentInset=UIEdgeInsetsMake(10, 20, 10, 20); //顯示轉動內容的指定地位 //_scrollView.contentOffset=CGPointMake(10, 0); //隱蔽轉動條 _scrollView.showsHorizontalScrollIndicator=NO; _scrollView.showsVerticalScrollIndicator=NO; //禁用彈簧後果 //_scrollView.bounces=NO; } #pragma mark 完成縮放視圖署理辦法,不完成此辦法沒法縮放 -(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{ return _imageView; } -(void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView{ NSLog(@"scrollViewWillBeginDecelerating"); } -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{ NSLog(@"scrollViewDidEndDecelerating"); } -(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{ NSLog(@"scrollViewWillBeginDragging"); } -(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{ NSLog(@"scrollViewDidEndDragging"); } -(void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view{ NSLog(@"scrollViewWillBeginZooming"); } -(void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale{ NSLog(@"scrollViewDidEndZooming"); } //-(void)scrollViewDidScroll:(UIScrollView *)scrollView{ // NSLog(@"scrollViewDidScroll"); //} #pragma mark 當圖片小於屏幕寬高時縮放後讓圖片顯示到屏幕中央 -(void)scrollViewDidZoom:(UIScrollView *)scrollView{ CGSize originalSize=_scrollView.bounds.size; CGSize contentSize=_scrollView.contentSize; CGFloat offsetX=originalSize.width>contentSize.width?(originalSize.width-contentSize.width)/2:0; CGFloat offsetY=originalSize.height>contentSize.height?(originalSize.height-contentSize.height)/2:0; _imageView.center=CGPointMake(contentSize.width/2+offsetX, contentSize.height/2+offsetY); } @end
運轉後果以下:
默許情形下縮放後的內容會放到UIScrollView的內容肇端地位,所以假如要想縮放後內容放到中央我們必需本身保護它的地位,下面曾經給出了設置辦法。
擴大—ARC
iOS5以後引入了ARC特征,法式中不消本身retain、release、autorelease操作,編譯器會主動為你治理內存,編譯時主動加上內存釋放的代碼,應用起來很便利。ARC是編譯器特征,而不是iOS運轉時特征,其本質照樣手動治理內存,只是響應內存治理的代碼編譯器會主動生成罷了。因為ARC是編譯器特征,是以它治理內存的規矩和之前ObjC內存治理是相似的,只需有一個對象援用(強援用)指向這個對象,那末這個對象就不會被釋放。
在開啟ARC以後我們可使用四個症結字潤飾我們的成員變量、部分變量和屬性:
strong(潤飾變量用__strong):強援用,相當於本來的retain,每次賦值援用計數器加1,只需指針援用這個對象,這個對象就不會被燒毀;
weak(潤飾變量用__weak):弱援用,相當於assign,和assign分歧的是當對象釋放後該變量會設置為nil避免野指針(固然之前講過的內容中assign都是運用於根本數據類型,其實它也完整可以潤飾對象類型的屬性);
unsafe_unretained(潤飾變量用__unsafe_unretained):和weak相似,差別就是假如對象釋放後它不會像weak一樣主動將指針設置為nil,有能夠湧現野指針;
__autoreleasing(只能潤飾變量不克不及潤飾屬性):潤飾一個對象在應用完以後主動釋放,平日用於延遲釋放內存,同在MRC下挪用對象的autorelease辦法是等效的;
留意:
除weak(留意不是__weak)以外其他的潤飾符在非ARC(MRC)下應用也不會報錯,然則這麼做並沒有甚麼意義,由於在編譯時會被疏忽。舉例來講:在MRC下應用__autoreleasing潤飾一個對象也不會主動釋放,而是應當應用autorelease辦法。異樣的,在MRC下應用__strong來潤飾一個變量也異樣是會直接疏忽這個症結字;
unsafe_unretained(或許__unsafe_unretained)和weak(或__weak)的差別不年夜,只是weak(或__weak)做釋放以後會將變量設置為nil防止野指針,之所以今朝兩個症結字還存在重要是由於後者在在iOS5.0及lion以後才湧現,出於兼容性斟酌,是以推舉應用weak或__weak;
__autoreleasing重要用於函數參數是ObjC對象指針的情形下(也就是參數”NSObject **obj”類型,指針的指針),典范的運用就是NSError的應用。在這類情形下,常常須要在函數外部從新創立一個對象給傳入的參數賦值(修正參數內容),假如應用__autorelesing參數編譯器在處置外部函數時會應用主動釋放池,即包管外部對象可以或許正常釋放又可以修正內部變量。之所以許多時刻應用NSError作為參數傳遞到一些辦法中未將變量聲明為__autoreleasing是由於編譯器曾經主動做了處置(是以,假如斟酌到機能推舉照樣加上此參數);
strong和weak在iOS開辟進程中常常應用,這裡簡略看一個例子(留意這兩個參數依然可以潤飾屬性,意義是完整一樣的在此不再演示)
KCPerson.h
// // KCPerson.h // ARC // // Created by Kenshin Cui on 14-2-23. // Copyright (c) 2014年 Kenshin Cui. All rights reserved. // #import <Foundation/Foundation.h> @interface KCPerson : NSObject @property (nonatomic,assign) int no; @end
KCPerson.m
// // KCPerson.m // ARC // // Created by Kenshin Cui on 14-2-23. // Copyright (c) 2014年 Kenshin Cui. All rights reserved. // #import "KCPerson.h" @implementation KCPerson -(NSString *)description{ return [NSString stringWithFormat:@"no=%i",_no]; } @end
main.m
// // main.m // ARC // // Created by Kenshin Cui on 14-2-23. // Copyright (c) 2014年 Kenshin Cui. All rights reserved. // #import <Foundation/Foundation.h> #import "KCPerson.h" int main(int argc, const char * argv[]) { @autoreleasepool { //strong __strong KCPerson *person1=[[KCPerson alloc]init]; __strong KCPerson *person2=person1; person1.no=1; NSLog(@"%@",person2); //成果:no=1 person1=nil; NSLog(@"%@",person2); //成果:no=1 //weak __strong KCPerson *person3=[[KCPerson alloc]init]; __weak KCPerson *person4=person3; person3.no=3; NSLog(@"%@",person4); //成果:no=3 person3=nil; NSLog(@"%@",person4); //成果:(null) } return 0; }
因為person1和person2都指向一個對象而且都是強援用,是以當person1設置為nil時對象依然不會釋放,所以此時person2照樣指向這個對象,可以正常輸入;person3和它指向的對象是強援用,而person4是弱援用,是以當person3設置為nil後,對象沒有了強援用就會釋放,此時再打印person4天然就是null。為了解釋strong和weak的應用,上面應用圖形方法描寫下面的情形:
strong--person1和person2的關系
weak--person3和person4的關系
由此得出以下結論:
1、不論是怎樣治理內存都是針對對象類型而言(不管是strong,weak都不克不及運用到根本數據類型),關於根本數據類型直接聲明為assign便可以了,它不須要我們本身治理內存;
2、一切的指針變量默許都是__strong類型,是以我們平日省略不寫__strong;
3、假如一個對象沒有強援用以後即便存在弱援用它也會被釋放,與此同時弱援用將被設置為nil;
回過火來我們看一下後面UIScrollView部門的幾個屬性都設置成了strong,假如設置成weak行不可呢?謎底能否定的。假如我們設置成weak,Xcode起首就會給出提出“Assigning retained object to weak variable; object will be released after assignment”,就是說ObjC對象賦值給一個弱援用變量,賦值以後對象會立刻被燒毀。其實依據後面引見的內容很輕易懂得,就拿下面的scrollView屬性來講,假如設置為weak,當應用“_scrollView =[[UIScrollView alloc]initWithFrame:[UIScreen mainScreen].applicationFrame];”給這個變量賦值,依據後面的常識假如一個對象沒有了強援用就會被燒毀,賦值完成後運轉時看到這個對象只要一個弱援用_scrollView天然就會燒毀這個對象,是以假如運轉下面的法式就達不到之前看到的後果了。
然則假如應用storyboard來設計界面的時刻,我們會發明體系默許生成的屬性就是weak,此時為何不會燒毀呢?那是由於它的頂層對象堅持了一個強援用strong,是以這個對象不會被燒毀。如許一來我們得出以下結論:
1、在iOS開辟中應用strong、weak取代之前的retain、assign(根本類型應用assign);
2、假如一個屬性應用IBOutlet潤飾(也就是此屬性時strongboard中組件)那末應用weak;
3、假如一個屬性不是storyboard組件(普通純代碼編寫界面時),應用strong;
6、UIScrollView實戰
後面引見了iOS中UIKit的一些簡略常識,這裡我們一路應用後面的常識做一個例子--圖片無窮輪回轉動。在這個例子中我們須要處理以下兩個成績:
若何無窮輪回?
我們曉得在UIScrollView中假如放置其他控件後,只需設置contentSize以後這些圖片便可以轉動。假如要讓圖片無窮輪回那末只要兩種方法,一種是無窮輪回疊加圖片,另外一種就是假如最初一張圖片閱讀完立刻顯示第一張圖片。很顯著第一種辦法是不實際的,我們斟酌應用第二種方法。其實應用第二種方法完成道理比擬簡略,只需在圖片前後各放一張圖片便可(此時共有n+2個圖片在UIScrollView中)。例如我們有5張圖片,只需應用7個UIImageView順次寄存:圖片5,圖片1,圖片2,圖片3,圖片4,圖片5,圖片1。當從圖片1轉動到圖片5時因為最初一張是圖片1就給用戶一種無窮輪回的感到,當這張圖完整顯示後我們敏捷將UIScrollView的contentOffset設置到第二個UIImageView,也就是圖片1,接著用戶可以持續向後轉動。固然向前轉動道理完整一樣,當轉動到第一張圖片(圖片5)就敏捷設置UIScrollView的contentOffset顯示第6張圖(圖片5)。為了便利解釋請看上面的表示圖(留意表示圖因為寬度無限只描寫了3張圖片顯示的情形):
若何優化機能?
無窮輪回完成了,然則我們曉得假如圖片過量這些圖片必將全體加載到內存,這是我們不肯意看到的,此時我們須要優化下面的計劃。其實從下面的計劃我們也能夠看出眉目,我們完整沒需要創立n+2個UIImageView,其實3個曾經足夠(現實上也能夠用兩個完成,年夜家無妨本身思慮一下),只需一向堅持顯示中央的UIImageView,轉動時靜態更改三個UIImageView的圖片便可。例如三個UIImageView默許放圖片5、圖片1、圖片2,以後顯示中央的UIImageView,也就是圖片1,。假如向後轉動那末就會顯示圖片2,當圖片2顯示完全後敏捷從新設置三個UIImageView的內容為圖片1、圖片2、圖片3,然後經由過程contentOffset設置顯示中央的UIImageView,也就是圖片2。持續向後看到圖片3,當圖片3轉動完成敏捷從新設置3個UIImageView的內容為圖片2、圖片3、圖片4,然後設置contentOffset顯示中央的UIImageView,也就是圖片3。固然,向前轉動道理完整一樣,如斯就給用戶一種輪回錯覺,並且不占用過量內存。
上面給出詳細的完成,在這個法式中除UIscrollView我們還可以看到UIPageControl的應用,完成其實不龐雜。起首我們須要將圖片信息存儲到plist文件中(往後便利擴大),而且設置plist的key表現圖片的稱號,value代表對應的圖片描寫,這個描寫我們須要展現在界面上方。詳細內容以下:
imageInfo.plist
<?XmlRss/ target=_blank class=infotextkey>Xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>0.jpg</key> <string>iphone 5s</string> <key>1.jpg</key> <string>iphone 5c</string> <key>2.jpg</key> <string>ipad min with retain</string> <key>3.jpg</key> <string>ipad air</string> <key>4.jpg</key> <string>ipod</string> <key>5.jpg</key> <string>ipod touch</string> <key>6.jpg</key> <string>mac book pro</string> <key>7.jpg</key> <string>mac book air</string> <key>8.jpg</key> <string>imac</string> </dict> </plist>
在法式中我們須要讀取plist文件並加載對應的圖片,這裡我們將圖片按次序順次定名:0.jpg、1.jpg…8.jpg。我們的法式重要集中於自界說的KCMainViewController.m中,在這裡我們聲明1個UIScrollView和3個UIImageView用於顯示圖片,同時聲明一個UILable顯示圖片描寫信息,聲明一個UIPageControl來顯示以後圖片頁數,詳細代碼以下:
// // KCMainViewController.m // ImageViewer // // Created by Kenshin Cui on 14-2-23. // Copyright (c) 2014年 Kenshin Cui. All rights reserved. // #import "KCMainViewController.h" #define SCREEN_WIDTH 320 #define SCREEN_HEIGHT 568 #define IMAGEVIEW_COUNT 3 @interface KCMainViewController ()<UIScrollViewDelegate>{ UIScrollView *_scrollView; UIImageView *_leftImageView; UIImageView *_centerImageView; UIImageView *_rightImageView; UIPageControl *_pageControl; UILabel *_label; NSMutableDictionary *_imageData;//圖片數據 int _currentImageIndex;//以後圖片索引 int _imageCount;//圖片總數 } @end @implementation KCMainViewController - (void)viewDidLoad { [super viewDidLoad]; //加載數據 [self loadImageData]; //添加轉動控件 [self addScrollView]; //添加圖片控件 [self addImageViews]; //添加分頁控件 [self addPageControl]; //添加圖片信息描寫控件 [self addLabel]; //加載默許圖片 [self setDefaultImage]; } #pragma mark 加載圖片數據 -(void)loadImageData{ //讀取法式包途徑中的資本文件 NSString *path=[[NSBundle mainBundle] pathForResource:@"imageInfo" ofType:@"plist"]; _imageData=[NSMutableDictionary dictionaryWithContentsOfFile:path]; _imageCount=(int)_imageData.count; } #pragma mark 添加控件 -(void)addScrollView{ _scrollView=[[UIScrollView alloc]initWithFrame:[UIScreen mainScreen].bounds]; [self.view addSubview:_scrollView]; //設置署理 _scrollView.delegate=self; //設置contentSize _scrollView.contentSize=CGSizeMake(IMAGEVIEW_COUNT*SCREEN_WIDTH, SCREEN_HEIGHT) ; //設置以後顯示的地位為中央圖片 [_scrollView setContentOffset:CGPointMake(SCREEN_WIDTH, 0) animated:NO]; //設置分頁 _scrollView.pagingEnabled=YES; //去失落轉動條 _scrollView.showsHorizontalScrollIndicator=NO; } #pragma mark 添加圖片三個控件 -(void)addImageViews{ _leftImageView=[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)]; _leftImageView.contentMode=UIViewContentModeScaleaspectFit; [_scrollView addSubview:_leftImageView]; _centerImageView=[[UIImageView alloc]initWithFrame:CGRectMake(SCREEN_WIDTH, 0, SCREEN_WIDTH, SCREEN_HEIGHT)]; _centerImageView.contentMode=UIViewContentModeScaleaspectFit; [_scrollView addSubview:_centerImageView]; _rightImageView=[[UIImageView alloc]initWithFrame:CGRectMake(2*SCREEN_WIDTH, 0, SCREEN_WIDTH, SCREEN_HEIGHT)]; _rightImageView.contentMode=UIViewContentModeScaleAspectFit; [_scrollView addSubview:_rightImageView]; } #pragma mark 設置默許顯示圖片 -(void)setDefaultImage{ //加載默許圖片 _leftImageView.image=[UIImage imageNamed:[NSString stringWithFormat:@"%i.jpg",_imageCount-1]]; _centerImageView.image=[UIImage imageNamed:[NSString stringWithFormat:@"%i.jpg",0]]; _rightImageView.image=[UIImage imageNamed:[NSString stringWithFormat:@"%i.jpg",1]]; _currentImageIndex=0; //設置以後頁 _pageControl.currentPage=_currentImageIndex; NSString *imageName=[NSString stringWithFormat:@"%i.jpg",_currentImageIndex]; _label.text=_imageData[imageName]; } #pragma mark 添加分頁控件 -(void)addPageControl{ _pageControl=[[UIPageControl alloc]init]; //留意此辦法可以依據頁數前往UIPageControl適合的年夜小 CGSize size= [_pageControl sizeForNumberOfPages:_imageCount]; _pageControl.bounds=CGRectMake(0, 0, size.width, size.height); _pageControl.center=CGPointMake(SCREEN_WIDTH/2, SCREEN_HEIGHT-100); //設置色彩 _pageControl.pageIndicatorTintColor=[UIColor colorWithRed:193/255.0 green:219/255.0 blue:249/255.0 alpha:1]; //設置以後頁色彩 _pageControl.currentPageIndicatorTintColor=[UIColor colorWithRed:0 green:150/255.0 blue:1 alpha:1]; //設置總頁數 _pageControl.numberOfPages=_imageCount; [self.view addSubview:_pageControl]; } #pragma mark 添加信息描寫控件 -(void)addLabel{ _label=[[UILabel alloc]initWithFrame:CGRectMake(0, 10, SCREEN_WIDTH,30)]; _label.textAlignment=NSTextAlignmentCenter; _label.textColor=[UIColor colorWithRed:0 green:150/255.0 blue:1 alpha:1]; [self.view addSubview:_label]; } #pragma mark 轉動停滯事宜 -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{ //從新加載圖片 [self reloadImage]; //挪動到中央 [_scrollView setContentOffset:CGPointMake(SCREEN_WIDTH, 0) animated:NO]; //設置分頁 _pageControl.currentPage=_currentImageIndex; //設置描寫 NSString *imageName=[NSString stringWithFormat:@"%i.jpg",_currentImageIndex]; _label.text=_imageData[imageName]; } #pragma mark 從新加載圖片 -(void)reloadImage{ int leftImageIndex,rightImageIndex; CGPoint offset=[_scrollView contentOffset]; if (offset.x>SCREEN_WIDTH) { //向右滑動 _currentImageIndex=(_currentImageIndex+1)%_imageCount; }else if(offset.x<SCREEN_WIDTH){ //向左滑動 _currentImageIndex=(_currentImageIndex+_imageCount-1)%_imageCount; } //UIImageView *centerImageView=(UIImageView *)[_scrollView viewWithtag:2]; _centerImageView.image=[UIImage imageNamed:[NSString stringWithFormat:@"%i.jpg",_currentImageIndex]]; //從新設置閣下圖片 leftImageIndex=(_currentImageIndex+_imageCount-1)%_imageCount; rightImageIndex=(_currentImageIndex+1)%_imageCount; _leftImageView.image=[UIImage imageNamed:[NSString stringWithFormat:@"%i.jpg",leftImageIndex]]; _rightImageView.image=[UIImage imageNamed:[NSString stringWithFormat:@"%i.jpg",rightImageIndex]]; } @end
在下面的代碼中須要提示年夜家的是必定要謹嚴在轉動時停止相干操作,後面我們說過轉動事宜會輪回履行非常消費機能,是以假如能不在個中操作的話盡量不要在這個辦法中停止相干操作,例如在下面的代碼中我們的焦點邏輯重要集中在轉動停滯事宜中,這個事宜在一次轉動操作中只須要履行一次。
運轉後果:
【iOS開辟中應用UIScrollView完成無窮輪回的圖片閱讀器】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!