標籤:
1:iOS視圖控制對象生命週期
init-初始化程式
viewDidLoad-載入視圖
viewWillAppear-UIViewController對象的視圖即將加入視窗時調用;
viewDidApper-UIViewController對象的視圖已經加入到視窗時調用;
viewWillDisappear-UIViewController對象的視圖即將消失、被覆蓋或是隱藏時調用;
viewDidDisappear-UIViewController對象的視圖已經消失、被覆蓋或是隱藏時調用;
執行時間順序
15:51:44.811inHyron[483:b903] init
15:51:54.081inHyron[483:b903] viewDidLoad
15:51:54.082inHyron[483:b903] viewVillAppear
15:51:54.084 inHyron[483:b903] viewDidAppear
很明顯,先執行init、然後執行viewDidLoad,然後是viewWillAppear最後是viewDidAppear,這樣視圖就建立好了,當視圖消失或者被覆蓋的時候:
15:54:14.557inHyron[483:b903] viewWillDisappear
15:54:14.558inHyron[483:b903] viewDidDisappear
這樣一來視圖就消失了
2:初始化一個有預設值執行個體類
userManager.h檔案內容:#import <Foundation/Foundation.h>@interface userManager : NSObject@property(nonatomic,copy)NSString *userName;@property(nonatomic,copy)NSString *passWord;@property (assign, nonatomic) NSInteger type;+(userManager *)userManagerWithType:(NSInteger)type;-(NSString *)toGetParams;-(void)configWithObj:(userManager *)userManagerInfo;@enduserManager.m檔案內容:#import "userManager.h"@implementation userManager- (instancetype)init{ self = [super init]; if (self) { [email protected]"root"; [email protected]"123456"; _type = 0; } return self;}+(userManager *)userManagerWithType:(NSInteger)type{ userManager *myManager=[[userManager alloc]init]; myManager.type=type; return myManager;}-(void)configWithObj:(userManager *)userManagerInfo{ self.userName=userManagerInfo.userName; self.passWord=userManagerInfo.passWord; self.type=userManagerInfo.type;}-(NSString *)toGetParams{ return [NSString stringWithFormat:@"目前使用者:%@ 密碼:%@",self.userName,self.passWord];}@end調用代碼:userManager *myManager=[userManager userManagerWithType:4];NSLog(@"使用者資訊:%@",myManager.toGetParams);
3:NSHTTPCookieStorage(擷取和刪除cookie)
取出cookieNSArray *cookiesArray = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];NSDictionary *cookieDict = [NSHTTPCookie requestHeaderFieldsWithCookies:cookiesArray];NSString *cookie = [cookieDict objectForKey:@"Cookie"];//設定http的header的cookie[urlRequest setValue:cookie forHTTPHeaderField:@"Cookie”];刪除cookieNSArray *cookiesArray = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];for (NSHTTPCookie *cookie in cookiesArray) { [[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie];}
4:iOS關於在UITableView中,實現多個cell中不同的倒計時實現
//所有剩餘時間數組NSMutableArray *totalLastTime;在網路請求到的所有資料中,根據需要將其中要進行倒計時顯示的資料中的剩餘時間單獨儲存出來,如果這裡是所有的資料都需要倒計時,則只需要儲存時間即可,如果是有部分資料才需要倒計時,則可以儲存字典,兩個索引值對分別為其在UITableView的indexPath和剩餘時間:num預設從0開始NSDictionary *dic = @{@"indexPath":[NSStrin stringWithFormat:@"%i",num],@"lastTime": order.payLastTime}; [totalLastTime addObject:dic];開啟定時器方法:- (void)startTimer{ timer = [NSTimer scheduledTimerWithTimeInterval:1 target:selfselector:@selector(refreshLessTime) userInfo:@"" repeats:YES]; 如果不添加下面這條語句,在UITableView拖動的時候,會阻塞定時器的調用 [[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode]; }主要的定時器中的方法,在該方法中,遍曆totalLastTime,取出其中儲存的lasttime和indexpath,time用來顯示,在顯示完後自減,indexpath代表對應顯示的位置,在一次迴圈後,將新的time和沒有改變的indexpath從新替換totalLastTime 中對應位置的元素,以此保證每一秒執行時,顯示time都是最新的。- (void)refreshLessTime{ NSUInteger time; for (int i = 0; i < totalLastTime.count; i++) { time = [[[totalLastTime objectAtIndex:i] objectForKey:@"lastTime"]integerValue]; NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:[[[totalLastTime objectAtIndex:i] objectForKey:@"indexPath"] integerValue]]; WLServiceOrderTableViewCell *cell = (WLServiceOrderTableViewCell *)[_tableView cellForRowAtIndexPath:indexPath]; cell.remainingTimeLabel.text = [NSString stringWithFormat:@"剩餘支付時間:%@",[self lessSecondToDay:--time]]; NSDictionary *dic = @{@"indexPath": [NSStringstringWithFormat:@"%i",indexPath.section],@"lastTime": [NSStringstringWithFormat:@"%i",time]}; [totalLastTime replaceObjectAtIndex:i withObject:dic]; }}- (NSString *)lessSecondToDay:(NSUInteger)seconds{ NSUInteger day = (NSUInteger)seconds/(24*3600); NSUInteger hour = (NSUInteger)(seconds%(24*3600))/3600; NSUInteger min = (NSUInteger)(seconds%(3600))/60; NSUInteger second = (NSUInteger)(seconds%60); NSString *time = [NSString stringWithFormat:@"%lu日%lu小時%lu分鐘%lu秒",(unsigned long)day,(unsigned long)hour,(unsigned long)min,(unsigned long)second]; return time; }
項目中運用中的代碼:- (void)startTimer{ self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(refreshLessTime) userInfo:@"" repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:UITrackingRunLoopMode]; }- (void)refreshLessTime{ NSInteger time; for (int i = 0; i < self.totalLastTime.count; i++) { time = [[[self.totalLastTime objectAtIndex:i] objectForKey:@"lastTime"]integerValue]; NSIndexPath *indexPath = [NSIndexPath indexPathForItem:[[[self.totalLastTime objectAtIndex:i] objectForKey:@"indexPath"] integerValue] inSection:0]; BDFindActivityCell *cell = (BDFindActivityCell *)[_tableView cellForRowAtIndexPath:indexPath]; if (time==0) { [cell setCellData:@"活動中"]; [email protected]"正在搶單中"; cell.clockImageView.hidden=YES;// [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; --time; } else if(time>0) { cell.myLabel.text = [NSString stringWithFormat:@"%@",[self lessSecondToDay:--time]]; } NSDictionary *dic = @{@"indexPath": [NSString stringWithFormat:@"%ld",indexPath.row],@"lastTime": [NSString stringWithFormat:@"%li",time]}; [self.totalLastTime replaceObjectAtIndex:i withObject:dic]; }}- (NSString *)lessSecondToDay:(NSUInteger)seconds{ NSUInteger hour = (NSUInteger)(seconds%(24*3600))/3600; NSUInteger min = (NSUInteger)(seconds%(3600))/60; NSUInteger second = (NSUInteger)(seconds%60); NSString *time = [NSString stringWithFormat:@"去搶單 %02lu:%02lu:%02lu",(unsigned long)hour,(unsigned long)min,(unsigned long)second]; return time; }
5:如何運用Method Swizzling動態插入一些操作
假設工程中有很多ViewController,但有個操作每個頁面都有,以前都是每個頁面都去編寫相同的代碼,其實用Method Swizzling就可以解決這個問題,比如RDVTabBarController這個只在四個首頁才顯示出來,其它頁面都進行隱藏;
a:建立一個擴充類:UIViewController+Swizzle
.h檔案的內容:
#import <UIKit/UIKit.h>#import <objc/runtime.h>#import "RDVTabBarController.h"@interface UIViewController (Swizzle)@end
.m檔案的內容:
#import "UIViewController+Swizzle.h"@implementation UIViewController (Swizzle)+ (void)load{ SEL origSel = @selector(viewDidAppear:); SEL swizSel = @selector(swiz_viewDidAppear:); [UIViewController swizzleMethods:[self class] originalSelector:origSel swizzledSelector:swizSel]; SEL [email protected](viewWillAppear:); SEL [email protected](swiz_viewWillAppear:); [UIViewController swizzleMethods:[self class] originalSelector:vcWillAppearSel swizzledSelector:swizWillAppearSel];}+ (void)swizzleMethods:(Class)class originalSelector:(SEL)origSel swizzledSelector:(SEL)swizSel{ Method origMethod = class_getInstanceMethod(class, origSel); Method swizMethod = class_getInstanceMethod(class, swizSel); //class_addMethod will fail if original method already exists BOOL didAddMethod = class_addMethod(class, origSel, method_getImplementation(swizMethod), method_getTypeEncoding(swizMethod)); if (didAddMethod) { class_replaceMethod(class, swizSel, method_getImplementation(origMethod), method_getTypeEncoding(origMethod)); } else { //origMethod and swizMethod already exist method_exchangeImplementations(origMethod, swizMethod); }}- (void)swiz_viewDidAppear:(BOOL)animated{ //可以對控制器名稱做過濾 達到過濾哪些是不操作 NSString *curClassName=NSStringFromClass([self class]); if (curClassName.length>0&&([curClassName isEqualToString:@"BDCustomerListViewController"]||[curClassName isEqualToString:@"BDOrdersViewController"]||[curClassName isEqualToString:@"BDDiscoverViewController"]||[curClassName isEqualToString:@"BDMineInfoViewController"])) { [self.rdv_tabBarController setTabBarHidden:NO animated:YES]; } //需要注入的代碼寫在此處 [self swiz_viewDidAppear:animated];}-(void)swiz_viewWillAppear:(BOOL)animated{ if ([[self.navigationController childViewControllers] count] > 1) { [self.rdv_tabBarController setTabBarHidden:YES animated:YES]; } [self swiz_viewWillAppear:animated];}@end
說明:+ (void)load 方法是一個類方法,當某個類的代碼被讀到記憶體後,runtime會給每個類發送 + (void)load 訊息。因此 + (void)load 方法是一個調用時機相當早的方法,而且不管父類還是子類,其 + (void)load 方法都會被調用到,很適合用來插入swizzling方法
b:調用在main.m引入這個擴充類
#import <UIKit/UIKit.h>#import "AppDelegate.h"#import "UIViewController+Swizzle.h"int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } }
6:IOS關於UIImageView的展開問題
指定這4個寬度後 會形成黑色模組 直白點就是 這塊內容就是展開後中間那塊不斷填充的部分
UIImage* img=[UIImage imageNamed:@"2.png"];//原圖UIEdgeInsets edge=UIEdgeInsetsMake(0, 10, 0,10); //UIImageResizingModeStretch:展開模式,通過展開UIEdgeInsets指定的矩形地區來填充圖片 上下左右都會 //UIImageResizingModeTile:平鋪模式,通過重複顯示UIEdgeInsets指定的矩形地區來填充圖img= [img resizableImageWithCapInsets:edge resizingMode:UIImageResizingModeStretch];self.imageView.image=img;項目中的運用: self.myImageView=[[UIImageView alloc]initWithFrame:CGRectMake(0, 100, 184, 25)]; UIImage *curImage=[UIImage imageNamed:@"form_no_selected_icon"]; UIEdgeInsets edge=UIEdgeInsetsMake(0, 40, 0,25); curImage= [curImage resizableImageWithCapInsets:edge resizingMode:UIImageResizingModeStretch]; self.myImageView.image=curImage; [self.view addSubview:self.myImageView];
如果只是左右展開就用UIImageResizingModeStretch,關於edge的值左右自個根據實際的大小進行確定,把以這塊進行展開,特別要注意2X跟3X的圖片;
7:AppDelegate各個事件及一些相應的通知運用
a 活動-》不活動 使用applicationWillResignActive:/UIApplicationWillResignActiveNotification來“暫停”應用程式的顯示。確保工作中不需要及時的使用者輸入,因為應用程式在一段時間內不會獲得任何使用者輸入。
b 不活動-》後台 使用applicationDidEnterBackground:/UIApplicationDidEnterBackgroundNotification釋放在應用程式處於後台狀態時不需要保留的任何資源(比如緩衝的映像或者其他可以輕鬆載入的資料),或者無法儲存在背景任何資源(比如網路連接)。在這裡避免過度的使用記憶體使用量將應用程式的最終的暫停快照更小,從而減小了應用程式從RAM整個清楚的風險。還可以通過此機會儲存任何必要的應用資料,這些資料將有助於使用者在下一次重新啟動時候找到上次離開時的進度。
c 後台-》不活動 使用applicationDidBecomeActive:/UIApplicationDidBecomeActiveNotification恢複從後台狀態切換到不活動狀態時候所執行的任何操作。例如,在這裡可以重建立立持久網路連接。
d不活動-》活動 使用applicationDidBecomeActive:/UIApplicationDidBecomeActiveNotification恢複從不活動到活動狀態時候所做的任何操作。這個方法和通知在應用程式全新啟動時使用,所以在這裡執行的任何操作也必須在該上下文有效。 注意:在此過度過程中,系統不會提供大量時間來儲存這裡的更改,僅提供5秒的時間。如果超過5秒,應用程式將立刻從記憶體中清楚並進入未運行狀態!
以UIApplicationDidBecomeActiveNotification通知為例子,在頁面上建立一個通知,並實現其代碼:
@interface FirstViewController ()@end@implementation FirstViewController- (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor=[UIColor redColor]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didBecomeActiveNotification:) name:UIApplicationDidBecomeActiveNotification object:nil];}- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}- (void)didBecomeActiveNotification:(NSNotification *)note{ NSLog(@"哈哈我進入了");}@end
上面執行的時間為程式運行在這一頁,然後退到後台,又進入APP到這個頁面進行喚醒,就會執行上面那個didBecomeActiveNotification方法;如果沒在這個頁面,就算喚醒也是不會執行
8:Aspects運用它進行面向切面編程
Aspects外掛程式地址:https://github.com/steipete/Aspects
建立一個SwizzleManager類:
.h檔案內容:#import <Foundation/Foundation.h>#import "Aspects/Aspects.h"@interface SwizzleManager : NSObject+ (void)createAllHooks;@end.m檔案內容:#import "SwizzleManager.h"#import <UIKit/UIKit.h>@implementation SwizzleManager+ (void)createAllHooks{ [UIViewController aspect_hookSelector:@selector(viewDidLoad) withOptions:AspectPositionBefore usingBlock:^(id<AspectInfo> info){ //使用者統計代碼寫在此處 NSLog(@"[ASPECT] inject in class instance:%@", [info instance]); } error:NULL]; //other hooks ... goes here //...}@end然後在AppDelegate檔案:- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. //在程式啟動的第一時間內建立 [SwizzleManager createAllHooks]; return YES;}
不錯的文章:http://tech.glowing.com/cn/method-swizzling-aop/ 裡面的執行個體可以記錄每個頁面,及每個按鍵的事件
9:怎麼改變UITextfield placeholder的顏色和位置?
繼承UITextfield,重寫這個方法
- (void) drawPlaceholderInRect:(CGRect)rect { [[UIColor blueColor] setFill]; [self.placeholder drawInRect:rect withFont:self.font lineBreakMode:UILineBreakModeTailTruncation alignment:self.textAlignment];}
10:怎麼把tableview裡cell的小對勾的顏色改成別的顏色?
_mTableView.tintColor = [UIColor redColor];
iOS開發基礎知識--片段35