NSFileManager、NSURL、NSFileHandle、NSData、NSXMLParser、NSUserDefaults、NSKeyedArchiver、NSKeyedUnarchiver、CoreData、NSFetchRequest、NSEntityDescription、NSPredicate、 NSSortDescriptor、UIImagePickerController、AVAudioPlayer、MPMoviePlayerController、NSThread、NSBlockOperation、NSInvocationOperation、NSOperationQueue、NSLock、NSCondicion、AsyncSocket(FTP)、AsyncUdpSocket(UTP)、NSJSONSerialization、NSMutableURLRequest、NSURLConnection、UIWebView、AFNetworking(HTTP)、MKAnnotationView 、MKMapView、UILocalNotification、CMMotionManagerhtml
橫屏: 1.故事版中,右側檢查器Oriemtation—>Landscape 2.主項目中,portrait的勾去掉 全屏:(去掉屏幕上邊的下拉框) 1.Supporting Files—>BaylAnimation—>info.plist—>右擊點擊空白處—>AddRow—>選倒數第一個 2.項目中勾上Hide duing application launch 例: 1.要求: 移動圖片,放到下邊的view視圖中,上邊的圖片保持不消失 2. 思想: 0.經過touch來實現 1.遍歷出數組中的圖片,判斷點擊的是哪一張圖片,而後將點擊的圖片保存在添加屬性的UIImageView中。 2.根據保存在UIImageView中的點擊的圖片,將圖片添加到下邊的view,意思是隻有點擊了此圖片才進行判斷添加到哪一個視圖,首先先判斷添加到下邊的哪一個view,判斷根據點擊的點是在哪一個視圖的範圍內,在變換點擊圖片的父視圖,變換成下面的view,而後將圖片添加進去,注意,若是點擊的區域不在兩個view上,就刪除此圖片。 3.根據下邊view的子視圖肯定添加到視圖的圖片數量,賦給label顯示 3.新知識點: 1.查看子視圖個數 self.leftCountLabel.text = [NSString stringWithFormat:@"%d",self.leftView.subviews.count]; 2.判斷點擊到的是哪一張圖片 根據點擊的點是不是矩形中包含的點肯定 CGRectContainsPoint(self.leftView.frame, p) 3.當一個控件的父視圖發生改變的時候 而且兩個父視圖不重疊 須要轉變相對座標 CGPoint oldCenter = self.dragIV.center; CGPoint newCenter = [self.view convertPoint:oldCenter toView:self.rightView]; self.dragIV.center=newCenter; 4.從主視圖移除此圖片 [self.dragIV removeFromSuperview]; 完整程序: #import "ViewController.h"
@interface ViewController () @property (nonatomic, strong)UIImageView *dragIV; @property (weak, nonatomic) IBOutlet UILabel *rightCountLabel; @property (weak, nonatomic) IBOutlet UILabel *leftCountLabel; @property (weak, nonatomic) IBOutlet UIView *rightView; @property (weak, nonatomic) IBOutlet UIView *leftView; @property (strong, nonatomic) IBOutletCollection(UIImageView) NSArray *imageViews;//三張圖片
@end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; } -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch *t = [touches anyObject]; CGPoint p = [t locationInView:self.view]; for (UIImageView *iv in self.imageViews) { //判斷點擊到的是哪一張圖片 矩形中包含的點
if (CGRectContainsPoint(iv.frame, p)) { self.dragIV = [[UIImageView alloc]initWithFrame:iv.frame]; self.dragIV.image = iv.image; [self.view addSubview:self.dragIV]; } } } -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch *t = [touches anyObject]; CGPoint p = [t locationInView:self.view]; self.dragIV.center = p; } -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch *t = [touches anyObject]; CGPoint p = [t locationInView:self.view]; if (self.dragIV) { if (CGRectContainsPoint(self.leftView.frame, p)) { CGPoint oldCenter = self.dragIV.center; CGPoint newCenter = [self.view convertPoint:oldCenter toView:self.leftView]; [self.leftView addSubview:self.dragIV]; self.dragIV.center = newCenter; //根據leftView的子視圖來肯定個數
self.leftCountLabel.text = [NSString stringWithFormat:@"%d",self.leftView.subviews.count]; }else if (CGRectContainsPoint(self.rightView.frame, p)){ // 當一個控件的父視圖發生改變的時候 而且兩個父視圖不重疊 須要轉變相對座標
CGPoint oldCenter = self.dragIV.center; CGPoint newCenter = [self.view convertPoint:oldCenter toView:self.rightView]; [self.rightView addSubview:self.dragIV]; self.dragIV.center = newCenter; self.rightCountLabel.text = [NSString stringWithFormat:@"%d",self.rightView.subviews.count]; }else{ [self.dragIV removeFromSuperview]; } self.dragIV = nil;//當放在下邊的視圖中就不能在實行移動
} } //意外中斷操做時調用
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{ } @end  2.植物大戰殭屍 殭屍類: 1.要求:從屏幕右側的邊界隨機的走出殭屍 2.思想: a.不要都堆到控制器,要建立新的單獨的類,封裝性,若是要實現不一樣的圖片移動,要用繼承,另外若是有重複出現的程序,還要用多態。總之這三點多用 b.建立UIImageView類,從總的圖中裁剪出單個圖片,記錄到公開屬性UIImageView中,利用NSTimer控制建立屢次裁剪的圖片,便可以實現動畫效果,改變其中心點便可以實現移動。 c.將保存在屬性中的圖片在賦給當前類,當前類在控制器中只須要實例化便可建立多個殭屍對象,要想實現重複建立,使用timer便可 d.實現從屏幕右側不一樣高度走出,只需隨機建立實例的frame的y點的值 e.若繼續建立多個類,繼承自建立的殭屍類,只要在子類修改其圖片以及移動的中心點就能夠實現不一樣形狀的殭屍對象 f.注意判斷,當殭屍走出屏幕時,須要將殭屍對象銷燬,即讓timer中止,並從當前視圖移除 3.新知識點 1).從總的圖中分別裁剪出子圖(注意類型的轉換) UIImage *zombImage = [UIImage imageNamed:@"zomb_0.png"]; float w = zombImage.size.width/8; CGImageRef subImage = CGImageCreateWithImageInRect(zombImage.CGImage, CGRectMake(self.count++%8*w, 0, w, zombImage.size.height)); self.image = [UIImage imageWithCGImage:subImage]; // 把CGImageRef釋放掉
CGImageRelease(subImage); 2)把timer中止 才能讓對象從內存中釋放掉 if (self.frame.origin.x<=-self.bounds.size.width) { //把timer中止 才能讓對象從內存中釋放掉
[timer invalidate]; [self removeFromSuperview];//從屏幕視圖中移除
} 完整程序: Zomb.h #import <UIKit/UIKit.h>
@interface Zomb : UIImageView @property (nonatomic)int count; @property (nonatomic, strong)UIImage *zombImage; @property (nonatomic)float speed; @end Zomb.m #import "Zomb.h"
@implementation Zomb - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // 當使用timer的時候 timer會給target的值內存計數+1 當timer中止的時候
[NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(changeImage:) userInfo:nil repeats:YES]; } return self; } -(void)changeImage:(NSTimer *)timer{ float w = self.zombImage.size.width/8; CGImageRef subImage = CGImageCreateWithImageInRect(self.zombImage.CGImage, CGRectMake(self.count++%8*w, 0, w, self.zombImage.size.height)); self.image = [UIImage imageWithCGImage:subImage]; // 把CGImageRef釋放掉
CGImageRelease(subImage); self.center = CGPointMake(self.center.x-self.speed, self.center.y); if (self.frame.origin.x<=-self.bounds.size.width) { //把timer中止 才能讓對象從內存中釋放掉
[timer invalidate]; [self removeFromSuperview];//從屏幕視圖中移除
} } - (void)dealloc { NSLog(@"殭屍死掉了!"); } @end Zomb.h #import "Zomb.h"
@interface ZombA : Zomb @end Zomb.m #import "ZombA.h"
@implementation ZombA - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.zombImage = [UIImage imageNamed:@"zomb_0.png"]; self.speed = 1; } return self; } ViewController.h ViewController.m #import "ViewController.h"
#import "ZombA.h"
#import "ZombB.h"
#import "ZombC.h"
#import "ZombD.h"
@interface ViewController () @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [NSTimer scheduledTimerWithTimeInterval:.5 target:self selector:@selector(addZomb) userInfo:nil repeats:YES]; } -(void)addZomb{ int type = arc4random()%4; Zomb *z = nil; switch (type) { case 0: z = [[ZombA alloc]initWithFrame:CGRectMake(self.view.bounds.size.width, arc4random()%(int)(self.view.bounds.size.height-60), 40, 60)]; break; case 1: z = [[ZombB alloc]initWithFrame:CGRectMake(self.view.bounds.size.width, arc4random()%(int)(self.view.bounds.size.height-60), 40, 60)]; break; case 2: z = [[ZombC alloc]initWithFrame:CGRectMake(self.view.bounds.size.width, arc4random()%(int)(self.view.bounds.size.height-60), 40, 60)]; break; case 3: z = [[ZombD alloc]initWithFrame:CGRectMake(self.view.bounds.size.width, arc4random()%(int)(self.view.bounds.size.height-60), 40, 60)]; break; } [self.view addSubview:z]; } @end
2.植物類 1.要求:實現將圖片添加到view中,即種植植物到地裏 2.思想: a.建立故事板,進行佈局,四個imageView進行存放植物,多個view進行存放移動的imageView,分別將其放到數組中 b.將四個imageView從數組遍歷出來,將總的圖剪裁出的子圖賦到遍歷出來的imageView中,將遍歷出來的圖在保存到新建立的UIImageView中,剪裁只要根據x的左邊便可肯定是哪張圖。 c.想實現每張圖片的動畫效果,繼續利用殭屍類的效果便可實現,建立植物類,而後四張圖片的效果分別繼承植物類,經過timer裁剪總的圖片實現移動效果。 d.實現上邊的四張圖片移動到下邊的view中,利用touch,經過點擊的時候遍歷判斷點擊的是哪張圖,點擊的圖片聲明成屬性,遍歷出來再將點擊的圖片添加到view父視圖 e.touch結束的時候,遍歷數組view即坑,判斷有沒有在坑裏鬆手 而且坑裏什麼都沒有才能夠放,而且判斷若是拖拽植物的父視圖仍是self.view的話 說明沒有扔到任何坑裏面 就應該刪除掉 if ([self.dragPlant.superview isEqual:self.view]) { [self.dragPlant removeFromSuperview]; } f.移到坑裏再也不移動,需設置self.dragPlant = nil; ViewController.h ViewController.m #import "ViewController.h"
#import "SunFlower.h"
#import "Pea.h"
#import "IcePea.h"
#import "Nut.h"
@interface ViewController () @property (weak, nonatomic) IBOutlet UILabel *sunCountLabel; @property (strong, nonatomic) IBOutletCollection(UIView) NSArray *boxes; @property (strong, nonatomic) IBOutletCollection(UIImageView) NSArray *plantIVs; @property (nonatomic, strong)Plant *dragPlant; @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [self initUI]; } -(void)initUI{ UIImage *plantsImage = [UIImage imageNamed:@"seedpackets.png"]; float w = plantsImage.size.width/18; for (int i=0; i<self.plantIVs.count; i++) { UIImageView *plantIV = self.plantIVs[i]; float x = 0; switch (i) { case 1: x = 2*w; break; case 2: x = 3*w; break; case 3: x = 5*w; break; } CGImageRef subImage = CGImageCreateWithImageInRect(plantsImage.CGImage, CGRectMake(x, 0, w, plantsImage.size.height)); plantIV.image = [UIImage imageWithCGImage:subImage]; CGImageRelease(subImage); } } -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch *t = [touches anyObject]; CGPoint p = [t locationInView:self.view]; for (int i=0;i<self.plantIVs.count;i++) { UIImageView *plantIV = self.plantIVs[i]; if (CGRectContainsPoint(plantIV.frame, p)) { switch (i) { case 0: self.dragPlant = [[SunFlower alloc]initWithFrame:plantIV.frame]; break; case 1: self.dragPlant = [[Pea alloc]initWithFrame:plantIV.frame]; break; case 2: self.dragPlant = [[IcePea alloc]initWithFrame:plantIV.frame]; break; case 3: self.dragPlant = [[Nut alloc]initWithFrame:plantIV.frame]; break; } [self.view addSubview:self.dragPlant]; } } } -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch *t = [touches anyObject]; CGPoint p = [t locationInView:self.view]; self.dragPlant.center = p; } -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch *t = [touches anyObject]; CGPoint p = [t locationInView:self.view]; if (self.dragPlant) { for (UIView *box in self.boxes) { //判斷有沒有在坑裏鬆手 而且坑裏什麼都沒有
if (CGRectContainsPoint(box.frame, p)&&box.subviews.count==0) { [box addSubview:self.dragPlant]; self.dragPlant.center = CGPointMake(box.bounds.size.width/2, box.bounds.size.height/2); } } //判斷若是拖拽植物的父視圖仍是self.view的話 說明沒有扔到任何坑裏面 就應該刪除掉
if ([self.dragPlant.superview isEqual:self.view]) { [self.dragPlant removeFromSuperview]; } self.dragPlant = nil; } } -(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{ [self.dragPlant removeFromSuperview]; }  3. 要求:實現點擊太陽花種植,太陽花增長錢數,當種植植物的時候,消耗太陽光,每種植物消耗的錢數都不一樣。當錢數不夠的時候就不能點擊。而且剛點擊過的植物不能短期呈透明狀態,不能在被點擊 知識點: 兩個類之間的傳值 方法一:代理 1.A類顯示,須要公開一個屬性或方法接收 2.將須要點擊的圖片設置爲代理 3.B類中,將其A類名稱在.h文件中公開建立屬性.delegate @property (nonatomic, weak)ViewController *delegate; 4.在B類中將值傳給.delegate屬性或方法便可 方法二:通知 1.在A類建立監聽通知 [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(sunDismissAction:) name:@"sunDismissAction" object:nil]; 2.實現監聽通知的方法,即創建接收消息的通知,記錄key值,與B類中的key值保持一致 -(void)sunDismissAction:(NSNotification *)noti{ int count = [[noti.userInfo objectForKey:@"sunCount"] intValue]; [self addSunCount:count]; } 3.B類中發送須要傳值的消息,值爲key值對應的value值 [[NSNotificationCenter defaultCenter]postNotificationName:@"sunDismissAction" object:nil userInfo:@{@"sunCount":@(25)}]; Plant.h Plant.m #import "Plant.h"
@implementation Plant - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [NSTimer scheduledTimerWithTimeInterval:.01 target:self selector:@selector(changeImage:) userInfo:nil repeats:YES]; } return self; } -(void)beginFier{ } -(void)changeImage:(NSTimer*)timer{ self.fps++; if (self.fps%10==0) { float w = self.plantImage.size.width/8; CGImageRef subImage = CGImageCreateWithImageInRect(self.plantImage.CGImage, CGRectMake(self.count++%8*w, 0, w, self.plantImage.size.height)); self.image = [UIImage imageWithCGImage:subImage]; CGImageRelease(subImage); } } SunFlower.h SunFlower.m #import "SunFlower.h"
@implementation SunFlower - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.plantImage = [UIImage imageNamed:@"plant_0.png"]; self.userInteractionEnabled = YES; self.costSunCount = 50; } return self; } -(void)beginFier{ [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(addSun) userInfo:nil repeats:YES]; } -(void)addSun{ UIButton *sunBtn = [[UIButton alloc]initWithFrame:CGRectMake(20, 20, 25, 25)]; [sunBtn setImage:[UIImage imageNamed:@"sun.png"] forState:UIControlStateNormal]; [sunBtn addTarget:self action:@selector(clickedSunAction:) forControlEvents:UIControlEventTouchUpInside]; [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(dismissSunAction:) userInfo:sunBtn repeats:NO]; [self addSubview:sunBtn]; } -(void)dismissSunAction:(NSTimer *)timer{ UIButton *sunBtn = timer.userInfo; [sunBtn removeFromSuperview]; } -(void)clickedSunAction:(UIButton *)sunBtn{ [sunBtn removeFromSuperview]; // 讓界面中的Label數量增長 // [self.delegate addSunCount:25];
[[NSNotificationCenter defaultCenter]postNotificationName:@"sunDismissAction" object:nil userInfo:@{@"sunCount":@(25)}]; } @end Pea.h #import "Plant.h"
@interface Pea : Plant @property (nonatomic, strong)NSMutableArray *bullets; @property (nonatomic, strong)UIImage *bulletImage; @end Pea.m #import "Pea.h"
@implementation Pea - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.bullets = [NSMutableArray array]; self.plantImage = [UIImage imageNamed:@"plant_2.png"]; self.bulletImage = [UIImage imageNamed:@"bullet_0.png"]; self.costSunCount = 100; } return self; } -(void)beginFier{ [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(addBullet) userInfo:nil repeats:YES]; } -(void)addBullet{ UIImageView *bulletIV = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 15, 15)]; bulletIV.center = CGPointMake(self.superview.center.x+20, self.superview.center.y-10); bulletIV.image = self.bulletImage; [self.delegate.view addSubview:bulletIV]; [self.bullets addObject:bulletIV]; } -(void)changeImage:(NSTimer *)timer{ [super changeImage:timer]; //移動子彈
for (UIImageView *bulletIV in self.bullets) { bulletIV.center = CGPointMake(bulletIV.center.x+2, bulletIV.center.y); if (bulletIV.frame.origin.x>=self.delegate.view.bounds.size.width) { [bulletIV removeFromSuperview]; [self.bullets removeObject:bulletIV]; break; } } } IcePea.h #import "Pea.h"
@interface IcePea : Pea @end IcePea.m #import "IcePea.h"
@implementation IcePea - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.plantImage = [UIImage imageNamed:@"plant_3.png"]; self.bulletImage = [UIImage imageNamed:@"bullet_1.png"]; self.costSunCount = 175; } return self; } Nut.h Nut.m #import "Nut.h"
@implementation Nut - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.plantImage = [UIImage imageNamed:@"plant_5.png"]; self.costSunCount = 125; } return self; } ViewController.h #import <UIKit/UIKit.h>
@interface ViewController : UIViewController -(void)addSunCount:(int)count; @end ViewController.m #import "ViewController.h"
#import "SunFlower.h"
#import "Pea.h"
#import "IcePea.h"
#import "Nut.h"
#import "ZombA.h"
#import "ZombB.h"
#import "ZombC.h"
#import "ZombD.h"
@interface ViewController () @property (weak, nonatomic) IBOutlet UILabel *sunCountLabel; @property (strong, nonatomic) IBOutletCollection(UIView) NSArray *boxes; @property (strong, nonatomic) IBOutletCollection(UIImageView) NSArray *plantIVs; @property (nonatomic, strong)Plant *dragPlant; @property (nonatomic)int zombCount; @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [self initUI]; //監聽陽光被點擊的通知
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(sunDismissAction:) name:@"sunDismissAction" object:nil]; //添加殭屍
[NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(addZomb) userInfo:nil repeats:YES]; } -(void)addZomb{ self.zombCount++; // 0-29 0A // 30-59 1B // 60-89 2C // 90 3D
int type = self.zombCount/30; Zomb *zomb = nil; switch (type) { case 0: zomb = [[ZombA alloc]init]; break; case 1: zomb = [[ZombB alloc]init]; break; case 2: zomb = [[ZombC alloc]init]; break; default: zomb = [[ZombD alloc]init]; break; } int line = arc4random()%5+1; zomb.frame = CGRectMake(self.view.bounds.size.width, line * 50, 30, 50); [self.view addSubview:zomb]; } -(void)sunDismissAction:(NSNotification *)noti{ int count = [[noti.userInfo objectForKey:@"sunCount"] intValue]; [self addSunCount:count]; } -(void)initUI{ UIImage *plantsImage = [UIImage imageNamed:@"seedpackets.png"]; float w = plantsImage.size.width/18; for (int i=0; i<self.plantIVs.count; i++) { UIImageView *plantIV = self.plantIVs[i]; float x = 0; switch (i) { case 1: x = 2*w; break; case 2: x = 3*w; break; case 3: x = 5*w; break; } CGImageRef subImage = CGImageCreateWithImageInRect(plantsImage.CGImage, CGRectMake(x, 0, w, plantsImage.size.height)); plantIV.image = [UIImage imageWithCGImage:subImage]; CGImageRelease(subImage); } } -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch *t = [touches anyObject]; CGPoint p = [t locationInView:self.view]; int currentSunCount = self.sunCountLabel.text.intValue; for (int i=0;i<self.plantIVs.count;i++) { UIImageView *plantIV = self.plantIVs[i]; if (plantIV.alpha!=1) { return; } if (CGRectContainsPoint(plantIV.frame, p)) { switch (i) { case 0: if (currentSunCount<50) { return; } self.dragPlant = [[SunFlower alloc]initWithFrame:plantIV.frame]; break; case 1: if (currentSunCount<100) { return; } self.dragPlant = [[Pea alloc]initWithFrame:plantIV.frame]; break; case 2: if (currentSunCount<175) { return; } self.dragPlant = [[IcePea alloc]initWithFrame:plantIV.frame]; break; case 3: if (currentSunCount<125) { return; } self.dragPlant = [[Nut alloc]initWithFrame:plantIV.frame]; break; } self.dragPlant.tag = i; self.dragPlant.delegate = self; [self.view addSubview:self.dragPlant]; } } } -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch *t = [touches anyObject]; CGPoint p = [t locationInView:self.view]; self.dragPlant.center = p; } -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch *t = [touches anyObject]; CGPoint p = [t locationInView:self.view]; if (self.dragPlant) { for (UIView *box in self.boxes) { //判斷有沒有在坑裏鬆手 而且坑裏什麼都沒有
if (CGRectContainsPoint(box.frame, p)&&box.subviews.count==0) { [box addSubview:self.dragPlant]; self.dragPlant.center = CGPointMake(box.bounds.size.width/2, box.bounds.size.height/2); //讓植物開火兒
[self.dragPlant beginFier]; //花錢
[self addSunCount:-self.dragPlant.costSunCount]; //處理CD
UIImageView *plantIV = self.plantIVs[self.dragPlant.tag]; plantIV.alpha = .3; [UIView animateWithDuration:3 animations:^{ plantIV.alpha = .8; } completion:^(BOOL finished) { plantIV.alpha = 1; }]; } } //判斷若是拖拽植物的父視圖仍是self.view的話 說明沒有扔到任何坑裏面 就應該刪除掉
if ([self.dragPlant.superview isEqual:self.view]) { [self.dragPlant removeFromSuperview]; } self.dragPlant = nil; } } -(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{ [self.dragPlant removeFromSuperview]; } -(void)addSunCount:(int)count{ int currentCount = self.sunCountLabel.text.intValue; self.sunCountLabel.text = [NSString stringWithFormat:@"%d",currentCount+count]; } ============================================================================================================== 知識點 1、NSFileManager對整個文件進行操做 NSFileHandle 對文件的局部進行操做 1.NSFileManager簡單的操做 1.刪除文件 刪除文件的時候若是想提示出錯的地方error參數設置爲: NSFileManager *manager = [NSFileManager defaultManager]; NSError *err = nil; //刪除文件
[manager removeItemAtPath:@"/Users/tarena/Desktop/dic.xml" error:&err]; if (err) { NSLog(@"出錯:%@",[err localizedDescription]); } 2.複製文件 (注意toURL的時候起名字和後綴) //複製文件
[manager copyItemAtURL:[NSURL fileURLWithPath:@"/Users/tarena/Desktop/鄭彤.zip"] toURL:[NSURL fileURLWithPath:@"/Users/tarena/Desktop/未命名文件夾/zhengtong.zip"] error:nil]; 3.移動文件 (注意toPath的路徑要加上移動文件的名稱) [manager moveItemAtPath:@"/Users/tarena6/Desktop/nihao.rtf" toPath:@"/Users/tarena6/Desktop/未命名文件夾/nihao" error:nil]; 4.建立文件 (建立的時候起好名字和後綴) //建立文件
NSString *name = @"張三"; //字符串轉換爲數據源
NSData *data = [name dataUsingEncoding:NSUTF8StringEncoding]; [manager createFileAtPath:@"/Users/tarena/Desktop/未命名文件夾/a.txt" contents:data attributes:nil]; 5.建立文件夾 (第二個參數用來控制路徑中若是有 不存在的文件夾的時候是否 建立成功) [manager createDirectoryAtPath:@"/Users/tarena/Desktop/未命名文件夾/a" withIntermediateDirectories:NO attributes:nil error:nil]; a.判斷是否文件存在 //判斷是否文件存在
if ([manager fileExistsAtPath:@"/Users/tarena/Desktop/鄭彤1.zip"]) { NSLog(@"存在"); } else NSLog(@"不存在"); b.判斷是不是文件夾 // 判斷是不是文件夾
BOOL isDir = NO; if ([manager fileExistsAtPath:@"/Users/tarena/Desktop/test2.rtf" isDirectory:&isDir]&&isDir) { NSLog(@"文件存在 而且是文件夾"); }else{ NSLog(@"文件不存在 或不是文件夾"); } ***6.獲取文件夾下面全部的內容 NSString *direcotry = @"/Users/tarena6/Desktop/未命名文件夾"; NSArray *fileNames = [manager contentsOfDirectoryAtPath:direcotry error:nil]; for (NSString *fileName in fileNames) { NSLog(@"%@",fileName); //獲得完整路徑,文件名和路徑關聯到一塊兒 //使用下面的方法拼接字符串 會自動添加一個/ 才能夠執行下面的所有刪除
NSString *filePath = [direcotry stringByAppendingPathComponent:fileName]; [manager removeItemAtPath:filePath error:nil];//刪除
} } 2.NSFileManager 根據指定的路徑查找路徑下文件夾的內容 主要知識點: 1.hasSuffix:路徑最後的即後綴 如:if ([fileName hasSuffix:@"jpg"]) - (BOOL)hasPrefix:(NSString *)aString;前綴 - (BOOL)hasSuffix:(NSString *)aString; 後綴 #import "ViewController.h"
@interface ViewController () @property (weak, nonatomic) IBOutlet UITextView *myTV; @property (weak, nonatomic) IBOutlet UITextField *myTF; @property (nonatomic)int count; - (IBAction)clicked:(id)sender; @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; } -(void)findFileInDirecotryPath:(NSString *)path{ NSFileManager *manager = [NSFileManager defaultManager]; NSArray *fileNames = [manager contentsOfDirectoryAtPath:path error:nil]; for (NSString *fileName in fileNames) { NSString *filePath = [path stringByAppendingPathComponent:fileName]; if ([fileName hasSuffix:@"jpg"]) { self.myTV.text = [self.myTV.text stringByAppendingFormat:@"\n%@",filePath]; NSLog(@"%d",self.count++); //[manager removeItemAtPath:filePath error:nil];
} //判斷是不是文件夾 若是是繼續查找
BOOL isDir; if ([manager fileExistsAtPath:filePath isDirectory:&isDir]&&isDir) { [self findFileInDirecotryPath:filePath]; } } } - (IBAction)clicked:(id)sender { [self findFileInDirecotryPath:@"/Users/tarena6/Desktop/付"];//肯定路徑
} @end  例: 要求:1.以表格的形式根據路徑顯示文件夾的名稱, 2.若是是文件夾,右側顯示小三角的標誌,點擊小三角繼續顯示文件夾下的內容 3.右上角的編輯狀態,若是不是文件夾能夠進入編輯狀態,而且能夠刪除 4.是文件夾的前面就顯示文件夾的圖標,不是文件夾的若是是圖片,前面就顯示其包含的圖片 5.包含圖片的文件,點擊彈出新的界面,並平鋪到界面上 6.指定文本的,點擊進去彈出文本的內容 7.其餘的點擊彈出警告框 知識點: 1. - (NSString *)lastPathComponent; 路徑最後的一個文件夾名稱,包括後綴 2.iv.image = [UIImage imageWithContentsOfFile:filePath]; 根據路徑添加照片 3.顯示文本的視圖,屬性爲.text UITextView *tv = [[UITextView alloc]initWithFrame:vc.view.bounds]; 4.獲取路徑中的內容 1)tv.text=[[NSString alloc]initWithData:[NSData dataWithContentsOfFile:filePath] encoding:NSUTF8StringEncoding]; 2)tv.text = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; 5. 經過故事板建立 FileListTableViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"FileListTableViewController"]; FileListTableViewController.h #import <UIKit/UIKit.h>
@interface FileListTableViewController : UITableViewController @property (nonatomic,copy)NSString *direcotryPath; @end FileListTableViewController.m #import "FileListTableViewController.h"
@interface FileListTableViewController () @property (nonatomic, strong)NSMutableArray *filePaths; @end
@implementation FileListTableViewController - (void)viewDidLoad { [super viewDidLoad]; self.filePaths = [NSMutableArray array]; self.navigationItem.rightBarButtonItem = self.editButtonItem; NSFileManager *manager = [NSFileManager defaultManager]; //判斷出 若是是第一次 就顯示users下面的內容
if (!self.direcotryPath) { self.direcotryPath =@"/Users/"; } self.title = [self.direcotryPath lastPathComponent]; NSArray *fileNames = [manager contentsOfDirectoryAtPath:self.direcotryPath error:nil]; for (NSString *fileName in fileNames) { //把隱藏文件去掉
if ([fileName hasPrefix:@"."]) { continue; } NSString *filePath = [self.direcotryPath stringByAppendingPathComponent:fileName]; [self.filePaths addObject:filePath]; } } #pragma mark - Table view data source
//幾行
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.filePaths.count; } //每行的內容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; NSString *filePath = self.filePaths[indexPath.row]; cell.textLabel.text = [filePath lastPathComponent]; //判斷是不是文件夾
if ([self isDirecotryWithPath:filePath]) { cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; //給文件夾添加圖標
cell.imageView.image = [UIImage imageNamed:@"direcotry.png"]; }else { cell.accessoryType = UITableViewCellAccessoryNone; //是照片的就顯示照片圖標
if ([filePath hasSuffix:@"jpg"]||[filePath hasSuffix:@"png"]) { cell.imageView.image = [UIImage imageWithContentsOfFile:filePath]; } } return cell; } //點擊每一行顯示的效果
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ NSString *filePath = self.filePaths[indexPath.row]; if ([self isDirecotryWithPath:filePath]) { //若是是文件夾要跳轉頁面
FileListTableViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"FileListTableViewController"]; vc.direcotryPath = filePath; [self.navigationController pushViewController:vc animated:YES]; //查看照片,鋪滿全屏
}else if ([filePath hasSuffix:@"jpg"]||[filePath hasSuffix:@"png"]){ UIViewController *vc = [[UIViewController alloc]init]; vc.view.backgroundColor = [UIColor whiteColor]; UIImageView *iv = [[UIImageView alloc]initWithFrame:vc.view.bounds]; iv.image = [UIImage imageWithContentsOfFile:filePath]; [iv setContentMode:UIViewContentModeScaleAspectFit]; [vc.view addSubview:iv]; [self.navigationController pushViewController:vc animated:YES]; //查看文件內容
}else if ([filePath hasSuffix:@".h"]||[filePath hasSuffix:@".m"]||[filePath hasSuffix:@".txt"]||[filePath hasSuffix:@".rtf"]){ UIViewController *vc = [[UIViewController alloc]init]; UITextView *tv = [[UITextView alloc]initWithFrame:vc.view.bounds]; tv.text = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; [vc.view addSubview:tv]; [self.navigationController pushViewController:vc animated:YES]; //點擊其餘的就彈出警告框
}else{ UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"提示" message:@"此文件格式暫不支持,請期待下一版本!" delegate:self cancelButtonTitle:@"肯定" otherButtonTitles:nil, nil]; [alertView show]; } } //判斷是不是文件夾
-(BOOL)isDirecotryWithPath:(NSString *)path{ NSFileManager *manager = [NSFileManager defaultManager]; BOOL isDir; if ([manager fileExistsAtPath:path isDirectory:&isDir]&&isDir) { return YES; } return NO; } //表格的編輯模式
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { NSString *filePath = self.filePaths[indexPath.row]; if ([self isDirecotryWithPath:filePath]) { return NO; } return YES; } // 刪除模式
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { NSString *filePath = self.filePaths[indexPath.row]; [[NSFileManager defaultManager]removeItemAtPath:filePath error:nil]; [self.filePaths removeObject:filePath]; [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; } else if (editingStyle == UITableViewCellEditingStyleInsert) { } }     2.NSFileHandle 對局部文件進行操做 1.建立路徑 NSFileHandle *fh = [NSFileHandle fileHandleForReadingAtPath:@"/Library/Screen Savers/Default Collections/2-Aerial/Aerial06.jpg"]; 2.獲得文件的長度 方法一:Data獲取 此時會把文件加載到內存中 NSData *data = [NSData dataWithContentsOfFile:@"/Users/tarena/Documents/UIKit Core/Day1DragImage/ Day1DragImage/CatInBin.jpg"]; int length = data.length; 方法二:經過fileHandel獲取長度 不會把文件加載到內存 int fileLength = (int)[fh seekToEndOfFile]; //把遊標重置到開始的位置
[fh seekToFileOffset:fileLength/2]; 3.文件的讀寫 讀:1.)readDataToEndOfFile 讀到最後 2.)[fh seekToFileOffset:fileLength/2];中間的部分 寫:1)NSFileHandle *writeFH = [NSFileHandle fileHandleForWritingAtPath:@"/Users/tarena/Desktop/未命名文件夾/a.jpg」];寫到此路徑中 2)writeData:寫 將讀到的寫到路徑中 [writeFH writeData:subData]; 若是使用fileHandle寫數據的時候必須保證目標文件存在 要求:首先取出前半部分,讀到界面上,並將前半部分寫到新建立的文件中,而後修改長度到後半部分,再將後半部分寫到文件中(注意:有時候讀取一半的時候界面顯示的是整張圖片,那說明是像素點下降了) #import "ViewController.h"
@interface ViewController () @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; NSFileHandle *fh = [NSFileHandle fileHandleForReadingAtPath:@"/Library/Screen Savers/Default Collections/2-Aerial/Aerial06.jpg"]; //獲得文件的長度 //1.Data獲取 此時會把文件加載到內存中 // NSData *data = [NSData dataWithContentsOfFile:@"/Users/tarena/ Documents/UIKit Core/Day1DragImage/Day1DragImage/CatInBin.jpg"]; // int length = data.length; //2.經過fileHandel獲取長度 不會把文件加載到內存
int fileLength = (int)[fh seekToEndOfFile]; //把遊標重置到開始的位置
[fh seekToFileOffset:fileLength/2]; NSData *subData = [fh readDataToEndOfFile];//讀數據
UIImageView *iv = [[UIImageView alloc]initWithFrame:self.view.bounds]; iv.image = [UIImage imageWithData:subData]; [self.view addSubview:iv]; //建立文件 //[[NSFileManager defaultManager]createFileAtPath:@"/Users/tarena/Desktop/未命名文件夾/a.jpg" contents:nil attributes:nil]; //若是使用fileHandle寫數據的時候必須保證目標文件存在
NSFileHandle *writeFH = [NSFileHandle fileHandleForWritingAtPath:@"/Users/tarena/Desktop/未命名文件夾/a.jpg"];//寫數據
[writeFH seekToFileOffset:fileLength/2]; [writeFH writeData:subData]; } @end
=========================================================================== 知識點 2、XML可擴展標記性語言 1.XML可擴展標記性語言 (主要用來封裝) 1.Other—>Empty—>建立xml(文件名.xml) 建立Students.xml 2.兩種解析方式: SAX解析:逐行解析,從根元素開始,能夠解析超大數據不佔內存,比較適合解析大文件 DOM解析:把全部xml數據一次性加載到內存中,在內存中構建樹狀結構進行解析,解析流程簡單 方便實用,比較適合解析小文件 3.兩種解析手段 1.蘋果原生 NSXMLParser:SAX解析 2.第三方框架 libxml2: 同時支持SAX解析和DOM解析 GDataXML: DOM解析 4.解析的時候從開始—文本—結束,注意的是解析過程當中空格也是文本 2.SAX解析: Students.xml <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<students>
<student sid="1">
<name>小明</name>
<chinese>38</chinese>
<math>30</math>
<english>18</english>
</student>
<student sid="2">
<name>小麗</name>
<chinese>78</chinese>
<math>90</math>
<english>78</english>
</student>
<student sid="3">
<name>小王</name>
<chinese>28</chinese>
<math>10</math>
<english>48</english>
</student>
</students> Student.h #import <Foundation/Foundation.h>
@interface Student : NSObject @property (nonatomic, copy)NSString *name; @property (nonatomic, copy)NSString *sid; @property (nonatomic)int chinese; @property (nonatomic)int math; @property (nonatomic)int english; @end Student.m MyXMLParser.h #import <Foundation/Foundation.h>
#import "Student.h"
@interface MyXMLParser : NSObject<NSXMLParserDelegate> @property (nonatomic, strong)NSMutableArray *students; @property (nonatomic, strong)Student *s; @property (nonatomic, copy)NSString *currentString; -(NSMutableArray *)parseStudentsByPath:(NSString *)path; @end MyXMLParser.m #import "MyXMLParser.h"
@implementation MyXMLParser -(NSMutableArray *)parseStudentsByPath:(NSString *)path{ self.students = [NSMutableArray array]; NSData *data = [NSData dataWithContentsOfFile:path]; NSXMLParser *parser = [[NSXMLParser alloc]initWithData:data]; parser.delegate = self; //開始解析
[parser parse]; return self.students; } //開始標籤的時候會執行這個方法
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{ NSLog(@"開始:%@",elementName); if ([elementName isEqualToString:@"student"]) { self.s = [[Student alloc]init]; self.s.sid = [attributeDict objectForKey:@"sid"]; [self.students addObject:self.s]; } } //標籤之間的文本
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{ self.currentString = string; NSLog(@"文本:%@",string); } //結束標籤
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{ if ([elementName isEqualToString:@"name"]) { self.s.name = self.currentString; }else if ([elementName isEqualToString:@"chinese"]) { self.s.chinese = self.currentString.intValue; }else if ([elementName isEqualToString:@"math"]) { self.s.math = self.currentString.intValue; }else if ([elementName isEqualToString:@"english"]) { self.s.english = self.currentString.intValue; } NSLog(@"結束:%@",elementName); } @end ViewController.h ViewController.m #import "ViewController.h"
#import "MyXMLParser.h"
@interface ViewController () @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; MyXMLParser *parser = [[MyXMLParser alloc]init]; NSArray *students = [parser parseStudentsByPath:@"/Users/tarena6/Desktop/day03/Day3XML/Day3XML/students.xml"]; NSLog(@"%@",students); } @end
3.DOM解析 Students.xml 同上 Student.h Student.m 同上 ViewController.h ViewController.m NSMutableArray *students = [MyXMLParser parseStudentsByPath:@"/Users/tarena/Documents/UIKit Core/Day3DomXml/Day3DomXml/students.xml"]; MyXMLParser.h #import <Foundation/Foundation.h>
#import "Student.h"
@interface MyXMLParser : NSObject + (NSMutableArray *)parseStudentsByPath:(NSString *)path;//靜態方法
@end MyXMLParser.m #import "MyXMLParser.h"
#import "TBXML.h"
@implementation MyXMLParser + (NSMutableArray *)parseStudentsByPath:(NSString *)path{ NSMutableArray *students = [NSMutableArray array]; NSData *data = [NSData dataWithContentsOfFile:path]; TBXML *tbXML = [[TBXML alloc]initWithXMLData:data error:nil]; //得到root節點
TBXMLElement *studentsEle = tbXML.rootXMLElement; TBXMLElement *stuEle = [TBXML childElementNamed:@"student" parentElement:studentsEle]; //遍歷每個學生元素
while (stuEle) { Student *s = [[Student alloc]init]; s.sid = [TBXML valueOfAttributeNamed:@"sid" forElement:stuEle]; TBXMLElement *nameEle = [TBXML childElementNamed:@"name" parentElement:stuEle]; TBXMLElement *chineseEle = [TBXML childElementNamed:@"chinese" parentElement:stuEle]; TBXMLElement *mathEle = [TBXML childElementNamed:@"math" parentElement:stuEle]; TBXMLElement *englishEle = [TBXML childElementNamed:@"english" parentElement:stuEle]; //獲取元素中的文本
s.name = [TBXML textForElement:nameEle]; s.chinese = [[TBXML textForElement:chineseEle]intValue]; s.math = [[TBXML textForElement:mathEle]intValue]; s.english = [[TBXML textForElement:englishEle]intValue]; [students addObject:s]; stuEle = [TBXML nextSiblingNamed:@"student" searchFromElement:stuEle]; } return students; } @end TBXML.h TBXML.m 引入第三方框架文件 ======================================================================== 知識點 3、Plist文件和數組或字典 1.把內存中的字典或數組保存成plist文件 // 把內存中的字典或數組保存成plist文件
NSArray *names = @[@"老楊",@"小澤",@"我",@"老張"]; [names writeToFile:@"/Users/tarena/Desktop/names.plist" atomically:YES]; 2.把plist文件加載到內存中 成字典或數組 // 把plist文件加載到內存中 成字典或數組
NSArray *names = [NSArray arrayWithContentsOfFile:@"/Users/tarena/Desktop/names.plist"]; NSLog(@"%@",names);  例:1.故事板中,scollView,TextView來佈局 2.將plist以數組的形式添加到內存中 3.遍歷出plist中每一個項目,用字典的方式取出plist每一個項目中照片key值對應的value值 4.根據要求建立button,其背景圖爲value值 5.設置scollView的大小,實現滾動 6.爲按鈕添加點擊事件,點擊圖片便可以將其對應的文本顯示在建立的文本框中 7.主要用tag來記錄button的位置,用於字典獲取plist中圖片的文本,賦給文本框便可 #import "ViewController.h"
@interface ViewController () @property (weak, nonatomic) IBOutlet UITextField *myTF; @property (weak, nonatomic) IBOutlet UIScrollView *mySV; @property (nonatomic, strong)NSArray *faces; @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //項目中拖進的plist表格路徑
NSString *path = @"/Users/tarena6/Desktop/day04/Day4Faces/Day4Faces/face/emoticons.plist"; self.faces = [NSArray arrayWithContentsOfFile:path]; //遍歷出plist
for (int i=0; i<self.faces.count; i++) { //根據字典取出照片
NSDictionary *faceDic = self.faces[i]; NSString *imageName = [faceDic objectForKey:@"png"]; UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(i%8*40, i/8*40, 40, 40)]; button.tag = i; // NSLog(@"%ld",(long)button.tag);記錄按鈕相對應的位置是第幾個
[button setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal]; [button addTarget:self action:@selector(clicked:) forControlEvents:UIControlEventTouchUpInside]; [self.mySV addSubview:button]; } int line = self.faces.count%8==0?self.faces.count/8 : self.faces.count/8+1; [self.mySV setContentSize:CGSizeMake(0, line*40)]; } //點擊圖片按鈕,對應的文本框顯示出其對應的文本
-(void)clicked:(UIButton *)btn{ NSDictionary *dic = self.faces[btn.tag]; NSString *text = [dic objectForKey:@"chs"]; self.myTF.text = [self.myTF.text stringByAppendingString:text]; } @end  ================================================================================================================= 知識點 4、沙箱/沙盒 1.沙箱/沙盒 1.工程名稱.app:保存着工程中用到的全部的素材 此包是隻讀的 2.Documents:使用最多、用來保存有用的數據 iTunes會備份和恢復 3.Library/Caches:緩存文件夾 緩存數據 4.Library/Prefernces:偏好設置用來保存有用的小量數據 iTunes會備份和恢復 5.tmp:臨時文件夾 此文件夾下的數據 不定時的可能會被銷燬掉 查看電腦儲存的路徑方式: 1.打開Finder,點擊上方第三個按鈕,點擊前往或者使用快捷鍵:(Shift+Command+g) 2.將輸出的路徑複製到文本框中,就能夠到達想要到的路徑 1.獲得沙箱的根目錄 NSString *home = NSHomeDirectory(); NSLog(@"%@",home); /Users/tarena6/Library/Application Support/iPhone Simulator/7.1/Applications/77AF5459-865F-4792-8588-54B1378F07A5 2.獲得工程中根路徑下面的素材完整路徑 NSString *path = [[NSBundle mainBundle]pathForResource:@"direcotry" ofType:@"png"]; 照片名稱 NSLog(@"%@",path); /Users/tarena6/Library/Application Support/iPhone Simulator/7.1/Applications/77AF5459-865F-4792-8588-54B1378F07A5/Day4Sandbox.app/direcotry.png 3.獲得app包的路徑 NSString *appPath = [[NSBundle mainBundle]resourcePath]; NSLog(@"%@",appPath); /Users/tarena6/Library/Application Support/iPhone Simulator/7.1/Applications/77AF5459-865F-4792-8588-54B1378F07A5/Day4Sandbox.app 4.獲取Documents路徑 NSString *documentsPath = [home stringByAppendingPathComponent:@"Documents"]; documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; NSLog(@"documentsPath:%@",documentsPath); /Users/tarena6/Library/Application Support/iPhone Simulator/7.1/Applications/77AF5459-865F-4792-8588-54B1378F07A5/Documents 5.得到臨時文件夾路徑 NSString *tmpPath = NSTemporaryDirectory(); NSLog(@"%@",tmpPath); /Users/tarena6/Library/Application Support/iPhone Simulator/7.1/Applications/77AF5459-865F-4792-8588-54B1378F07A5/tmp/
6.獲取緩存路徑 NSString *cachesPath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0]; NSLog(@"%@",cachesPath); /Users/tarena6/Library/Application Support/iPhone Simulator/7.1/Applications/77AF5459-865F-4792-8588-54B1378F07A5/Library/Caches 2.練習,將一個文件的路徑複製到Documents路徑下 #import "ViewController.h"
@interface ViewController () @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //獲得沙箱的根目錄
NSString *home = NSHomeDirectory(); NSLog(@"%@",home); //文件的路徑
NSString *filePath = [[NSBundle mainBundle]pathForResource:@"direcotry" ofType:@"png"]; //documents的路徑
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject]; //將文件的路徑複製到documents的路徑下
NSString *newFilePath = [documentsPath stringByAppendingPathComponent:[filePath lastPathComponent]]; [[NSFileManager defaultManager]copyItemAtPath:filePath toPath:newFilePath error:nil]; } @end  ======================================================================== 知識點 5、NSUserDefaults 將數據保存在系統的偏好設置中plist 1.NSUserDefaults 偏好設置 第二次運行程序的時候,都保留了以前的數據 步驟: 1.建立NSUserDefaults實例 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults] 2.讀取以前保存的數據 int runCount = [ud integerForKey:@"runCount"]; 3.將數據保存到內存中 [ud setInteger:++runCount forKey:@"runCount"]; 4.數據同步,把內存中的數據同步到文件中 [ud synchronize]; 例:保存兩個控件的滑動狀態 @interface ViewController () - (IBAction)VolumeChange:(UISlider *)sender; - (IBAction)playModeChange:(UISegmentedControl *)sender; @property (weak, nonatomic) IBOutlet UISegmentedControl *playModeSC; @property (weak, nonatomic) IBOutlet UISlider *mySlider; @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; NSLog(@"%@",NSHomeDirectory()); NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; //把以前保存的數據取出來
int runCount = [ud integerForKey:@"runCount"]; //保存到內存中
[ud setInteger:++runCount forKey:@"runCount"]; //數據同步 把內存中的數據同步到文件中
[ud synchronize]; NSLog(@"程序運行了%d次",runCount); self.mySlider.value = [ud floatForKey:@"volume"]; self.playModeSC.selectedSegmentIndex = [ud integerForKey:@"playMode"]; } - (IBAction)VolumeChange:(UISlider *)sender { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; [ud setFloat:sender.value forKey:@"volume"]; [ud synchronize]; } - (IBAction)playModeChange:(UISegmentedControl *)sender { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; [ud setInteger:sender.selectedSegmentIndex forKey:@"playMode"]; selectedSegmentIndex選擇了第幾個按鈕 [ud synchronize]; } @end   例2:每次運行粉界面和黃界面交替出現 AppDelegate.h AppDelegate.m #import "AppDelegate.h"
#import "SecondViewController.h"
@implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSUserDefaults*user=[NSUserDefaults standardUserDefaults]; int runCount=[user integerForKey:@"runCount"]; [user setInteger:++runCount forKey:@"runCount"]; [user synchronize]; NSLog(@"%d",runCount); if (runCount%2==0) { //偶數時,顯示粉色界面 SecondViewController本身建立的控制器
SecondViewController*sec=[self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:@"SecondView"]; SecondViewController控制器的ID self.window.rootViewController=sec; } return YES; }   ============================================================================================ 知識點 6、 NSKeyedArchiver 歸檔 、 NSKeyedUnarchiver 反歸檔 1. NSKeyedArchiver 歸檔 把對象和data之間互相轉換 (只有實現了NSCoding協議才能將對象轉換成data) 2.歸檔,將對象轉爲data 1).歸檔方法一:能夠將多個對象添加到data中 1.準備一個可變的Data 2.建立歸檔對象 3.編碼 4.完成編碼 - (void)viewDidLoad { [super viewDidLoad]; NSArray *names = @[@"張三",@"李四",@"王五",@"趙六",@"田七"]; //1.準備一個可變的Data
NSMutableData *data = [NSMutableData data]; //2.建立歸檔對象
NSKeyedArchiver *arch = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data]; //3.編碼
[arch encodeObject:names forKey:@"names"]; //能夠往一個data中添加不少對象 //[arch encodeObject:names2 forKey:@"names2"]; //4.完成編碼
[arch finishEncoding]; [data writeToFile:@"/Users/tarena/Desktop/names.arch" atomically:YES]; 2).歸檔方法二:只能將一個對象添加到data中 - (void)viewDidLoad { [super viewDidLoad]; //NSLog(@"%@",self.view.subviews);
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self.view.subviews]; [data writeToFile:@"/Users/tarena/Desktop/subviews_1" atomically:YES]; }  3.反歸檔 把data轉回對象 1)反歸檔方法一: NSData *data = [NSData dataWithContentsOfFile:@"/Users/tarena/Desktop/names.arch"]; //1.建立反歸檔對象
NSKeyedUnarchiver *unArch = [[NSKeyedUnarchiver alloc]initForReadingWithData:data]; //2.解碼
NSArray *names = [unArch decodeObjectForKey:@"names"]; NSLog(@"%@",names); 2)反歸檔方法二: NSData *data = [NSData dataWithContentsOfFile:@"/Users/tarena6/Desktop/subviews_1"]; NSArray *subViews = [NSKeyedUnarchiver unarchiveObjectWithData:data]; 例:1.每兩秒變換一次界面圖片, 2.利用歸檔,事先從一個工程中建立好view界面,而後把五個界面分別轉換成data,名字要有guilv 3.利用反歸檔將data轉換爲對象,再另外一個工程中顯示 #import "ViewController.h"
@interface ViewController () @property (nonatomic)int count; @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; NSString *path = [[NSBundle mainBundle]pathForResource:@"subviews_0" ofType:@""]; NSData *data = [NSData dataWithContentsOfFile:path]; NSArray *subViews = [NSKeyedUnarchiver unarchiveObjectWithData:data]; for (int i=0;i<subViews.count;i++) { UIView *view = subViews[i]; UIImageView *imageView = [[UIImageView alloc]initWithFrame:view.frame]; imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%d.tif",i]]; imageView.layer.borderWidth = 1; [self.view addSubview:imageView]; } [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(changeLayout) userInfo:nil repeats:YES]; } -(void)changeLayout{ self.count++; NSString *path = [[NSBundle mainBundle]pathForResource:[NSString stringWithFormat:@"subviews_%d",self.count%5] ofType:@""]; NSData *data = [NSData dataWithContentsOfFile:path]; NSArray *newSubviews = [NSKeyedUnarchiver unarchiveObjectWithData:data]; for (int i=0; i<newSubviews.count; i++) { UIImageView *iv = self.view.subviews[i]; UIView *view = newSubviews[i]; [UIView animateWithDuration:1 animations:^{ iv.frame = view.frame; }]; } } @end    4.自定義歸檔 1.建立一個類繼承NSObject,遵照協議<NSCoding>,建立兩個屬性 2.而後實現兩個方法,並保存和讀取其數據 - (void)encodeWithCoder:(NSCoder *)aCoder{ [aCoder encodeObject:self.name forKey:@"name"]; [aCoder encodeInt:self.age forKey:@"age"]; } - (id)initWithCoder:(NSCoder *)aDecoder{ self = [super init]; if (self) { self.name = [aDecoder decodeObjectForKey:@"name"]; self.age = [aDecoder decodeIntForKey:@"age"]; } return self; } 例:1.自定義一個類,建立兩個屬性name,length。遵照協議並實現協議 2.A界面獲取一個路徑,而後將其遍歷,獲取其長度和名字賦給自定義的類 3.而後將其保存到數組中,再進行歸檔,保存到桌面 4.點擊A界面的按鈕進入到B界面,B界面是個表示圖控制器,將保存在桌面的文件進行反歸檔,獲取到data,以表格的形式將名稱和長度顯示出來 File.h #import <Foundation/Foundation.h>
@interface File : NSObject<NSCoding> @property (nonatomic, copy)NSString *name; @property (nonatomic)int length; @property (nonatomic)BOOL isDir; @end File.m #import "File.h"
@implementation File - (void)encodeWithCoder:(NSCoder *)aCoder{ [aCoder encodeObject:self.name forKey:@"name"]; [aCoder encodeInt:self.length forKey:@"length"]; [aCoder encodeBool:self.isDir forKey:@"isDir"]; } - (id)initWithCoder:(NSCoder *)aDecoder{ self = [super init]; if (self) { self.name = [aDecoder decodeObjectForKey:@"name"]; self.length = [aDecoder decodeIntForKey:@"length"]; self.isDir = [aDecoder decodeBoolForKey:@"isDir"]; } return self; } @end ViewController.h ViewController.m #import "ViewController.h"
#import "File.h"
@interface ViewController () @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; NSString *path = @"/Users/tarena/Desktop"; NSFileManager *manager = [NSFileManager defaultManager]; NSArray *fileNames = [manager contentsOfDirectoryAtPath:path error:nil]; NSMutableArray *files = [NSMutableArray array]; for (NSString *fileName in fileNames) { File *file = [[File alloc]init]; file.name = fileName; NSString *filePath = [path stringByAppendingPathComponent:fileName]; NSFileHandle *fh = [NSFileHandle fileHandleForReadingAtPath:filePath]; file.length = (int)[fh seekToEndOfFile]; [files addObject:file]; BOOL isDir; if ([manager fileExistsAtPath:filePath isDirectory:&isDir]&&isDir) { file.isDir = YES; } } NSData *data = [NSKeyedArchiver archivedDataWithRootObject:files]; [data writeToFile:@"/Users/tarena/Desktop/files" atomically:YES]; } @end FileListTableViewController.h FileListTableViewController.m #import "FileListTableViewController.h"
#import "File.h"
@interface FileListTableViewController () @property (nonatomic, strong)NSArray *files; @end
@implementation FileListTableViewController - (void)viewDidLoad { [super viewDidLoad]; NSData *data = [NSData dataWithContentsOfFile:@"/Users/tarena/Desktop/files"]; self.files = [NSKeyedUnarchiver unarchiveObjectWithData:data]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.files.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; File *file = self.files[indexPath.row]; cell.textLabel.text = file.name; NSString *size = nil; if (file.length>1024*1024) { size = [NSString stringWithFormat:@"%dM",file.length/1024/1024]; }else{ size = [NSString stringWithFormat:@"%dKB",file.length/1024]; } if (file.isDir) { size = @"文件夾"; } cell.detailTextLabel.text = size; return cell; } @end   ==================================================================== 知識點 7、CoreData 封裝了sqlite數據庫的框架 1.基本建立 1. 建立項目時直接選Application—>Empty Application 2.勾上Use Core Data 3.開始建立Storyboard.storyboard (User Interface 裏建立) 4.在主項目中Main Interface中下拉框選擇Storyboard 5.開始配置CoreData.xcdatamodeld,點擊下邊Add Entety進行添加對象,在右側Attributes中添加屬性 6.實現添加對象的類,點擊CoreData,選擇第三個下一步建立便可,而後項目中就多了一個類 2.基本功能 0.獲取AppDelegate的上下文 AppDelegate *app = [UIApplication sharedApplication].delegate; 1.增長 Person *p = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:app.managedObjectContext]; p.name = @"張三"; p.age = @(20); p.mobileCod = @"13838383388"; [app saveContext]; 2.刪除 NSFetchRequest *request = [[NSFetchRequest alloc]initWithEntityName:@"Person"]; NSArray *persons = [app.managedObjectContext executeFetchRequest:request error:nil]; for (Person *p in persons) { if ([p.name isEqualToString:@"張三"]) { [app.managedObjectContext deleteObject:p]; [app saveContext]; 3.修改 NSFetchRequest *reqeust = [[NSFetchRequest alloc]initWithEntityName:@"Person"]; NSArray *persons = [app.managedObjectContext executeFetchRequest:reqeust error:nil]; for (Person *p in persons) { if ([p.name isEqualToString:@"李四"]) { p.name = @"王五"; p.age = @(88); } } [app saveContext]; } 4.查看 NSFetchRequest *reqeust = [[NSFetchRequest alloc]initWithEntityName:@"Person"]; NSArray *persons = [app.managedObjectContext executeFetchRequest:reqeust error:nil]; for (Person *p in persons) { NSLog(@"%@ %@ %@",p.name,p.age,p.mobileCod); } 1)讓查詢結果進行排序 NSSortDescriptor [request setSortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES]]]; //根據年齡升序排序
2)設置查詢條件 NSPredicate NSPredicate *pre = nil; //1.比較運算符> < >= <= == !=
pre = [NSPredicate predicateWithFormat:@"age>40"]; //2.範圍運算符 IN、BETWEEN
pre = [NSPredicate predicateWithFormat:@"age BETWEEN{30,40}"]; pre = [NSPredicate predicateWithFormat:@"name IN{'aaaaa','bcd'}"]; //3.字符串處理 BEGINSWITH ENDSWITH CONTAINS c不區分大小寫 d不區分發音
pre = [NSPredicate predicateWithFormat:@"name BEGINSWITH[cd] 'a'"]; pre = [NSPredicate predicateWithFormat:@"name CONTAINS[cd] 'a'"]; //4.通配符:LIKE ?表明單個字符 *多個位置字符
pre = [NSPredicate predicateWithFormat:@"name LIKE[cd] '*m'"]; [request setPredicate:pre]; 如: //幾行
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { NSFetchRequest *request = [[NSFetchRequest alloc]initWithEntityName:@"Team"]; NSPredicate*pre=nil; pre=[NSPredicate predicateWithFormat:@"name BEGINSWITH[cd] 'a'"]; [request setPredicate:pre ]; self.teams = [self.app.managedObjectContext executeFetchRequest:request error:nil]; return self.teams.count; } 3.例:一個數據庫 1.建立一個Core Data數據庫,保存一個類,屬性爲name,age 2.兩個界面,A界面是tableViewControlle,B界面是普通控制器,B中有兩個文本框 3.點擊A界面左上角的加號,推出B界面,而後在B界面的文本框中輸入內容,保存在建立的Core Data數據庫中,點擊肯定按鈕,傳回到A界面顯示在表格中,利用數據庫增長的功能 4.在A 界面利用數據庫查看的功能,接收B界面傳回保存在數據庫的內容 5.刪除功能,點擊右上角的編輯按鈕,進行刪除每行的內容 6.點擊每行,能夠跳轉到B 界面,把每行的內容顯示到B界面的文本框中,利用segue方法實現傳值 知識點:Segue 1.經過設置Segue的identifier來肯定是跳轉到哪 - (IBAction)gobackText:(UIBarButtonItem *)sender { [self performSegueWithIdentifier:@"identifi" sender:nil]; //跳轉到另外一個界面
} -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ Person*p=self.persons[indexPath.row]; [self performSegueWithIdentifier:@"identifi" sender:p];//跳轉到另外一個界面,能夠傳參
} 2.若是有參數要傳到另外一個界面的時候,用系統提供的方法 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if (sender) { TextViewController*textVC=segue.destinationViewController; textVC.editPerson=sender; } } 建立的數據庫  Person.h #import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
@interface Person : NSManagedObject @property (nonatomic, retain) NSString * name; @property (nonatomic, retain) NSNumber * age; @end Person.m #import "Person.h"
@implementation Person @dynamic name; @dynamic age; @end PersonsTableViewController.h PersonsTableViewController.m #import "Person.h"
#import "PersonsTableViewController.h"
#import "AppDelegate.h"
#import "PersonInfoViewController.h"
@interface PersonsTableViewController () @property (nonatomic, strong)NSArray *persons; @property (nonatomic, weak)AppDelegate *app; @end
@implementation PersonsTableViewController - (void)viewDidLoad { [super viewDidLoad]; self.app = [UIApplication sharedApplication].delegate; self.title = @"通信錄"; self.navigationItem.rightBarButtonItem = self.editButtonItem; UIBarButtonItem *addItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addPerson)]; self.navigationItem.leftBarButtonItem = addItem; } //右上角+按鈕
-(void)addPerson{ [self performSegueWithIdentifier:@"personinfovc" sender:nil]; } #pragma mark - Table view data source
-(void)viewWillAppear:(BOOL)animated{ [self.tableView reloadData];//更新界面
} - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { NSFetchRequest *request = [[NSFetchRequest alloc]initWithEntityName:@"Person"]; self.persons = [self.app.managedObjectContext executeFetchRequest:request error:nil]; return self.persons.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; Person *p = self.persons[indexPath.row]; cell.textLabel.text = p.name; cell.detailTextLabel.text = [NSString stringWithFormat:@"%@",p.age]; return cell; } -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ Person *p = self.persons[indexPath.row]; [self performSegueWithIdentifier:@"personinfovc" sender:p]; } // 刪除功能
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { Person *person = self.persons[indexPath.row]; [self.app.managedObjectContext deleteObject:person]; [self.app saveContext]; [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; } else if (editingStyle == UITableViewCellEditingStyleInsert) { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
} } //此方法中寫傳遞參數的代碼
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { //判斷是不是編輯
if (sender) { PersonInfoViewController *vc = segue.destinationViewController; vc.editPerson = sender; } } @end PersonInfoViewController.h #import <UIKit/UIKit.h>
#import "Person.h"
@interface PersonInfoViewController : UIViewController @property (nonatomic, strong)Person *editPerson; @end PersonInfoViewController.m #import "PersonInfoViewController.h"
#import "AppDelegate.h"
#import "Person.h"
@interface PersonInfoViewController () - (IBAction)clicked:(id)sender; @property (weak, nonatomic) IBOutlet UITextField *ageTF; @property (weak, nonatomic) IBOutlet UITextField *nameTF; @end
@implementation PersonInfoViewController - (void)viewDidLoad { [super viewDidLoad]; //判斷是不是編輯
if (self.editPerson) { self.nameTF.text = self.editPerson.name; self.ageTF.text = [NSString stringWithFormat:@"%@",self.editPerson.age]; } } - (IBAction)clicked:(id)sender { AppDelegate *app = [UIApplication sharedApplication].delegate; //若是是編輯 就修改
if (self.editPerson) { self.editPerson.name = self.nameTF.text; self.editPerson.age = @(self.ageTF.text.intValue); }else{//若是editPerson沒有值說明是新建person
Person *p = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:app.managedObjectContext]; p.name = self.nameTF.text; p.age = @(self.ageTF.text.intValue); } [app saveContext]; [self.navigationController popViewControllerAnimated:YES]; } @end    4.例:兩個有聯繫的數據庫 1.經過.xcdatamodeld添加兩個類,設置好各自的屬性 2.而後點擊右下角進行切換模式,進行連線。 3.雙擊最後一行修改屬性,並經過右側的窗口設置Type,To One 或To Many 4.對兩個類進行實例化  To Many To One 例:要求: 1.建立兩個數據庫球隊和球員,並創建關係實例化 2.建立兩個table控制器,A控制器顯示球隊,點擊左上角加號彈出AlertView,輸入數據後顯示在單元格中 3.點擊單元格又彈出AlertView,對當前單元格進行修改 4.點擊右上角Edit按鈕,進入編輯模式,進行刪除操做 5.點擊每行右側的圓圈,進入B界面球員,點擊右上角加號彈出AlertView進行添加,顯示到單元格,刪除功能,修改功能同第一個界面 6.當返回到A界面時,右側的人數根據B界面添加的球員有關 TeamsTableViewController.h TeamsTableViewController.m #import "PlayersTableViewController.h"
#import "TeamsTableViewController.h"
#import "AppDelegate.h"
#import "Team.h"
@interface TeamsTableViewController ()<UIAlertViewDelegate> @property (nonatomic, weak)AppDelegate *app; @property (nonatomic, strong)NSArray *teams; @property (nonatomic, strong)Team *editTeam; @end
@implementation TeamsTableViewController - (void)viewDidLoad { [super viewDidLoad]; self.app = [UIApplication sharedApplication].delegate; self.navigationItem.rightBarButtonItem = self.editButtonItem; UIBarButtonItem *addItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addTeam)]; self.navigationItem.leftBarButtonItem = addItem; } //彈出alertView
-(void)addTeam{ UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"提示" message:@"請輸入球隊名稱" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"肯定", nil]; [alertView setAlertViewStyle:UIAlertViewStylePlainTextInput]; [alertView show]; } //實現協議
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ NSString *name = [alertView textFieldAtIndex:0].text; if (buttonIndex==1) { if (alertView.tag==0) { Team *t = [NSEntityDescription insertNewObjectForEntityForName:@"Team" inManagedObjectContext:self.app.managedObjectContext]; t.name = name; }else{//修改
self.editTeam.name = name; } [self.app saveContext]; [self.tableView reloadData]; } } //更新
-(void)viewWillAppear:(BOOL)animated{ [self.tableView reloadData]; } //幾行
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { NSFetchRequest *request = [[NSFetchRequest alloc]initWithEntityName:@"Team"]; self.teams = [self.app.managedObjectContext executeFetchRequest:request error:nil]; return self.teams.count; } //單元格內容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; Team *t = self.teams[indexPath.row]; cell.textLabel.text = t.name; cell.detailTextLabel.text = [NSString stringWithFormat:@"%d人",t.players.count]; UIButton *btn = [UIButton buttonWithType:UIButtonTypeInfoLight]; btn.tag = indexPath.row; [btn addTarget:self action:@selector(clicked:) forControlEvents:UIControlEventTouchUpInside]; cell.accessoryView = btn; return cell; } //點擊圓圈按鈕
-(void)clicked:(UIButton*)btn{ Team *team = self.teams[btn.tag]; [self performSegueWithIdentifier:@"playersvc" sender:team]; } //刪除
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { Team *t = self.teams[indexPath.row]; [self.app.managedObjectContext deleteObject:t]; [self.app saveContext]; [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; } else if (editingStyle == UITableViewCellEditingStyleInsert) { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
} } //點擊單元格
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ self.editTeam = self.teams[indexPath.row]; UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"提示" message:@"請修改球隊名稱" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"肯定", nil]; alertView.tag = 1; [alertView setAlertViewStyle:UIAlertViewStylePlainTextInput]; UITextField *tf = [alertView textFieldAtIndex:0]; tf.text = self.editTeam.name; [alertView show]; } //把值傳到B界面
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { PlayersTableViewController *vc = segue.destinationViewController; vc.team = sender; } @end PlayersTableViewController.h #import <UIKit/UIKit.h>
#import "Team.h"
@interface PlayersTableViewController : UITableViewController @property (nonatomic, strong)Team *team; @end PlayersTableViewController.m #import "PlayersTableViewController.h"
#import "Player.h"
#import "AppDelegate.h"
@interface PlayersTableViewController () @property (nonatomic, strong)NSArray *players; @property (nonatomic, weak)AppDelegate *app; @property (nonatomic, strong)Player *editPlayer; @end
@implementation PlayersTableViewController - (void)viewDidLoad { [super viewDidLoad]; self.app = [UIApplication sharedApplication].delegate; self.title = self.team.name; UIBarButtonItem *addItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addPlayer)]; self.navigationItem.rightBarButtonItems = @[self.editButtonItem,addItem]; } -(void)addPlayer{ UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"提示" message:@"請輸入球員名稱" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"肯定", nil]; [alertView setAlertViewStyle:UIAlertViewStylePlainTextInput]; [alertView show]; } //實現協議
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ NSString *name = [alertView textFieldAtIndex:0].text; if (buttonIndex==1) { if (alertView.tag==0) { Player *p = [NSEntityDescription insertNewObjectForEntityForName:@"Player" inManagedObjectContext:self.app.managedObjectContext]; p.name = name; p.myTeam = self.team; }else{//修改
self.editPlayer.name = name; } [self.app saveContext]; [self.tableView reloadData]; } } //幾行
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // 把set轉成array
self.players = [self.team.players allObjects]; return self.team.players.count; } //單元格內容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; Player *p = self.players[indexPath.row]; cell.textLabel.text = p.name; return cell; } //刪除單元格
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { Player *p = self.players[indexPath.row]; [self.app.managedObjectContext deleteObject:p]; [self.app saveContext]; [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; } else if (editingStyle == UITableViewCellEditingStyleInsert) { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
} } //點擊單元格
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ self.editPlayer = self.players[indexPath.row]; UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"提示" message:@"請修改球員名稱" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"肯定", nil]; alertView.tag = 1; [alertView setAlertViewStyle:UIAlertViewStylePlainTextInput]; UITextField *tf = [alertView textFieldAtIndex:0]; tf.text = self.editPlayer.name; [alertView show]; } @end    ========================================================================================= 知識點 8、多媒體 (圖片、音頻、視頻) 1.查看系統相冊保存的照片 UIImagePickerController 1.建立查看系統照片的實例 ,需設置代理,遵照協議 2.實現方法 ,點擊照片到下面的scrollView中 3.每張照片排布存放,每一個照片的右上角有編輯按鈕,點擊能夠刪除圖片 4.scrollView的右上角有完成按鈕返回到主界面,顯示到最上邊 5.長按圖片移動到中間的View區域 6.在view中點擊圖片,圖片能夠實現移動,旋轉,縮放,置上的功能 7.當點擊長按圖片拖放到最下邊的imageView中時,此時中間View的背景圖更換成下邊imageView中顯示的圖片 8.將view中的內容保存在一張照片中 9.點擊最右下角的保存按鈕,將圖片保存到內存中,在照片查看器能夠查看到 10.爲圖片添加濾鏡效果 知識點: 1.) UIImagePickerController 獲取系統照片 需設置代理,遵照協議 < UINavigationControllerDelegate, UIImagePickerControllerDelegate> UIImagePickerController *ipc = [[UIImagePickerController alloc]init]; [ipc setSourceType:UIImagePickerControllerSourceTypePhotoLibrary]; ipc.delegate = self; ipc.allowsEditing = YES; [self presentViewController:ipc animated:YES completion:nil]; 2.)屬性: //設置查看照片的保存方式
[pic setSourceType:UIImagePickerControllerSourceTypePhotoLibrary]; //文件夾形式顯示
UIImagePickerControllerSourceTypeCamera //照相機形式顯示
3.)照片的Key值 UIImagePickerControllerOriginalImage //原始照片
UIImagePickerControllerMediaType //
4.)向一個控件插入一個控件 (atIndex 表明插入到哪) [self.editView insertSubview:self.backgroundIV atIndex:0]; 5.)取出一個控件中的內容,保存在一張圖裏(截圖功能) -(UIImage *)getImageFromView:(UIView *)view{ ** //想保存的控件傳給view便可 //建立一個畫布
UIGraphicsBeginImageContext(view.frame.size); //把view中的內容渲染到畫布中
[view.layer renderInContext:UIGraphicsGetCurrentContext()]; //把畫布中的圖片取出來
UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); //結束渲染
UIGraphicsEndImageContext(); return image; 6.)保存照片 1.把圖片保存到系統相冊中 UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil); 2.將照片保存在指定的位置 UIImage *image = [info objectForKey:@"UIImagePickerControllerEditedImage"]; NSString *url = [[info objectForKey:UIImagePickerControllerReferenceURL] description]; // 把UIImage轉成Data
if ([url hasSuffix:@"JPG"]) { // 把UIImage轉成Data
self.imageData = UIImageJPEGRepresentation(image, 1); }else{//PNG
self.imageData = UIImagePNGRepresentation(image); } self.selectedIV.image = image; 保存在此imageView [self dismissViewControllerAnimated:YES completion:nil]; 7.)手勢自帶一個視圖view ,至關於此時點擊的圖片 UIImageView *tapIV = (UIImageView *)longPress.view; 8.)連續手勢都有state屬性,就是點擊的時機 (通常配合switch使用) UIGestureRecognizerStateBegan 開始 UIGestureRecognizerStateChanged 拖動 UIGestureRecognizerStateEnded 結束 例:day06—照片控制器 #import "ViewController.h"
@interface ViewController () @property (weak, nonatomic) IBOutlet UIImageView *bgIV; @property (weak, nonatomic) IBOutlet UIView *editView; @property (nonatomic, strong)UIImageView *backgroundIV; @property (nonatomic, strong) UIImageView *dragIV; @property (weak, nonatomic) IBOutlet UIScrollView *mySV; - (IBAction)clicked:(id)sender; @property (nonatomic, strong)UIScrollView *selectedImageSV; @property (nonatomic, strong)NSMutableArray *selectedImages; @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib.
} //獲取圖片和保存圖片的按鈕
- (IBAction)clicked:(id)sender { UIButton *btn = sender; if (btn.tag == 0) { self.selectedImages =[NSMutableArray array];UIImagePickerController *ipc = [[UIImagePickerController alloc]init]; ipc.delegate = self; // ipc.allowsEditing = YES;
[ipc setSourceType:UIImagePickerControllerSourceTypePhotoLibrary]; [self presentViewController:ipc animated:YES completion:nil]; }else{//保存圖片
UIImage *image = [self getImageFromView:self.editView]; //把圖片保存到系統相冊中selector不要瞎寫 點到方法內部 告訴你怎麼寫了
UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil); } } - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{ UIAlertView *alertView =[[UIAlertView alloc]initWithTitle:@"提示" message:@"圖片保存完成" delegate:self cancelButtonTitle:@"肯定" otherButtonTitles:nil, nil]; [alertView show]; } -(UIImage *)getImageFromView:(UIView *)view{ //建立一個畫布
UIGraphicsBeginImageContext(view.frame.size); // 把view中的內容渲染到畫布中
[view.layer renderInContext:UIGraphicsGetCurrentContext()]; // 把畫布中的圖片取出來
UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); //結束渲染
UIGraphicsEndImageContext(); return image; } //點擊圖片
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{ NSLog(@"%@",info); UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage]; UIImageView *iv = [[UIImageView alloc]initWithFrame:CGRectMake(self.selectedImages.count*80, 0, 80, 80)]; UIButton *deleteBtn = [[UIButton alloc]initWithFrame:CGRectMake(60, 0, 20, 20)]; [deleteBtn setTitle:@"X" forState:UIControlStateNormal]; [iv addSubview:deleteBtn]; iv.userInteractionEnabled = YES; [deleteBtn addTarget:self action:@selector(deleteImage:) forControlEvents:UIControlEventTouchUpInside]; iv.image = image; [self.selectedImageSV addSubview:iv]; [self.selectedImages addObject:iv]; [self.selectedImageSV setContentSize:CGSizeMake(self.selectedImages.count*80, 0)]; // [self dismissViewControllerAnimated:YES completion:nil];
} //刪除按鈕
-(void)deleteImage:(UIButton *)btn{ UIImageView *iv = (UIImageView *)btn.superview; [self.selectedImages removeObject:iv]; [iv removeFromSuperview]; for (int i=0;i<self.selectedImages.count;i++) { UIImageView *iv = self.selectedImages[i]; [UIView animateWithDuration:.5 animations:^{ iv.frame = CGRectMake(i*80, 0, 80, 80); }]; } } -(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{ if (navigationController.viewControllers.count==2) { UIView *v = [[UIView alloc]initWithFrame:CGRectMake(0, self.view.bounds.size.height-100, 320, 100)]; v.backgroundColor = [UIColor redColor]; [viewController.view addSubview:v]; self.selectedImageSV = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 20, 320, 80)]; self.selectedImageSV.backgroundColor = [UIColor blueColor]; [v addSubview:self.selectedImageSV]; UIButton *doneBtn = [[UIButton alloc]initWithFrame:CGRectMake(260, 0, 60, 20)]; [doneBtn setTitle:@"Done" forState:UIControlStateNormal]; [doneBtn addTarget:self action:@selector(doneAction) forControlEvents:UIControlEventTouchUpInside]; [v addSubview:doneBtn]; } } -(void)doneAction{ [self dismissViewControllerAnimated:YES completion:nil]; for (UIImageView *iv in self.selectedImages) { UIButton *btn = [iv.subviews lastObject]; [btn removeFromSuperview]; [self.mySV addSubview:iv]; // 添加長按手勢
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longAction:)]; [iv addGestureRecognizer:longPress]; } self.mySV.contentSize = self.selectedImageSV.contentSize; } //長按將圖片添加到view
-(void)longAction:(UILongPressGestureRecognizer*)longPress{ UIImageView *tapIV = (UIImageView *)longPress.view; CGPoint p = [longPress locationInView:self.view]; switch ((int)longPress.state) { case UIGestureRecognizerStateBegan: { CGRect oldFrame = tapIV.frame; CGRect newFrame = [self.mySV convertRect:oldFrame toView:self.view]; self.dragIV = [[UIImageView alloc]initWithFrame:newFrame]; self.dragIV.image = tapIV.image; [self.view addSubview:self.dragIV]; } break; case UIGestureRecognizerStateChanged: self.dragIV.center = p; break; case UIGestureRecognizerStateEnded: if (CGRectContainsPoint(self.editView.frame, p)) { CGPoint oldCenter = self.dragIV.center; CGPoint newCenter = [self.view convertPoint:oldCenter toView:self.editView]; [self.editView addSubview:self.dragIV]; self.dragIV.center = newCenter; //添加各類手勢
[self addGesture]; }else if (CGRectContainsPoint(self.bgIV.frame, p)){//背景區鬆手
self.bgIV.image = self.dragIV.image; //只有第一次往界面加背景的時候須要建立 添加到最下面 之後每次只須要修改便可
if (!self.backgroundIV) { self.backgroundIV = [[UIImageView alloc]initWithFrame:self.editView.bounds]; [self.editView insertSubview:self.backgroundIV atIndex:0]; } self.backgroundIV.image = self.dragIV.image; [self.dragIV removeFromSuperview]; }else{ [self.dragIV removeFromSuperview]; } break; } } //添加到view的圖片手勢
-(void)addGesture{ self.dragIV.userInteractionEnabled = YES; UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapAction:)]; UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panAction:)]; UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc]initWithTarget:self action:@selector(rotationAction:)]; UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinchAction:)]; [self.dragIV addGestureRecognizer:tap]; [self.dragIV addGestureRecognizer:pan]; [self.dragIV addGestureRecognizer:rotation]; [self.dragIV addGestureRecognizer:pinch]; } -(void)tapAction:(UITapGestureRecognizer *)tap{ //把某個子視圖帶到前面來
[self.editView bringSubviewToFront:tap.view]; } -(void)panAction:(UIPanGestureRecognizer*)pan{ pan.view.center = [pan locationInView:self.editView]; } -(void)rotationAction:(UIRotationGestureRecognizer *)rotation{ [rotation.view setTransform:CGAffineTransformRotate(rotation.view.transform, rotation.rotation)]; rotation.rotation = 0; } -(void)pinchAction:(UIPinchGestureRecognizer *)pinch{ [pinch.view setTransform:CGAffineTransformScale(pinch.view.transform, pinch.scale, pinch.scale)]; pinch.scale = 1; } @end    2.音頻 AVAudioPlayer 1.導入頭文件 #import <AVFoundation/AVFoundation.h>
2.建立音頻實例 AVAudioPlayer *player=[[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:@"/Users/tarena/Downloads/小蘋果.mp3"] error:nil] 3.屬性 [player play];播放 [player prepareToPlay]; //準備播放 是把數據加載到內存中 以便播放時可以及時播放
[self.player pause]; 暫停 player.volume = .2; 音量 player.currentTime 當前時間 player.currentTime = 50;從50秒開始唱 player.duration 總時間 知識點: 1.取出歌曲的名字 cell.textLabel.text = [[[musicPath lastPathComponent]componentsSeparatedByString:@"."]firstObject];省去.前面的(剪切) 2.實現界面結束,但歌曲不結束,將其AVAudioPlayer在AppDelegate中聲明成屬性,並在顯示界面時用self.app.player獲取 3.歌曲完成一首播放時,下一步該進行的事 a.將player設置爲當前代理,遵照協議<AVAudioPlayerDelegate> 實現其方法便可 4.字符串分割 componentsSeparatedByString:@「」 字符串中的內容爲剪切的起始點 5.字典排序 keys = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { if ([obj1 intValue]<[obj2 intValue]) { return NSOrderedAscending; 升序 }else return NSOrderedDescending; 降序 }]; 6.cell中的文本的設置 cell.textLabel.font = [UIFont systemFontOfSize:13]; 字體大小 [cell.textLabel setTextAlignment:NSTextAlignmentCenter]; 居中 cell.selectedBackgroundView = [[UIView alloc]initWithFrame:cell.bounds]; 點擊的背景 cell.selectedBackgroundView.backgroundColor = [UIColor clearColor]; cell.textLabel.highlightedTextColor = [UIColor redColor]; 文本顏色 7.UISegmentedControl 分割控件 .selectedSegmentIndex==0 根據此屬性來肯定點擊的是哪一個控件 例:day07 1.A 界面tableView顯示音樂播放列表,歌曲名單 2.點擊每行的時候,跳轉到B界面,進入B 界面後就開始播放點擊這行的歌曲 3.B界面有兩個進度條,一個調節音量,一個顯示歌曲進度 4.顯示進度的還能夠滑動調節歌曲的進度 5.兩個label,一個顯示歌曲總的秒數,另外一個根據歌曲的進度顯示秒數 6.一個button控制歌曲的播放和暫停 7.一首歌曲結束後自動播放下一曲 8.點擊按鈕,實現循環播放,隨機播放和單曲循環 UISegmentedControl按鈕,調去某個按鈕 用.selectedSegmentIndex屬性 9.添加圖片和歌詞 10.歌詞以tableView的形式顯示出來,從網上下載rlc形式的歌詞,而後將歌詞利用字符串的形式進行裁剪,並將裁剪的形式保存到數組和字典中,而後在顯示的界面,將歌曲的當前的時間與字典中的存儲的歌詞對應起來 AppDelegate.h #import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate> @property (strong, nonatomic) UIWindow *window; @property (nonatomic, strong)AVAudioPlayer *player; MusicsTableViewController.h MusicsTableViewController.m #import "MusicsTableViewController.h"
#import "ViewController.h"
@interface MusicsTableViewController () @property (nonatomic, strong)NSMutableArray *musicPaths; @end
@implementation MusicsTableViewController - (void)viewDidLoad { [super viewDidLoad]; //根據路徑獲取音樂 而後將路徑都保存到數組中
self.musicPaths = [NSMutableArray array]; NSString *path = @"/Users/tarena6/Desktop/音樂"; NSFileManager *fm = [NSFileManager defaultManager]; NSArray *fileNames = [fm contentsOfDirectoryAtPath:path error:nil]; for (NSString *fileName in fileNames) { if ([fileName hasSuffix:@"mp3"]) { //獲取完整的路徑
NSString *filePath = [path stringByAppendingPathComponent:fileName]; [self.musicPaths addObject:filePath]; } } } #pragma mark - Table view data source
//幾行
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.musicPaths.count; } //每行
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; NSString *musicPath = self.musicPaths[indexPath.row]; cell.textLabel.text = [[[musicPath lastPathComponent]componentsSeparatedByString:@"."]firstObject]; return cell; } //點擊每行的時候跳轉到b界面,並記錄每行的索引
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ [self performSegueWithIdentifier:@"playvc" sender:@(indexPath.row)]; } //將數組和內行內容所對應的索引值傳給b界面
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { ViewController *vc = segue.destinationViewController; vc.musicPaths = self.musicPaths; vc.currentIndex = [sender intValue]; } @end ViewController.h ViewController.m #import "Utils.h"
#import "AppDelegate.h"
#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
@interface ViewController ()<AVAudioPlayerDelegate,UITableViewDataSource,UITableViewDelegate> @property (weak, nonatomic) IBOutlet UILabel *currentTimeLabel; @property (nonatomic, strong)NSArray *keys; @property (nonatomic, strong)NSDictionary *lrcDic; @property (weak, nonatomic) IBOutlet UISlider *progressSlider; @property (weak, nonatomic) IBOutlet UILabel *totalTimeLabel; @property (nonatomic, weak)AppDelegate *app; @property (weak, nonatomic) IBOutlet UISegmentedControl *playModeSC; @property (weak, nonatomic) IBOutlet UITableView *tableView; @property (weak, nonatomic) IBOutlet UIImageView *artworkIV; @property (nonatomic, strong)NSTimer *timer; @end
@implementation ViewController //根據滑動的slider顯示總的時間,控制音量的大小
- (IBAction)sliderValueChange:(UISlider *)sender { if (sender.tag==0) { self.app.player.currentTime = sender.value; }else{ self.app.player.volume = sender.value; } } - (void)viewDidLoad { [super viewDidLoad]; self.app = [UIApplication sharedApplication].delegate; self.timer = [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(updateUI) userInfo:nil repeats:YES]; [self playMusic]; } -(void)playMusic{ if (self.currentIndex==-1) { self.currentIndex = self.musicPaths.count-1; } if (self.currentIndex==self.musicPaths.count) { self.currentIndex = 0; } self.musicPath = self.musicPaths[self.currentIndex]; self.artworkIV.image = [Utils getArtworkByPath:self.musicPath]; self.app.player = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:self.musicPath] error:nil]; self.app.player.delegate = self; self.title = [[[self.musicPath lastPathComponent]componentsSeparatedByString:@"."]firstObject]; //準備播放 是把數據加載到內存中 以便播放時可以及時播放 // [self.app.player prepareToPlay];
[self.app.player play]; self.totalTimeLabel.text = [NSString stringWithFormat:@"%02d:%02d",(int)self.app.player.duration/60,(int)self.app.player.duration%60]; self.progressSlider.maximumValue = self.app.player.duration; //判斷有沒有歌詞
NSString *lrcPath = [self.musicPath stringByReplacingOccurrencesOfString:@"mp3" withString:@"lrc"]; if ([[NSFileManager defaultManager]fileExistsAtPath:lrcPath]) { NSString *lrcString = [NSString stringWithContentsOfFile:lrcPath encoding:NSUTF8StringEncoding error:nil]; self.lrcDic = [Utils parseLrcWithString:lrcString]; self.keys = [self.lrcDic.allKeys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { if ([obj1 intValue]<[obj2 intValue]) { return NSOrderedAscending; }else return NSOrderedDescending; }]; [self.tableView reloadData]; } } //頁面將要結束的時候,關閉時間計時器
-(void)viewWillDisappear:(BOOL)animated{ [self.timer invalidate]; self.app.player.delegate =nil; 頁面結束的時候會奔 } //根據當前的時間來更新label顯示的進度
-(void)updateUI{ self.progressSlider.value = self.app.player.currentTime; self.currentTimeLabel.text = [NSString stringWithFormat:@"%02d:%02d",(int)self.app.player.currentTime/60,(int)self.app.player.currentTime%60]; //讓歌詞和歌曲同步
for (int i=0; i<self.keys.count; i++) { int time = [self.keys[i]intValue]; if (time>self.app.player.currentTime) { int line = i - 1; [self.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:line inSection:0] animated:YES scrollPosition:UITableViewScrollPositionMiddle]; break; } } } //點擊按鈕的時候,根據tag值來肯定點擊的是哪一個按鈕,選擇上一曲、下一曲仍是播放個暫停
- (IBAction)clicked:(UIButton *)sender { switch (sender.tag) { case 0: if (self.app.player.isPlaying) { [self.app.player pause]; [sender setTitle:@"播放" forState:UIControlStateNormal]; }else{ [self.app.player play]; [sender setTitle:@"暫停" forState:UIControlStateNormal]; } break; case 1: self.currentIndex--; [self playMusic]; break; case 2: self.currentIndex++; [self playMusic]; break; } } - (void)dealloc { NSLog(@"播放頁面銷燬了"); } //當一首歌播放完成的時候,根據點擊的按鈕來肯定隨機播放仍是循環播放仍是單曲循環
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{ if (self.playModeSC.selectedSegmentIndex==0) { self.currentIndex++; }else if (self.playModeSC.selectedSegmentIndex ==2){ self.currentIndex = arc4random()%self.musicPaths.count; } [self playMusic]; } //tableView來顯示歌詞
#pragma mark UITableViewDelegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return self.lrcDic.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; NSNumber *key = self.keys[indexPath.row]; cell.textLabel.text = [self.lrcDic objectForKey:key]; cell.textLabel.font = [UIFont systemFontOfSize:13]; [cell.textLabel setTextAlignment:NSTextAlignmentCenter]; cell.selectedBackgroundView = [[UIView alloc]initWithFrame:cell.bounds]; cell.selectedBackgroundView.backgroundColor = [UIColor clearColor]; cell.textLabel.highlightedTextColor = [UIColor redColor]; return cell; } -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ return 15; } @end 用來顯示圖片和歌詞的配置 Utils.h Utils.m (配置歌詞) +(NSDictionary *)parseLrcWithString:(NSString *)lrcString{ NSMutableDictionary *lrcDic = [NSMutableDictionary dictionary]; NSArray *lines = [lrcString componentsSeparatedByString:@"\n"]; for (NSString *line in lines) { if ([line hasPrefix:@"[0"]) { NSArray *timeAndText = [line componentsSeparatedByString:@"]"]; NSString *timeString = [[timeAndText firstObject] substringFromIndex:1]; NSArray *times = [timeString componentsSeparatedByString:@":"]; float time = [times[0]intValue]*60+[times[1]intValue]; [lrcDic setObject:timeAndText[1] forKey:@(time)]; } } return lrcDic; } @end   3.音頻(錄音) #import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
@interface ViewController () @property (nonatomic, strong)AVAudioPlayer *player; @property (nonatomic, strong)AVAudioRecorder *recorder; @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; NSMutableDictionary *settings = [NSMutableDictionary dictionary]; // 錄音格式
[settings setObject:@(kAudioFormatLinearPCM) forKey:AVFormatIDKey]; // 採樣率
[settings setObject:@(11025) forKey:AVSampleRateKey]; // 通道數
[settings setObject:@(2) forKey:AVNumberOfChannelsKey]; // 音頻質量
[settings setObject:@(AVAudioQualityMin) forKey:AVEncoderAudioQualityKey]; NSURL *url = [NSURL fileURLWithPath:@"/Users/tarena/Desktop/a.caf"]; self.recorder = [[AVAudioRecorder alloc]initWithURL:url settings:settings error:nil]; } //開始錄音
- (IBAction)beginAction:(id)sender { [self.recorder record]; } //開始播放錄音
- (IBAction)stopAction:(id)sender { [self.recorder stop]; self.player = [[AVAudioPlayer alloc]initWithContentsOfURL:self.recorder.url error:nil]; [self.player play]; } 封裝成類 RecordButton.h #import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@interface RecordButton : UIButton @property (nonatomic, strong)AVAudioPlayer *player; @property (nonatomic, strong)AVAudioRecorder *recorder; @end RecordButton.m #import "RecordButton.h"
@implementation RecordButton - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self initRecord]; } return self; } - (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { [self initRecord]; } return self; } //-(void)awakeFromNib{ // [super awakeFromNib]; //}
-(void)initRecord{ NSMutableDictionary *settings = [NSMutableDictionary dictionary]; // 錄音格式
[settings setObject:@(kAudioFormatLinearPCM) forKey:AVFormatIDKey]; // 採樣率
[settings setObject:@(11025) forKey:AVSampleRateKey]; // 通道數
[settings setObject:@(2) forKey:AVNumberOfChannelsKey]; // 音頻質量
[settings setObject:@(AVAudioQualityMin) forKey:AVEncoderAudioQualityKey]; NSURL *url = [NSURL fileURLWithPath:@"/Users/tarena/Desktop/a.caf"]; self.recorder = [[AVAudioRecorder alloc]initWithURL:url settings:settings error:nil]; [self addTarget:self action:@selector(beginAction) forControlEvents:UIControlEventTouchDown]; [self addTarget:self action:@selector(stopAction) forControlEvents:UIControlEventTouchUpInside]; } -(void)beginAction{ [self.recorder record]; } -(void)stopAction{ [self.recorder stop]; // 播放功能 // self.player = [[AVAudioPlayer alloc]initWithContentsOfURL:self.recorder.url error:nil]; // [self.player play];
NSData *audioData = [NSData dataWithContentsOfFile:self.recorder.url.path]; NSString *audioString = [audioData base64EncodedStringWithOptions:0]; [[NSNotificationCenter defaultCenter]postNotificationName:@"recordfinish" object:nil userInfo:@{@"audioString":audioString}]; } @end
4.視頻播放 MPMoviePlayerController 1.導入頭文件 #import <MediaPlayer/MediaPlayer.h>
2.根據路徑 建立實例,設置視屏屏幕view顯示大小 ,而後加入view 3.設置控制樣式 [self.player setControlStyle:MPMovieControlStyleNone]; 不能夠修改 4.點擊按鈕截取圖片 方法一:self.player thumbnailImageAtTime:方法 以下 方法二:設置監聽截屏通知 [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(didReceiveImage:) name:MPMoviePlayerThumbnailImageRequestDidFinishNotification object:nil]; [self.player requestThumbnailImagesAtTimes:@[@(self.player.currentPlaybackTime)] timeOption:MPMovieTimeOptionExact]; 在點擊按鈕事件中添加 5.播放完之後視頻從界面刪除 [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(didfi:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil]; 例:截圖,播放完刪除功能 #import "ViewController.h"
@interface ViewController () @property(nonatomic,strong)MPMoviePlayerController* player; @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; NSURL*sur=[NSURL fileURLWithPath:@"/Users/tarena6/Desktop/day08/mtv.mp4"]; self.player=[[MPMoviePlayerController alloc]initWithContentURL:sur]; self.player.view.frame=CGRectMake(0, 0, 320, 200); [self.view addSubview:self.player.view]; [self.player setControlStyle:MPMovieControlStyleDefault]; [self.player play]; //監聽截屏通知
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(startSing:) name:MPMoviePlayerThumbnailImageRequestDidFinishNotification object:nil]; //刪除
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(didfi:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil]; } -(void)didfi:(NSNotification*)ti{ [self.player.view removeFromSuperview]; } -(void )startSing:(NSNotification*)noti{ UIImage *image = [noti.userInfo objectForKey:MPMoviePlayerThumbnailImageKey]; UIImageView *iv = [[UIImageView alloc]initWithFrame:CGRectMake(0, 300, 320, 200)]; iv.image = image; [self.view addSubview:iv]; } - (IBAction)saveImage:(UIButton *)sender { /*方法一截圖*/
// UIImage* iamge=[self.player thumbnailImageAtTime:self.player.currentPlaybackTime timeOption:MPMovieTimeOptionExact]; // UIImageView*imageView=[[UIImageView alloc]initWithFrame:CGRectMake(0, 300, 320, 200)]; // imageView.image=iamge; // [self.view addSubview:imageView];
[self.player requestThumbnailImagesAtTimes:@[@(self.player.currentPlaybackTime)] timeOption:MPMovieTimeOptionExact]; } @end  ================================================================================== 知識點 7、多線程 1.應用場景: 1.解決耗時操做致使界面阻塞問題 2.同時作幾件事 3.多線程下載 2.切記!耗時操做不能放到主線程否則會致使界面阻塞 修改頁面的代碼不要放在子線程 3.三種開啓線程的方式: 1.NSThread:須要本身管理線程的生命週期,線程同步。線程同步對數據的加鎖會有必定的系統開銷 2.GCD:Grand Central Dispatch 中央任務分發 基於C語言 執行效率高 ,GCD是一個替代NSThread, NSOperationQueue,NSInvocationOperation等技術的很高效強大的技術。 3.NSOperation: 更靈活 能夠設置線程和線程之間的關係 不須要關心線程管理, 數據同步的事情,能夠把精力放在本身須要執行的操做上。 Cocoa operation相關的類是NSOperation, NSOperationQueue. NSOperation是個抽象類,使用它必須用它的子類,能夠實現它或者使用它定義好的兩個子 類: NSInvocationOperation和NSBlockOperation. 4.線程隊列: 1.串行隊列:依次執行隊列中的線程 2.並行隊列:同時執行隊列中的線程 1.NSThread開啓線程方式 1.建立多線程 1. [NSThread detachNewThreadSelector:@selector(runAction) toTarget:self withObject:nil]; 2.初始化方法 ,但須要 [t start] 2.建立出更改的頁面,但讓當前線程睡眠狀態 [NSThread sleepForTimeInterval:1]; 1爲睡眠時間。即界面顯示的時間間隔 3.而後把修改頁面的代碼回到主線程去執行 [self performSelectorOnMainThread:@selector(updateUI:) withObject:v waitUntilDone:NO]; 4.加載到界面顯示 5. 若不顯示的時候,須要刷新一下 [im setNeedsDisplay]; //刷新本控件顯示的時候調用
[im setNeedsLayout];//刷新子控件顯示的時候調用
如: #import "ViewController.h"
@interface ViewController () @end
@implementation ViewController - (IBAction)clicked:(id)sender { [NSThread detachNewThreadSelector:@selector(runAction) toTarget:self withObject:nil]; } -(void)runAction{ for (int i=0; i<10; i++) { //讓當前線程睡眠
[NSThread sleepForTimeInterval:1]; UIView *v = [[UIView alloc]initWithFrame:CGRectMake(100, i*50, 40, 40)]; v.backgroundColor = [UIColor redColor]; //把修改頁面的代碼回到主線程去執行
[self performSelectorOnMainThread:@selector(updateUI:) withObject:v waitUntilDone:NO]; } } -(void)updateUI:(UIView *)v{ [self.view addSubview:v]; [v setNeedsDisplay]; //刷新本控件顯示的時候調用
[v setNeedsLayout];//刷新子控件顯示的時候調用
} @end  利用多線程,在點擊按鈕後,紅色的方框就會逐步挨個出現。否則會總體出現 例: 1.打地鼠,每1秒隨機出現一個地鼠(按鈕) 2.按鈕上顯示數據3-2-1-0,顯示到0就消失 3.當點擊了按鈕,按鈕也消失 4.用兩個label來記錄成功和失敗的地鼠數(通知) ViewController.h ViewController.m #import "ViewController.h"
#import "Mouse.h"
@interface ViewController () @property (weak, nonatomic) IBOutlet UILabel *failLabel; @property (weak, nonatomic) IBOutlet UILabel *successLabel; @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [NSThread detachNewThreadSelector:@selector(addMouse) toTarget:self withObject:nil]; //監聽地鼠數量
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(statusChangeAction:) name:@"statusChange" object:nil]; } //記錄地鼠數量
-(void)statusChangeAction:(NSNotification *)noti{ NSString *status = [noti.userInfo objectForKey:@"status"]; if ([status isEqualToString:@"success"]) { int count = self.successLabel.text.intValue; self.successLabel.text = [NSString stringWithFormat:@"%d",count+1]; }else{ int count = self.failLabel.text.intValue; self.failLabel.text = [NSString stringWithFormat:@"%d",count+1]; } } //子線程
-(void)addMouse{ while (YES) { [NSThread sleepForTimeInterval:1]; [self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:NO]; } } //主線程
-(void)updateUI{ Mouse *m = [[Mouse alloc]initWithFrame:CGRectMake(arc4random()%300, arc4random()%548, 20, 20)]; [self.view addSubview:m]; } @end Mouse.h #import <UIKit/UIKit.h>
@interface Mouse : UIButton @end Mouse.m #import "Mouse.h"
@implementation Mouse - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.backgroundColor = [UIColor blueColor]; [self setTitle:@"3" forState:UIControlStateNormal]; [NSThread detachNewThreadSelector:@selector(countDownAction) toTarget:self withObject:nil]; [self addTarget: self action:@selector(clicked) forControlEvents:UIControlEventTouchUpInside]; } return self; } //點擊按鈕時
-(void)clicked{ [self removeFromSuperview]; [[NSNotificationCenter defaultCenter]postNotificationName:@"statusChange" object:nil userInfo:@{@"status": @"success"}]; } //倒計時3秒,本身消失
-(void)countDownAction{ for (int i=2; i>=0; i--) { [NSThread sleepForTimeInterval:.5]; if (!self.superview) { //若是再也不父視圖就返回
return; } [self performSelectorOnMainThread:@selector(updateUI:) withObject:@(i) waitUntilDone:NO]; } //由於刪除老鼠的代碼寫在了子線程的最後面 執行完成以後 並無耗時的代碼 因此雖然是修改頁面的 也能在子線程中執行
[self removeFromSuperview]; // 失敗次數+1
[[NSNotificationCenter defaultCenter]postNotificationName:@"statusChange" object:nil userInfo:@{@"status": @"fail"}]; } -(void)updateUI:(NSNumber *)number{ [self setTitle:[NSString stringWithFormat:@"%@",number] forState:UIControlStateNormal]; } @end  2.GCD開啓線程方式 1.建立線程隊列 串行隊列 線程1——0 線程1——1... 線程2——0... dispatch_queue_t myQueue1 = dispatch_queue_create("myQueue", NULL); 2. 獲取系統提供的並行隊列 (只有多個dispatch_async(myQueue2, ^{……}時)線程2——0 線程1——0 dispatch_queue_t myQueue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 3.執行某段代碼 在某個隊列中 dispatch_async(myQueue2, ^{ } 4.執行一段代碼在主線程中 dispatch_async(dispatch_get_main_queue(), ^{ } 例:每隔1秒。每隔單元格加載出一張圖片 #import "TableViewController.h"
@interface TableViewController () @end
@implementation TableViewController - (void)viewDidLoad { [super viewDidLoad]; } #pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 100; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; cell.imageView.image = nil;//避免單元格的重用
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ UIImage *image = [self downloadImage]; dispatch_async(dispatch_get_main_queue(), ^{ cell.imageView.image =image; [cell setNeedsLayout];//刷新每行
}); }); return cell; } -(UIImage *)downloadImage{ [NSThread sleepForTimeInterval:1]; return [UIImage imageNamed:@"a.jpg"]; } @end  3.NSOperation開啓線程方式 1.建立多線程 a.NSBlockOperation *op1 = [[NSBlockOperation blockOperationWithBlock:^{。。。。}]; b.NSInvocationOperation *op2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(runAction) object:nil]; 注意:兩個都須要開啓[op1 start];但注意start並無開啓子線程,只有添加到子線程纔會實行子線程加載 2.將多線程添加到子線程隊列當中 NSOperationQueue *opQueue = [[NSOperationQueue alloc]init]; 1)//設置最大並行線程數量
[opQueue setMaxConcurrentOperationCount:1]; 1爲串行 2)//添加線程之間的依賴關係
[op1 addDependency:op2]; 先顯示op2,在顯示op1 [opQueue addOperation:op1];普通的添加 例:每行的圖片漸漸的淡出 #import "MyTableViewController.h"
@interface MyTableViewController () @property(nonatomic,strong)NSOperationQueue*opQueue; @end
@implementation MyTableViewController - (void)viewDidLoad { [super viewDidLoad]; self.opQueue=[[NSOperationQueue alloc]init]; [self.opQueue setMaxConcurrentOperationCount:1]; } #pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 100; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath]; //cell.imageView.image=nil;
cell.imageView.alpha=0; NSBlockOperation*op=[NSBlockOperation blockOperationWithBlock:^{ [NSThread sleepForTimeInterval:1]; UIImage*image=[UIImage imageNamed:@"Dandelion.tif"]; //主線程
dispatch_async(dispatch_get_main_queue(), ^{ cell.imageView.image=image; [cell setNeedsLayout]; //淡化
[UIView animateWithDuration:1 animations:^{ cell.imageView.alpha=1; }]; }); }]; //添加到子線程
[self.opQueue addOperation:op]; return cell; } @end  ============================================================================================== 知識點 8、線程同步 當多條線程同時操做同一份數據的時候可能會出現問題,須要用到線程同步來解決此問題 1.同步:串行 不一樣時 線程同步的方式有三種方式 : 1.同步代碼塊 2.NSLock 3.NSCondicion 2.異步:並行 同時 1. 同步代碼塊 @synchronized(self){。。。} 當有其A對象在執行,那麼其餘的對象須要等到A對象執行完畢才能進入執行 例:模擬賣票系統 #import "ViewController.h"
@interface ViewController () @property (nonatomic)int totalCount; @property (nonatomic)int selledCount; //@property (nonatomic, strong)NSLock *myLock;
@end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.totalCount = 100; // self.myLock = [[NSLock alloc]init];
NSThread *t1 = [[NSThread alloc]initWithTarget:self selector:@selector(sellAction) object:nil]; t1.name = @"一號窗口"; [t1 start]; NSThread *t2 = [[NSThread alloc]initWithTarget:self selector:@selector(sellAction) object:nil]; t2.name = @"二號窗口"; [t2 start]; } -(void)sellAction{ while (YES) { NSString *name = [NSThread currentThread].name; //參數須要一個id類型的對象 對象中有個鎖旗標
@synchronized(self){ //[self.myLock lock];
NSLog(@"%@開始賣%d號票",name,self.selledCount+1); [NSThread sleepForTimeInterval:.5]; self.selledCount++; NSLog(@"%@賣了%d號票,還剩%d",name,self.selledCount,self.totalCount-self.selledCount); } // [self.myLock unlock];
} } @end 一號窗口開始賣1號票 一號窗口賣了1號票,還剩99 二號窗口開始賣2號票 二號窗口賣了2號票,還剩98 一號窗口開始賣3號票 一號窗口賣了3號票,還剩97 2.NSLock 1.建立實例 self.myLock = [[NSLock alloc]init]; 2.開鎖 [self.myLock lock]; 3.解鎖 [self.myLock unlock]; 3.NSCondicion 用法同上 4.線程之間的通訊 就是在進行進程內的兩個執行的河流之間進行的數據傳遞 performSelectOnTheThread方法 5.進程間的通訊 (兩個程序之間的通訊) a)和本身的程序創建鏈接 在Supporting Files—>.plist—>右擊建立Add Row—->倒數第二個—>下拉Item 0—>修改成URL-Schemes—>下拉Item 0—>最右側雙擊寫上名字myApp  要打開的程序設置 - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url{ NSString *info = [[[url description]componentsSeparatedByString:@"//"]lastObject]; UILabel *l = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 100, 100)]; l.backgroundColor = [UIColor redColor]; l.text = info; [self.window.rootViewController.view addSubview:l]; return YES; } 建立的新文件 ViewController.h ViewController.m - (IBAction)clicked:(UIButton *)sender { NSString *path = nil; switch (sender.tag) { case 0: path = @"tel://10010";//打電話
break; case 1: path = @"sms://10010";//發短信
break; case 2: path = @"mailto://838383@qq.com";//發郵件
break; case 3: path = @"http://www.youku.com";//瀏覽器
break; case 4: path = @"myApp://hehe";//打開本身的程序
break; } //將路徑添加到app
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:path]]; }  ============================================================================================================= 知識點 (day09) 9、網絡 TCP:三次握手,創建連接,數據安全,相對於UDP傳輸效率較低 UDP:傳輸速度塊,一對多廣播,安全性較低 1.TCP 1.服務器端 127.0.0.1 迴路ip a.導入框架,從網上 b.導入頭文件 #import "AsyncSocket.h"AsyncSocket框架 c.建立實例,遵照協議,建立監聽端口 d.實現協議,三步 day09 框架 AsyncSocket ViewController.h ViewController.m #import "ViewController.h"
#import "AsyncSocket.h"
@interface ViewController ()<AsyncSocketDelegate> @property (nonatomic, strong)AsyncSocket *serverSocket; @property (nonatomic, strong)AsyncSocket *myNewSocket; @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.serverSocket = [[AsyncSocket alloc]initWithDelegate:self]; //監聽端口
[self.serverSocket acceptOnPort:8000 error:nil]; } //監聽到管道連接過來 可是並沒連上呢
-(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket{ self.myNewSocket = newSocket; } //管道打通
-(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{ NSLog(@"連接成功 對方ip:%@",host); //調用獲取數據的方法
[self.myNewSocket readDataWithTimeout:-1 tag:0]; } //顯示對方傳過的數據
-(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{ NSString *info = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"接收到:%@",info); //接着要數據
[sock readDataWithTimeout:-1 tag:0]; } @end 連接成功 對方ip:172.60.13.175 接收到:該吃放了! 2.客戶端 a.導入文件,建立實例,遵照協議,建立與服務器的監聽端口 b.實現協議,和服務器創建鏈接 c.向服務器發送消息 #import "ViewController.h"
#import "AsyncSocket.h"
@interface ViewController ()<AsyncSocketDelegate>
- (IBAction)clicked:(UIButton *)sender; @property (nonatomic, strong)AsyncSocket *clientSocket; @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.clientSocket = [[AsyncSocket alloc]initWithDelegate:self]; [self.clientSocket connectToHost:@"對方的ip地址" onPort:8000 error:nil]; } -(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{ NSLog(@"和%@創建連接",host); } - (IBAction)clicked:(UIButton *)sender { NSData *data = [@"該吃飯了!" dataUsingEncoding:NSUTF8StringEncoding]; [self.clientSocket writeData:data withTimeout:-1 tag:0]; } @end 和172.60.13.60創建連接 2.服務器和用戶端在同一界面執行 #import "ViewController.h"
#import "AsyncSocket.h"
@interface ViewController ()<AsyncSocketDelegate> @property (nonatomic, strong)AsyncSocket *serverSocket; @property (nonatomic, strong)AsyncSocket *myNewSocket; @property (nonatomic, strong)AsyncSocket *clientScoket; @property (weak, nonatomic) IBOutlet UITextField *otherIP; @property (weak, nonatomic) IBOutlet UITextView *contentTV; @property (weak, nonatomic) IBOutlet UITextField *contentFV; @end
@implementation ViewController - (IBAction)close:(UITextField *)sender { [sender resignFirstResponder]; } - (void)viewDidLoad { [super viewDidLoad]; self.serverSocket = [[AsyncSocket alloc]initWithDelegate:self]; //監聽端口
[self.serverSocket acceptOnPort:8000 error:nil]; } //監聽到管道連接過來 可是並沒連上呢
-(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket{ self.myNewSocket = newSocket; } //管道打通
-(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{ // NSLog(@"連接成功 對方ip:%@",host);
self.otherIP.text=[NSString stringWithFormat:@"%@",host]; //調用獲取數據的方法
[self.myNewSocket readDataWithTimeout:-1 tag:0]; } //我發送的數據
- (IBAction)clicked:(id)sender { self.clientScoket = [[AsyncSocket alloc]initWithDelegate:self]; NSString*str=self.otherIP.text; [self.clientScoket connectToHost:str onPort:8000 error:nil]; self.contentTV.text=[self.contentTV.text stringByAppendingFormat:@"\n我說:%@",self.contentFV.text]; NSString* str1=self.contentFV.text; NSData *data = [str1 dataUsingEncoding:NSUTF8StringEncoding]; [self.clientScoket writeData:data withTimeout:-1 tag:0]; } //接受的數據
-(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{ NSString *info = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]; NSString*str=[self.otherIP.text stringByAppendingFormat:@"說:%@",info]; self.contentTV.text=[self.contentTV.text stringByAppendingFormat:@"\n %@",str]; // NSLog(@"接收到:%@",info); //接着要數據
[sock readDataWithTimeout:-1 tag:0]; } @end  ***3.傳輸文件和大型圖片和視頻 #import "ViewController.h"
#import "AsyncSocket.h"
@interface ViewController ()<AsyncSocketDelegate> @property (nonatomic, strong)AsyncSocket *serverSocket; @property (nonatomic, strong)AsyncSocket *myNewSocket; @property (nonatomic, strong)AsyncSocket *clientScoket; @property (nonatomic, strong)NSMutableData *allData; @property (nonatomic)int fileLength; @property (nonatomic, copy)NSString *fileName; @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.allData = [NSMutableData data]; self.serverSocket = [[AsyncSocket alloc]initWithDelegate:self]; //監聽端口
[self.serverSocket acceptOnPort:8000 error:nil]; self.clientScoket = [[AsyncSocket alloc]initWithDelegate:self]; // 127.0.0.1 迴路ip
[self.clientScoket connectToHost:@"127.0.0.1" onPort:8000 error:nil]; } //監聽到管道連接過來 可是並沒連上呢
-(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket{ self.myNewSocket = newSocket; } //管道打通
-(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{ NSLog(@"連接成功 對方ip:%@",host); //調用獲取數據的方法
[self.myNewSocket readDataWithTimeout:-1 tag:0]; } //接收數據
-(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{ //取出頭100個字節,轉化爲字符串
NSData *headerData = [data subdataWithRange:NSMakeRange(0, 100)]; NSString *headerString = [[NSString alloc]initWithData:headerData encoding:NSUTF8StringEncoding]; if (headerString&&[headerString componentsSeparatedByString:@"&&"].count==2) {//第一部分數據
NSArray *headers = [headerString componentsSeparatedByString:@"&&"]; self.fileName = [headers firstObject]; self.fileLength = [[headers lastObject] intValue]; self.allData = [NSMutableData data]; //取出拋去頭剩下的文件數據
NSData *subFileData = [data subdataWithRange:NSMakeRange(100, data.length-100)]; [self.allData appendData:subFileData]; }else{//不是第一部分 接收到的data時文件data
[self.allData appendData:data]; } //判斷文件是否下載完成
if (self.allData.length == self.fileLength) { NSLog(@"文件傳輸完成"); NSString *newPath = [@"/Users/tarena6/Desktop" stringByAppendingPathComponent:self.fileName]; [self.allData writeToFile:newPath atomically:YES]; } //接着要數據 保證後面的數據接收到
[sock readDataWithTimeout:-1 tag:0]; } //發送
- (IBAction)clicked:(id)sender { NSString *imagePath = @"/Users/tarena6/Desktop/老師課件/day08/mtv.mp4"; NSData *fileData = [NSData dataWithContentsOfFile:imagePath]; NSLog(@"%@",fileData); // 1.準備頭字符串 (文件名+文件長度)
NSString *headerString = [NSString stringWithFormat:@"%@&&%d",[imagePath lastPathComponent],fileData.length]; // 2.把頭字符串轉成data
NSData *headerData = [headerString dataUsingEncoding:NSUTF8StringEncoding]; // 3.把headerData 裝進100個字節的data中
NSMutableData *sendAllData = [NSMutableData dataWithLength:100]; [sendAllData replaceBytesInRange:NSMakeRange(0, headerData.length) withBytes:headerData.bytes]; // 4.把文件數據 追加在後面
[sendAllData appendData:fileData]; [self.clientScoket writeData:sendAllData withTimeout:-1 tag:0]; } @end 例:day10FTP 服務器接收的步驟: 1.導入框架(網上) AsyncSocket.h 2.建立實例和監聽接口,遵照協議 self.serverSocket = [[AsyncSocket alloc]initWithDelegate:self]; [self.serverSocket acceptOnPort:8000 error:nil]; 3.監聽到管道連接過來 (但並無鏈接上) -(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket{ self.myNewSocket = newSocket; } 4.打通管道,得到對方的IP //管道打通
-(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{ NSLog(@"連接成功 對方ip:%@",host); //調用獲取數據的方法
[self.myNewSocket readDataWithTimeout:-1 tag:0]; } 5.接受數據 -(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{ 1.先獲取頭數據 a.取出0-100字節的頭字符串data 轉換爲字符串 b.判斷是不是頭字符串,是的話就經過&&拆分爲幾部分保存在數組中(名字+長度) c.提取出名字和長度 d.就剩下的100-data.length-100的data存放到data數組中 2.沒有第一部分就直接接受data 3.繼續接收數據 [sock readDataWithTimeout:-1 tag:0]; 3.接收完成後保存建立保存的路徑 經過判斷self.fileAllData.length == self.fileLength來肯定是否接收完成 [self.fileAllData writeToFile:saveFilePath atomically:YES]; 客戶端發送的步驟: 1.導入文件,建立實例,遵照協議,建立與服務器的監聽端口, 輸入服務器IP self.clientScoket = [[AsyncSocket alloc]initWithDelegate:self]; [self.clientScoket connectToHost:@"127.0.0.1" onPort:8000 error:nil]; 2.實現協議,和服務器創建鏈接 -(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{ NSLog(@"和%@創建連接",host); } 3.向服務器發送消息 a.將要傳送的路徑轉換成data b.取出頭字符串(文件名+長度) c.把頭字符串轉成data d.新建立一個可變100個字節的data d.把頭Data 裝進100個字節的data中 e.把整個文件數據 追加在後面 4.發送數據 [self.clientScoket writeData:sendAllData withTimeout:-1 tag:0]; 新知識點: 1.設置進度條,來顯示文件的下載速度 (文件數據長度/包括文件頭的數據長度) self.myProgressView.progress = self.fileAllData.length*1.0/self.fileLength; 2.獲取文件的長度,以字符串M和kb顯示出來 NSFileHandle *fh = [NSFileHandle fileHandleForReadingAtPath:filePath]; int length = (int)[fh seekToEndOfFile]; NSString *size = @""; size = length>1024*1024?[NSString stringWithFormat:@"%dM",length/1024/1024] : [NSString stringWithFormat:@"%dKB",length/1024] 3.從客戶端獲取服務器中儲存的數據 -(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{ 2.UDP: 框架 AsyncUdpSocket.h 0.建立實例 self.myUDPSocket = [[AsyncUdpSocket alloc]initWithDelegate:self]; 1.綁定端口 [self.myUDPSocket bindToPort:9000 error:nil]; 2.開啓廣播 [self.myUDPSocket enableBroadcast:YES error:nil]; 3.接收數據 [self.myUDPSocket receiveWithTimeout:-1 tag:0]; 4.接到對方傳過來的數據 -(BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port{ *** //繼續讀取數據
[self.myUDPSocket receiveWithTimeout:-1 tag:0]; 5.點擊按鈕發送消息 255.255.255.255 你們在一個網段就均可以收到 NSData *data = [@"你們好!" dataUsingEncoding:NSUTF8StringEncoding]; [self.myUDPSocket sendData:data toHost:@"255.255.255.255" port:9000 withTimeout:-1 tag:0]; 例:實現和你們傳輸,也能夠針對性的傳輸 知識點: 1.查看數組中是否包含此數據 if (![self.hosts containsObject:host]) { [self.hosts addObject:host]; [self.tableView reloadData]; } 2.離開頁面的時候 關閉socket 關閉後別人就不能給你發送了 -(void)viewDidDisappear:(BOOL)animated{ [self.myUDPSocket close]; } 3.判斷不是以點開頭的ip if (![host hasPrefix:@":"]) { 開始給host發送消息 ViewController.h ViewController.m #import "ViewController.h"
#import "AsyncUdpSocket.h"
@interface ViewController ()<UITableViewDataSource, UITableViewDelegate> @property (nonatomic, copy)NSString *toHost; @property (weak, nonatomic) IBOutlet UILabel *statusLabel; @property (weak, nonatomic) IBOutlet UITableView *tableView; @property (weak, nonatomic) IBOutlet UITextView *historyTV; - (IBAction)valueChangeAction:(UISwitch *)sender; @property (weak, nonatomic) IBOutlet UITextField *sendInfoTF; @property (weak, nonatomic) IBOutlet UISwitch *mySwitch; @property (nonatomic, strong)AsyncUdpSocket *myUDPSocket; @property (nonatomic, strong)NSMutableArray *hosts; @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.toHost = @"255.255.255.255"; self.hosts = [NSMutableArray array]; self.myUDPSocket = [[AsyncUdpSocket alloc]initWithDelegate:self]; // 綁定端口
[self.myUDPSocket bindToPort:9000 error:nil]; //開啓廣播
[self.myUDPSocket enableBroadcast:YES error:nil]; //接收數據
[self.myUDPSocket receiveWithTimeout:-1 tag:0]; [self checkingOnline]; [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(checkingOnline) userInfo:nil repeats:YES]; } -(void)checkingOnline{ NSData *data = [@"誰在線" dataUsingEncoding:NSUTF8StringEncoding]; [self.myUDPSocket sendData:data toHost:@"255.255.255.255" port:9000 withTimeout:-1 tag:0]; } - (IBAction)clicked:(id)sender { [self.sendInfoTF resignFirstResponder]; NSData *data = [self.sendInfoTF.text dataUsingEncoding:NSUTF8StringEncoding]; [self.myUDPSocket sendData:data toHost:self.toHost port:9000 withTimeout:-1 tag:0]; NSString *toName = self.toHost; if ([toName isEqualToString:@"255.255.255.255"]) { toName = @"全部人"; } self.historyTV.text = [self.historyTV.text stringByAppendingFormat:@"我對%@說:%@",toName,self.sendInfoTF.text]; } -(BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port{ if (![host hasPrefix:@":"]) { NSString *info = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@說:%@",host,info); if ([info isEqualToString:@"誰在線"]) { NSData *d = [@"我在線" dataUsingEncoding:NSUTF8StringEncoding]; [self.myUDPSocket sendData:d toHost:host port:9000 withTimeout:-1 tag:0]; }else if ([info isEqualToString:@"我在線"]){ if (![self.hosts containsObject:host]) { [self.hosts addObject:host]; [self.tableView reloadData]; } }else{//接收到的是聊天內容
self.historyTV.text = [self.historyTV.text stringByAppendingFormat:@" %@說:%@",host,info]; } } //繼續讀取數據
[self.myUDPSocket receiveWithTimeout:-1 tag:0]; return YES; } #pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.hosts.count; } //幾行
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; NSString *host = self.hosts[indexPath.row]; cell.textLabel.text = [[host componentsSeparatedByString:@"."]lastObject]; return cell; } //點擊每行時針對我的ip
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ self.toHost = self.hosts[indexPath.row]; self.statusLabel.text = [NSString stringWithFormat:@"對%@說:",self.toHost]; [self.mySwitch setOn:NO animated:YES]; } - (IBAction)valueChangeAction:(UISwitch *)sender { if (sender.isOn) { self.statusLabel.text = @"對全部人說:"; }else{//開着變關
if ([self.toHost isEqualToString:@"255.255.255.255"]) { [sender setOn:YES animated:YES]; return; } self.statusLabel.text = [NSString stringWithFormat:@"對%@說:",self.toHost]; } } @end   例:經過UDF 服務器與客戶端創建連接,而後在經過FTP雙方互相通訊,實現點擊屏幕打地鼠的遊戲 day11 ========================================================================= 知識點 10、 NSJSONSerialization 數據接口(JSON) 1.將此種類型轉換後顯示{ 聚合數據 "resultcode": "200", "reason": "success", "result": [{ "rid": "1", "name": "灰姑娘", "wk": "2015.3.16 – 2015.3.22(單位:萬元)", "wboxoffice": "¥18000", "tboxoffice": "¥34200" }, 1.獲得要解的路徑,以data的形式保存起來 2.存放到字典中,在將字典存放到數組中 3.開始遍歷數組,取出字典中存放的數據,分別賦給建立好接收的類的屬性 4.再將類的屬性以tableView的形式顯示出來 NSString *path = [[NSBundle mainBundle]pathForResource:@"hongshaorou" ofType:@"txt"]; NSData *jsonData = [NSData dataWithContentsOfFile:path]; NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil]; self.menus = [JsonParser parseMenusByDic:dic];//將值賦給JsonParser類解析
經典例子解析:  JsonParser.h #import <Foundation/Foundation.h>
@interface JsonParser : NSObject +(NSMutableArray *)parseMenusByDic:(NSDictionary *)dic; @end JsonParser.m 解析類 #import "JsonParser.h"
#import "Menu.h"
#import "Step.h"
@implementation JsonParser +(NSMutableArray *)parseMenusByDic:(NSDictionary *)dic{ NSDictionary *resultDic = [dic objectForKey:@"result"]; NSArray *dataArr = [resultDic objectForKey:@"data"]; NSMutableArray *menus = [NSMutableArray array]; for (NSDictionary *menuDic in dataArr) { Menu *m = [[Menu alloc]init]; m.title = [menuDic objectForKey:@"title"]; m.menuID = [menuDic objectForKey:@"id"]; m.intro = [menuDic objectForKey:@"imtro"]; m.album = [[menuDic objectForKey:@"albums"] firstObject]; NSArray *stepsArr = [menuDic objectForKey:@"steps"]; for (NSDictionary *stepDic in stepsArr) { Step *s = [[Step alloc]init]; s.img = [stepDic objectForKey:@"img"]; s.step = [stepDic objectForKey:@"step"]; [m.steps addObject:s]; } [menus addObject:m]; } return menus; } @end WebUtils.h typedef void (^Callback)(id obj); 傳值 #import <Foundation/Foundation.h>
@interface WebUtils : NSObject +(void)menusByName:(NSString*)name andCallback:(Callback)callback; @end WebUtils.m 網絡請求類 #import "WebUtils.h"
#import "JsonParser.h"
@implementation WebUtils +(void)menusByName:(NSString*)name andCallback:(Callback)callback{ NSString*path=@"http://apis.juhe.cn/cook/query"; NSURL* url=[NSURL URLWithString:path]; NSMutableURLRequest*request=[NSMutableURLRequest requestWithURL:url]; NSString*params=[NSString stringWithFormat:@"key=80996127f667eac43832103850b3b13a&menu=%@",name]; [request setHTTPMethod:@"POST"]; [request setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]]; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; NSMutableArray*menus=[JsonParser parseMenusByDic:dic]; callback(menus); }]; } @end Menu.h #import <Foundation/Foundation.h>
@interface Menu : NSObject @property (nonatomic, copy)NSString *title; @property (nonatomic, copy)NSString *menuID; @property (nonatomic, copy)NSString *intro; @property (nonatomic, strong)NSMutableArray *steps; @property (nonatomic, copy)NSString *album; @end Menu.m 菜單 #import "Menu.h"
@implementation Menu - (instancetype)init { self = [super init]; if (self) { self.steps = [NSMutableArray array]; } return self; } @end Step.h 步驟 #import <Foundation/Foundation.h>
@interface Step : NSObject @property (nonatomic, copy)NSString *img; @property (nonatomic, copy)NSString *step; @end Step.m TableViewController.h TableViewController.m 顯示菜單界面 #import "MenuTableViewCell.h"
#import "TableViewController.h"
#import "JsonParser.h"
#import "Menu.h"
#import "Step.h"
#import "WebUtils.h"
@interface TableViewController () @property (nonatomic, strong)NSMutableArray *menus; @end
@implementation TableViewController - (void)viewDidLoad { [super viewDidLoad]; [WebUtils menusByName:self.str andCallback:^(id obj) { self.menus=obj; [self.tableView reloadData]; }]; } #pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.menus.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { MenuTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; cell.m = self.menus[indexPath.row]; return cell; } MenuTableViewCell.h MenuTableViewCell.m 自定義單元格 #import "MenuTableViewCell.h"
@implementation MenuTableViewCell -(void)layoutSubviews{ [super layoutSubviews]; //更新頁面顯示
self.titleLabel.text = self.m.title; self.menuIDLabel.text = self.m.menuID; self.introTV.text = self.m.intro; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:self.m.album]]; dispatch_async(dispatch_get_main_queue(), ^{ self.albumIV.image = [UIImage imageWithData:imageData]; }); }); } @end SeekViewController.h SeekViewController.m 搜索界面 #import "SeekViewController.h"
#import "TableViewController.h"
@interface SeekViewController () - (IBAction)beganSeek:(UIButton *)sender; @property (weak, nonatomic) IBOutlet UITextField *textField; @end
@implementation SeekViewController - (void)viewDidLoad { [super viewDidLoad]; } - (IBAction)beganSeek:(UIButton *)sender { [self.textField resignFirstResponder]; } -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ TableViewController*vc=segue.destinationViewController; vc.str=self.textField.text; } @end   注意:顯示照片:不能直接賦值 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:self.m.album]]; dispatch_async(dispatch_get_main_queue(), ^{ self.albumIV.image = [UIImage imageWithData:imageData]; }); }); =========================================================================== 知識點 11、HTTP(GET /POST) NSURLConnection NSURLSession Http:基於鏈接協議 短連接(請求響應式),開發效率高,容錯性強 ,傳輸效率低(每次數據傳輸都須要帶頭數據) Socket:對程序員要求高,開發效率低 ,長鏈接,傳輸效率高 (聊天) 1. Http: 網絡接口、網絡API、webService、網絡服務、web接口、webAPI(服務器提供的接口) ***從接口文檔當中須要獲得信息:請求地址、請求參數、請求類型( GET/POST)、返回數據類型 支持格式(XML/JSON)、返回數據具體字段類型 2. HTTP請求方式: GET: 把請求參數放到請求地址後面用?鏈接, 應用場景: 通常是從服務器獲取數據時用到 POST:把請求參數放到請求體裏面, 數據安全,能夠傳遞大的數據的參數, 應用場景 :須要把數據保存到服務器的時候   3.HTTP發送請求的方式 與NSURLConnection相比,NSURLSession最直接的改善就是提供了配置每一個會話的緩存,協議,cookie和證書政策(credential policies),甚至跨應用程序共享它們的能力。 1)NSURLConnection 2)NSURLSession 3)第三方框架 AFNetworking 1. 步驟:NSURLConnection 獲取網絡數據 1.使用GET請求方式+同步請求 1.請求地址 (GET請求方式是把請求參數放在路徑的後面) 字典形式存在 ,中間加上& NSString *path = @"http://apis.juhe.cn/cook/query?key=80996127f667eac43832103850b3b13a&menu=紅燒肉"; 2.請求地址中若是出現中文 須要進行URL編碼 path = [path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSURL *url = [NSURL URLWithString:path]; 3.建立請求對象 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url] 4.發出請求獲得返回數據 NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];//發出同步請求獲得返回數據
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; 2.使用POST請求方式+異步請求 NSString *path = @"http://apis.juhe.cn/cook/query"; NSURL *url = [NSURL URLWithString:path]; //建立請求對象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSString *params = [NSString stringWithFormat:@"key=80996127f667eac43832103850b3b13a&menu=%@",self.menuName];//參數 //若是使用POST請求方式 須要作兩件事: //1.設置請求方式
[request setHTTPMethod:@"POST"]; //2.把參數設置到請求體裏面
[request setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]]; //發出異步請求獲得返回數據
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; self.menus = [JsonParser parseMenusByDic:dic]; [self.tableView reloadData]; }]; 新知識點,將網絡傳輸封裝到一個類,block反向傳值 WebUtils.h typedef void (^Callback)(id obj);//定義類型
#import <Foundation/Foundation.h>
@interface WebUtils : NSObject +(void)requestMenusByName:(NSString *)name andCallback:(Callback)callback; @end WebUtils.m #import "WebUtils.h"
#import "JsonParser.h"
@implementation WebUtils +(void)requestMenusByName:(NSString *)name andCallback:(Callback)callback{ NSString *path = @"http://apis.juhe.cn/cook/query"; NSURL *url = [NSURL URLWithString:path]; //建立請求對象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSString *params = [NSString stringWithFormat:@"key=80996127f667eac43832103850b3b13a&menu=%@",name]; //若是使用POST請求方式 須要作兩件事: // 1.設置請求方式
[request setHTTPMethod:@"POST"]; // 2.把參數設置到請求體裏面
[request setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]]; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; NSMutableArray *menus = [JsonParser parseMenusByDic:dic]; callback(menus);//返回
}]; } @end TableViewController.h TableViewController.m 調用的時候 [WebUtils requestMenusByName:self.menuName andCallback:^(id obj) { self.menus = obj; [self.tableView reloadData]; }]; 2.NSURLSession 獲取解析數據 //解析明星
+(void)requestStarInfoWithStarName:(NSString *)name andCallback:(MyCallback)callback{ NSString *path = [NSString stringWithFormat:@"http://web.juhe.cn:8080/video/p?appkey=f0e620e13cb28728e6a5f4cc5e0e9dfb&v=1.0&pname=com.tarena&keyword=%@",name]; path = [path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSURL *url = [NSURL URLWithString:path]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; //建立Session 會話
NSURLSession *session = [NSURLSession sharedSession]; // 分爲三種請求:1.上傳請求 2.下載請求 3.數據請求
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; Star *s = [JsonParser parseStarByDic:dic]; callback(s); }]; //***獲取數據
[task resume]; } 3.經過網址直接觀看視頻 UIWebView UIWebView *wv = [[UIWebView alloc]initWithFrame:self.view.bounds]; [self.view addSubview:wv]; //obj是網址
NSURL *url = [NSURL URLWithString:obj]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [wv loadRequest:request]; day12經過搜索明星和電影名字,能夠查看明星資料和電影資料,而且能夠播放電影 1.用到了經過三種接口 解析數據 (即原始路徑不一樣)  界面      4.NSURLSession的下載請求 1.導入下載路徑,保存成NSURL 發送請求 NSString *path = @"http://music.baidu.com/data/music/file?link=http://yinyueshiting.baidu.com/data2/music/238979467/124380645248400128.mp3?xcode=5bc281221e17f22342438bc98f009a4aa957e289de92d109&song_id=124380645"; NSURL *url = [NSURL URLWithString:path]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url] 1).下載任務 直接直接下載完成時用此方法 NSURLSession *session = [NSURLSession sharedSession]; NSURLSessionDownloadTask *task = [session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) { NSLog(@"%@",location); [task resume]; 2).有下載過程的下載任務 不支持後臺defaultSessionConfiguration 能夠實現後臺下載 NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfiguration:@"abcd"]; NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]]; NSURLSessionDownloadTask *task = [session downloadTaskWithRequest:request]; [task resume]; } 2.能夠查看下載進度 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{ NSLog(@"%lld %lld %lld",bytesWritten,totalBytesWritten,totalBytesExpectedToWrite); //每次下載任務/總的下載任務 進度條
self.myPV.progress = totalBytesWritten*1.0/totalBytesExpectedToWrite; } 3.將下載下來默認的保存路徑更改 -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{ NSLog(@"下載完成"); NSString *path = @"/Users/tarena/Desktop/匆匆那年.mp3"; NSURL *newURL = [NSURL fileURLWithPath:path]; [[NSFileManager defaultManager]moveItemAtURL:location toURL:newURL error:nil]; } ***5.HTTP 發送請求經過第三方框架 AFNetworking UIKit+AFNetworking 1.照片的路徑能夠不用解析直接利用框架擴展的方法直接調用 #import "UIImageView+AFNetworking.h" UIImageView *iv = [[UIImageView alloc]initWithFrame:self.view.bounds]; [self.view addSubview:iv]; NSString *imgPath = @"http://g.hiphotos.baidu.com/image/pic/item/d000baa1cd11728be1f6a446cbfcc3cec2fd2cfe.jpg"; [iv setImageWithURL:[NSURL URLWithString:imgPath]]; 2.HTTP 請求 網絡數據 1)經過AFHTTPRequestOperationManager發出請求 NSString *path = @"http://web.juhe.cn:8080/video/p"; NSDictionary *params = @{@"appkey": @"f0e620e13cb28728e6a5f4cc5e0e9dfb",@"v":@"1.0",@"pname":@"com.tarena",@"keyword":@"劉德華"}; AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; //設置響應數據序列化
[manager setResponseSerializer:[AFHTTPResponseSerializer serializer]]; //GET POST請求方式根據須要定
[manager GET:path parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) { NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:nil]; NSLog(@"%@",dic); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"請求失敗"); }]; 2)經過AFHTTPRequestOperation發出請求 NSString *path = @"http://api.dianping.com/v1/business/find_businesses"; NSDictionary *params = @{@"city": @"北京"}; path = [DianpingApi serializeURL:path params:params];//DianpingApi?
NSLog(@"%@",path); NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:path]]; AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc]initWithRequest:request]; [op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:nil]; NSLog(@"%@",dic); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"請求失敗"); }]; [op start]; ======================================================================================================= 知識點 12、美團網站APP 例:day14頁面上方加的搜索框 例:day15經過首字母分類(plist文件)    ========================================================== 知識點 十3、地圖 MKMapView 相似於cell的一些特性,好比點擊事件和滾動地圖都是能夠選擇時機方法的 1.注意:使用地圖要在項目中增長  2.右側故事板中還能夠修改地圖的樣式 Hybrid 有建築物標誌 Satellite 衛星地圖 Map 街道形式 3.導入頭文件 #import <MapKit/MapKit.h>
4. //刪除以前的位置
[self.mapView removeAnnotations:self.mapView.annotations]; //當前地圖中心經緯度
CLLocationCoordinate2D coord = mapView.centerCoordinate; 5.得到地圖的位置,將點擊的座標點轉換成經緯度 CLLocationCoordinate2D coord = [self.mapView convertPoint:point toCoordinateFromView:self.view]; 6.自定義大頭針 1.繼承自 MKAnnotationView 2.初始化方法,添加大頭針的照片 -(id)initWithAnnotation:(id<MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier{ if ([super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier]) { UIImage *image = [UIImage imageNamed:@"001.png"]; self.image = image; } return self; } 3.控制器調用的時候 設置代理 ,在故事版中要鏈接到當前控制器的代理 @interface ViewController ()<MKMapViewDelegate>
4.實現方法 - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{ static NSString *identifer = @"annotationView"; MyAnnotationView *annView = (MyAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:identifer]; if (!annView) { annView = [[MyAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:identifer]; } return annView; } 7.移動到哪就在哪顯示大頭針 - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{ [WeiboApi requestWeibosWithCoord:mapView.centerCoordinate andCallBack:^(id obj) { [self loadAnnotationsWithWeibos:obj]; 建立大頭針的方法 }]; } 例: MyAnnotation.h 點擊即添加大頭針 ,繼承自NSObject #import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@interface MyAnnotation : NSObject<MKAnnotation> 增長協議,點進協議,複製方法 @property (nonatomic) CLLocationCoordinate2D coordinate; // Title and subtitle for use by selection UI.
@property (nonatomic, copy) NSString *title; @property (nonatomic, copy) NSString *subtitle; // Called as a result of dragging an annotation view.
- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate; @end MyAnnotation.m #import "MyAnnotation.h"
@implementation MyAnnotation @end ViewController.h ViewController.m #import "ViewController.h"
#import <MapKit/MapKit.h>
#import "MyAnnotation.h"
#import "MyAnnotationView.h"
@interface ViewController ()<MKMapViewDelegate> @property (weak, nonatomic) IBOutlet MKMapView *mapView; @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // 北緯:39.90960456049752 // 東經:116.3972282409668
CLLocationCoordinate2D coord; coord.longitude = 116.3972282409668; coord.latitude = 39.90960456049752; //指定顯示的地圖
[self.mapView setRegion:MKCoordinateRegionMake(coord, MKCoordinateSpanMake(0.001, 0.001))]; } //點擊到達的地圖位置
- (IBAction)tapAction:(UITapGestureRecognizer *)sender { CGPoint point = [sender locationInView:self.view]; //得到地圖的位置,將點擊的座標點轉換成經緯度
CLLocationCoordinate2D coord = [self.mapView convertPoint:point toCoordinateFromView:self.view]; //地圖顯示範圍 0.1表明範圍大
[self.mapView setRegion:MKCoordinateRegionMake(coord, MKCoordinateSpanMake(0.001, 0.001)) animated:YES]; //添加大頭針
MyAnnotation *ann = [[MyAnnotation alloc]init]; ann.coordinate = coord; ann.title = @"這是標題"; ann.subtitle = @"這是詳情"; [self.mapView addAnnotation:ann]; } //自定義大頭針
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{ static NSString *identifer = @"annotationView"; MyAnnotationView *annView = (MyAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:identifer]; if (!annView) { annView = [[MyAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:identifer]; } return annView; } @end
//自定義大頭針
MyAnnotationView.h #import <MapKit/MapKit.h>
@interface MyAnnotationView : MKAnnotationView @end MyAnnotationView.m #import "MyAnnotationView.h"
@implementation MyAnnotationView -(id)initWithAnnotation:(id<MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier{ if ([super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier]) { UIImage *image = [UIImage imageNamed:@"001.png"]; self.image = image; } return self; } @end   =============================================================================== 知識點 12、UIWebView 1.直接經過故事板建立web,和控制器連線設置代理 2.圖中四個按鈕,無需寫代碼,只須要右擊web,直接與按鈕連線便可   #import "ViewController.h"
@interface ViewController ()<UIWebViewDelegate> @property (weak, nonatomic) IBOutlet UITextField *myTF; @property (weak, nonatomic) IBOutlet UIActivityIndicatorView *juhua; @property (weak, nonatomic) IBOutlet UIWebView *webView; - (IBAction)Go:(UIButton*)sender; @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; } //文本框輸入網址,點擊go按鈕跳轉到此頁面
- (IBAction)Go:(id)sender { NSURL *url = [NSURL URLWithString:self.myTF.text]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [self.webView loadRequest:request]; } //頁面開始加載的時候,路徑中若是不包含baidu,就不跳轉
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{ NSString *urlPath = [request.URL description]; if ([urlPath rangeOfString:@"baidu"].length>0) {//路徑中是否包含baidu
return YES; } return NO; } //頁面加載的時候,進度圈加載
-(void)webViewDidStartLoad:(UIWebView *)webView{ [self.juhua startAnimating]; } //頁面加載完成的時候,進度圈中止加載
-(void)webViewDidFinishLoad:(UIWebView *)webView{ [self.juhua stopAnimating]; } @end
========================================================================================================================= 知識點 十4、微博項目 day17 1.註冊微博開發者帳號,獲取appKey即 client_id 2.用代碼加載登錄頁面 (設置delegate,故事板須要連線) NSString *appKey = @"1629509029"; //重定向地址
NSString *uri = @"https://api.weibo.com/oauth2/default.html"; //加載登陸頁面
NSString *path = [NSString stringWithFormat:@"https://api.weibo.com/oauth2/authorize?client_id=%@&redirect_uri=%@",appKey,uri]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:path]]; [self.webView loadRequest:request];   3.經過代碼發送微博 4.網絡請求例子 (照片和文本) //發送照片和文本
+(void)sendWeiboWithText:(NSString *)text andImageData:(NSData *)imageData andCallback:(MyCallback)callback{ NSString *path = @"https://api.weibo.com/2/statuses/upload.json"; NSDictionary *params = @{@"access_token": [WeiboApi getToken],@"status":text}; AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; [manager setResponseSerializer:[AFHTTPResponseSerializer serializer]]; [manager POST:path parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { //發送照片
[formData appendPartWithFileData:imageData name:@"pic" fileName:@"abc.jpg" mimeType:@"image/jpg"]; } success:^(AFHTTPRequestOperation *operation, id responseObject) { NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:nil]; callback(dic); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"發送帶圖失敗"); }]; } 5.自定義cell xib建立 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *identifier = @"Cell"; WeiboCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; if (!cell) { cell = [[[NSBundle mainBundle]loadNibNamed:@"WeiboCell" owner:self options:nil]firstObject]; } cell.weibo = self.weibos[indexPath.row]; weibo是自定義類,記錄屬性的 return cell; } 6.*****側滑欄 1.框架 ICSDrawerController 2.藉助TabBarViewController來實現多個界面的側滑 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { MenuTableViewController *menuvc = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:@"menuvc"]; self.mainvc = (MainTabbarController*)self.window.rootViewController; //經過框架來實現,
self.drawerController = [[ICSDrawerController alloc]initWithLeftViewController:menuvc centerViewController:self.mainvc]; //跟視圖控制器
self.window.rootViewController = self.drawerController; return YES; }  ***7.建立控件的時候須要調用的方法 //經過純代碼建立自定義的控件的時候調用此方法
-(id)initWithFrame:(CGRect)frame //經過storyboard或xib建立控件時調用此方法 此時子控件沒有初始化 爲nil
-(id)initWithCoder:(NSCoder *)aDecoder //經過storyboard或xib建立控件時調用此方法 此時子控件有值
-(void)awakeFromNib ***8.根據微博文本的高度肯定顯示的cell大小 自定義微博 Weibo.h Weibo.m #import "Weibo.h"
@implementation Weibo -(float)getWeiboHeight{ // 1.拿到文本 計算文本所佔高度 // 2.若是有圖片加上圖片高度 // 3.判斷是否有轉發 若是有轉發 // 轉發微博對象也有getWeiboHeight方法
float height = 0; //計算微博文本的高度
CGRect frame = [self.text boundingRectWithSize:CGSizeMake(300, 999) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:14]} context:nil]; //加上文本高度
height += frame.size.height; //加上微博圖片的高度-----------------------
if (self.thumbnailImage != nil && ![@"" isEqualToString:self.thumbnailImage]) { height += 110; } //加上轉發的微博的高度
if (self.relWeibo) { //轉發微博視圖的高度
float repostHeight = [self.relWeibo getWeiboHeight]; height += repostHeight; } if (_isRepost == YES) {//若是有轉發 多加20個像素 爲了美觀
height += 20; } return height; } @end 每條微博高度 weiboView.h #import <UIKit/UIKit.h>
#import "Weibo.h"
@interface weiboView : UIView @property (nonatomic, strong)Weibo *weibo; @property (nonatomic, strong)UITextView *textView; @property (nonatomic, strong)UIImageView *imageView; //轉發微博
@property(nonatomic,strong)weiboView*relWeiboView; @end weiboView.m #import "weiboView.h"
#import "UIImageView+AFNetworking.h"
@implementation weiboView - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { //此位置初始化用到的兩個控件
[self initUI]; } return self; } -(void)initUI{ //添加文本控件
self.textView = [[UITextView alloc]initWithFrame:CGRectZero]; self.textView.userInteractionEnabled = NO; self.textView.font = [UIFont systemFontOfSize:14]; [self addSubview:self.textView]; self.textView.backgroundColor = [UIColor clearColor]; // 添加圖片控件
self.imageView = [[UIImageView alloc]initWithFrame:CGRectZero]; [self.imageView setContentMode:UIViewContentModeScaleAspectFit]; [self addSubview:self.imageView]; } -(void)layoutSubviews{ [super layoutSubviews]; //此位置寫顯示內容和更改尺寸的代碼
float width = 300; //計算文本高度
CGRect frame = [self.weibo.text boundingRectWithSize:CGSizeMake(width, 999) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:14]} context:nil]; self.textView.frame = CGRectMake(5, 0, width, frame.size.height+10); // 設置顯示的文本
self.textView.text = self.weibo.text; //若是存在圖片
if (self.weibo.thumbnailImage && ![self.weibo.thumbnailImage isEqualToString:@""]) { // 由於不是每一條微博都有圖片 weiboView又是不停在複用
self.imageView.hidden = NO; self.imageView.frame = CGRectMake(5,self.textView.frame.size.height+10, width, 100); [self.imageView setImageWithURL:[NSURL URLWithString:self.weibo.thumbnailImage]]; }else{//若是沒有圖片把圖片隱藏
self.imageView.hidden = YES; } //**************添加轉發**************************
if (self.weibo.relWeibo) { //第一次須要建立 以後直接複用
if (!self.relWeiboView) { self.relWeiboView = [[weiboView alloc]initWithFrame:CGRectZero]; [self.relWeiboView setBackgroundColor:[UIColor colorWithRed:223/255.0 green:223/255.0 blue:223/255.0 alpha:1]]; [self addSubview:self.relWeiboView]; } // 複用的時候若是沒有轉發須要隱藏 有則顯示出來
self.relWeiboView.hidden = NO; self.relWeiboView.frame = CGRectMake(5, self.textView.frame.size.height+5, width, [self.relWeiboView.weibo getWeiboHeight]); self.relWeiboView.weibo = self.weibo.relWeibo; }else{//若是沒有轉發就隱藏
self.relWeiboView.hidden = YES; } //********************************************
} @end 自定義cell WeiboCell.h @property(nonatomic,strong)Weibo * weibo; @property(nonatomic,strong)weiboView*weiboView; WeiboCell.m -(void)awakeFromNib{ [super awakeFromNib]; self.weiboView = [[weiboView alloc]initWithFrame:CGRectZero]; [self addSubview:self.weiboView]; } //千萬不能在此方法中建立控件
-(void)layoutSubviews{ [super layoutSubviews]; //更新每一條微博的高度
self.weiboView.frame = CGRectMake(5, 45, 300, [self.weibo getWeiboHeight]); self.weiboView.weibo = self.weibo; } 顯示控制器 SelfMessageViewController.h SelfMessageViewController.m -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ Weibo *weibo = self.showSendweibos[indexPath.row]; return [weibo getWeiboHeight]+110; //顯示行高
} 9.從下面的toolbar彈出鍵盤,並收起 記得要遵照協議<UIAlertViewDelegate,UITextFieldDelegate>
-(void)initToolbar{ self.toolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, self.view.bounds.size.height-45, 320, 45)]; self.sendInfoTF = [[UITextField alloc]initWithFrame:CGRectMake(10, 5, 260, 35)]; [self.sendInfoTF setPlaceholder:@"寫評論"]; [self.sendInfoTF setBorderStyle:UITextBorderStyleBezel]; UIBarButtonItem *bbi = [[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:@"03話題詳情_11.png"] style:UIBarButtonItemStyleBordered target:self action:@selector(sendAction)]; UIBarButtonItem *sendInfoBBI = [[UIBarButtonItem alloc]initWithCustomView:self.sendInfoTF]; self.toolbar.items = @[sendInfoBBI,bbi]; [self.navigationController.view addSubview:self.toolbar]; //監聽軟鍵盤 事件
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(WillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil]; self.sendInfoTF.delegate = self; } //離開頁面的時候把toolbar刪除
-(void)viewWillDisappear:(BOOL)animated{ [self.toolbar removeFromSuperview]; } //控制toolbar位置
#pragma mark - keyboard reference
-(void)WillChangeFrame:(NSNotification *)notif{ NSDictionary *info = [notif userInfo]; NSValue *value = [info objectForKey:UIKeyboardFrameEndUserInfoKey]; CGRect keyboardFrame = [value CGRectValue]; [UIView animateWithDuration:.2 animations:^{ CGRect frame = self.toolbar.frame; frame.origin.y = keyboardFrame.origin.y-45; self.toolbar.frame = frame; }]; } //發送按鈕
-(void)sendAction{ [self.sendInfoTF resignFirstResponder]; //清空文本輸入框
self.sendInfoTF.text = @""; } ===================================================================================================================== 知識點 十5、XMPP 10.xmpp:基於xml的即時通信協議 (主要用於聊天) 經過一個框架進行操做 0.找到第三方框架 iphone XMPP 1.把第三方框架中的一個.h文件和六個文件夾拖到本身的工程中 2.此時編譯會出現1個錯,百度解決 Build Settings—>Search Paths—>Header Search Paths—>點開後增長一行/usr/include/libxml2  3.把xmpp項目中用到的5個黃色工具箱和三個白色的文件拖到本身的工程中 (拖拽時必定不要勾選copy,刪除的時候選擇第二個Remove Reference,刪的只是引用) 知識點: 1.base64編碼 把data轉成string //將照片轉換爲data
NSData *imageData = nil; if ([imageURL hasSuffix:@"JPG"]) { imageData = UIImageJPEGRepresentation(image, 1); }else{//png
imageData = UIImagePNGRepresentation(image); } NSString *imageString = [imageData base64EncodedStringWithOptions:0]; 2. base64編碼 把string轉成data NSData *imageData = [[NSData alloc]initWithBase64EncodedString:imageString options:0]; day21XMLL (放送文本,圖片,音頻) //封裝XMLL類
XMPPManager.h #import <Foundation/Foundation.h>
#import "XMPPFramework.h"
@interface XMPPManager : NSObject @property (nonatomic, strong)XMPPStream *xmppStream; @property (nonatomic, copy)NSString *password; //單例1.聲明一個獲取對象的靜態方法
+(XMPPManager *)shareManager; -(void)initXMPPWithUserName:(NSString *)name andPassword:(NSString *)pw; -(XMPPMessage *)sendMessageWithType:(NSString *)type andToName:(NSString *)toName andBody:(NSString *)body; @end XMPPManager.m #import "XMPPFramework.h"
#import "XMPPManager.h"
//2.聲明一個靜態的變量
static XMPPManager *_manager; @implementation XMPPManager //建立實例對象
+(XMPPManager *)shareManager{ if (!_manager) { _manager = [[XMPPManager alloc]init]; } return _manager; } //我的用戶登錄
-(void)initXMPPWithUserName:(NSString *)name andPassword:(NSString *)pw{ self.password = pw; self.xmppStream = [[XMPPStream alloc]init]; // 設置delegate
[self.xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()]; // 設置服務器地址 // 172.60.5.100 124.207.192.18
[self.xmppStream setHostName:@"172.60.5.100"]; // 設置端口
[self.xmppStream setHostPort:5222]; // 設置當前用戶
NSString *jidString = [NSString stringWithFormat:@"%@@tarena.com",name]; XMPPJID *jid = [XMPPJID jidWithString:jidString]; [self.xmppStream setMyJID:jid]; // 鏈接服務器
[self.xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:nil]; } //向對方發送消息
-(XMPPMessage *)sendMessageWithType:(NSString *)type andToName:(NSString *)toName andBody:(NSString *)body{ XMPPMessage *message = [XMPPMessage messageWithType:type to:[XMPPJID jidWithString:[NSString stringWithFormat:@"%@@tarena.com",toName]]]; [message addBody:body]; [self.xmppStream sendElement:message]; return message; } -(void)xmppStreamDidConnect:(XMPPStream *)sender{ NSLog(@"已經鏈接"); //登陸受權
[self.xmppStream authenticateWithPassword:self.password error:nil]; } -(void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error{ NSLog(@"斷開鏈接"); } -(void)xmppStreamDidAuthenticate:(XMPPStream *)sender{ NSLog(@"登陸成功"); //通知服務器登陸狀態
[self.xmppStream sendElement:[XMPPPresence presence]]; } -(void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message{ NSLog(@"%@說%@",message.fromStr,message.body); //經過通知把消息傳遞出去
[[NSNotificationCenter defaultCenter]postNotificationName:@"receiveMessage" object:nil userInfo:@{@"message": message}]; } -(void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error{ NSLog(@"登陸失敗"); //註冊
[self.xmppStream registerWithPassword:self.password error:nil]; } -(void)xmppStreamDidRegister:(XMPPStream *)sender{ NSLog(@"註冊成功!"); [self.xmppStream authenticateWithPassword:self.password error:nil]; } -(void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error{ NSLog(@"註冊失敗"); } @end 已經鏈接 登陸失敗 註冊成功! 登陸成功 (第一次登錄) 已經鏈接 登陸成功 ViewController.h ViewController.m #import "ViewController.h"
#import "XMPPManager.h"
#import <AVFoundation/AVFoundation.h>
@interface ViewController ()<UITableViewDelegate,UITableViewDataSource,UIImagePickerControllerDelegate,UINavigationControllerDelegate> @property (weak, nonatomic) IBOutlet UITableView *tableView; @property (nonatomic, strong)AVAudioPlayer *player; @property (weak, nonatomic) IBOutlet UITextField *sendInfoTF; @property (weak, nonatomic) IBOutlet UITextField *toNameTF; @property (nonatomic, strong)NSMutableArray *messages; @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.messages = [NSMutableArray array]; [[XMPPManager shareManager]initXMPPWithUserName:@"1412liuguobin" andPassword:@"aaaaaaaa"]; //監聽接收到的消息
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(didReceiveMessage:) name:@"receiveMessage" object:nil]; //監聽錄音完成的通知
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(recordfinish:) name:@"recordfinish" object:nil]; } -(void)recordfinish:(NSNotification *)noti{ NSString *audioString = [noti.userInfo objectForKey:@"audioString"]; XMPPMessage *message = [[XMPPManager shareManager]sendMessageWithType:@"audio" andToName:self.toNameTF.text andBody:audioString]; [self.messages addObject:message]; [self.tableView reloadData]; } -(void)didReceiveMessage:(NSNotification *)noti{ XMPPMessage *message = [noti.userInfo objectForKey:@"message"]; [self.messages addObject:message]; [self.tableView reloadData]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return self.messages.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; XMPPMessage *message = self.messages[indexPath.row]; NSString *name = [[message.fromStr componentsSeparatedByString:@"@"]firstObject]; if (!message.fromStr) { name = @"我"; } if ([message.type isEqualToString:@"text"]) { cell.textLabel.text = [NSString stringWithFormat:@"%@說:%@",name,message.body]; }else if ([message.type isEqualToString:@"image"]) { cell.textLabel.text = [NSString stringWithFormat:@"%@的圖片信息",name]; }else if ([message.type isEqualToString:@"audio"]) { cell.textLabel.text = [NSString stringWithFormat:@"%@的音頻",name]; } return cell; } -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ XMPPMessage *message = self.messages[indexPath.row]; if ([message.type isEqualToString:@"image"]) { NSString *imageString = message.body; NSData *imageData = [[NSData alloc]initWithBase64EncodedString:imageString options:0]; UIImage *image = [UIImage imageWithData:imageData]; UIViewController *vc = [[UIViewController alloc]init]; UIImageView *iv = [[UIImageView alloc]initWithFrame:vc.view.bounds]; iv.image = image; [vc.view addSubview:iv]; [self.navigationController pushViewController:vc animated:YES]; }else if ([message.type isEqualToString:@"audio"]) { NSString *audioString = message.body; NSData *audioData = [[NSData alloc]initWithBase64EncodedString:audioString options:0]; self.player = [[AVAudioPlayer alloc]initWithData:audioData error:nil]; [self.player play]; } } - (IBAction)clicked:(id)sender { UIButton *btn = sender; if (btn.tag==0) { XMPPMessage *message = [[XMPPManager shareManager]sendMessageWithType:@"text" andToName:self.toNameTF.text andBody:self.sendInfoTF.text]; [self.messages addObject:message]; [self.tableView reloadData]; }else{ UIImagePickerController *ipc = [[UIImagePickerController alloc]init]; ipc.delegate = self; ipc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; [self presentViewController:ipc animated:YES completion:nil]; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.
} - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{ UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage]; NSString *imageURL = [[info objectForKey:UIImagePickerControllerReferenceURL]description]; NSData *imageData = nil; if ([imageURL hasSuffix:@"JPG"]) { imageData = UIImageJPEGRepresentation(image, 1); }else{//png
imageData = UIImagePNGRepresentation(image); } NSLog(@"%@",info); // base64編碼 把data轉成string
NSString *imageString = [imageData base64EncodedStringWithOptions:0]; XMPPMessage *message = [[XMPPManager shareManager]sendMessageWithType:@"image" andToName:self.toNameTF.text andBody:imageString]; [self.messages addObject:message]; [self.tableView reloadData]; [self dismissViewControllerAnimated:YES completion:nil]; } @end
================================================================================ 亂亂的知識點 1.國際化 i18n (internationalization ) 設置了之後,若是當模擬器修改語言之後,故事板中的控件顯示的文本就會跟着修改 1. 在故事板中建立的按鈕,修改顯示語言 先添加按鈕—>在故事板中增長語言: 根目錄—>左上角三角—>Project—>Localization—>增長語言—>修改按鈕上想要顯示的文字樣式 如:」gMY-9U-YVd.normalTitle" = "按鈕";
  2.在類中用代碼建立的控件,修改語言 a.在控制器中建立好控件—>新建類OS X—>Resource—>Strings File—>名字必須是Localizable—>完成 b.建立好之後—>在文件中輸入:」hello"="hello」;鍵值對—>右側邊欄添加語言—>點擊修改便可   - (void)viewDidLoad { [super viewDidLoad]; UILabel *l = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 100, 100)]; l.text = NSLocalizedString(@"hello", @"這是個你好的意思」);//此處的hello是個key值 [self.view addSubview:l]; } 3.根據不一樣的語言環境,項目的名稱能夠跟着改變 Supporting Files—>InfoPlist.strings—>本身寫CFBundleDisplayName=「小圖標名稱」;  2.本地通知 UILocalNotification 功能當用戶退出程序後,每過3秒界面上拉框會提示,而後點擊提示還會切換到此程序,還能夠進行傳值 (提升用戶和程序的粘合度 ) - (void)viewDidLoad { [super viewDidLoad]; UILocalNotification *noti = [[UILocalNotification alloc]init]; noti.fireDate = [[NSDate new] dateByAddingTimeInterval:5]; [noti setRepeatInterval:NSCalendarUnitMinute]; noti.alertBody = @"大爺 很久沒來玩兒了";
//傳遞參數
noti.userInfo = @{@"name": @"小麗"}; // 圖標上面的數量
noti.applicationIconBadgeNumber = 3; [[UIApplication sharedApplication]scheduleLocalNotification:noti]; } //顯示傳遞過來的參數
AppDelegate.h AppDelegate.m -(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{ NSString *name = [notification.userInfo objectForKey:@"name"]; NSLog(@"%@",name); 小麗 }  練習:點擊直接到達新浪或微博頁面 AppDelegate.h AppDelegate.m -(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{ //刪除全部的通知
[[UIApplication sharedApplication]cancelAllLocalNotifications]; // 把程序圖標上面的數去掉
[[UIApplication sharedApplication]setApplicationIconBadgeNumber:0]; [[NSNotificationCenter defaultCenter]postNotificationName:@"backAction" object:nil userInfo:notification.userInfo]; } ViewController.h ViewController.m #import "ViewController.h"
@interface ViewController () @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(bacAction:) name:@"backAction" object:nil]; } -(void)bacAction:(NSNotification *)noti{ NSString *name = [noti.userInfo objectForKey:@"name"]; NSString *path = @"http://www.baidu.com"; if ([name isEqualToString:@"新浪"]) { path = @"http://www.sina.com.cn"; }else if ([name isEqualToString:@"騰訊"]){ path = @"http://www.qq.com"; } UIViewController *vc = [[UIViewController alloc]init]; UIWebView *webView = [[UIWebView alloc]initWithFrame:self.view.bounds]; [webView loadRequest:[NSMutableURLRequest requestWithURL:[NSURL URLWithString:path]]]; [vc.view addSubview:webView]; [self.navigationController pushViewController:vc animated:YES]; } - (IBAction)clicked:(UIButton *)sender { UILocalNotification *noti = [[UILocalNotification alloc]init]; noti.fireDate = [[NSDate new] dateByAddingTimeInterval:5]; [noti setRepeatInterval:NSCalendarUnitMinute]; NSString *title = [sender titleForState:UIControlStateNormal]; noti.alertBody =[NSString stringWithFormat: @"大爺 很久沒來玩兒了 %@",title]; //傳遞參數
noti.userInfo = @{@"name": title}; // 圖標上面的數量
noti.applicationIconBadgeNumber = 5; [[UIApplication sharedApplication]scheduleLocalNotification:noti]; } @end    3.重力傳感器 CMMotionManager 只有在真機上才能調試,模擬器不能夠 #import "ViewController.h"
#import <CoreMotion/CoreMotion.h> //導入框架
@interface ViewController () @property (weak, nonatomic) IBOutlet UIButton *myBall;//界面上的按鈕,假設爲球
@property (nonatomic, strong)CMMotionManager *manager; @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.manager = [[CMMotionManager alloc]init]; //設置更新頻率
[self.manager setAccelerometerUpdateInterval:1.0/60]; //開始更新
[self.manager startAccelerometerUpdates]; [NSTimer scheduledTimerWithTimeInterval:1.0/60 target:self selector:@selector(getInfo) userInfo:nil repeats:YES]; } -(void)getInfo{ //獲取手機的x,y,z值
CMAcceleration acc = self.manager.accelerometerData.acceleration; //球跟着值改變
self.myBall.center = CGPointMake(self.myBall.center.x+acc.x, self.myBall.center.y-acc.y); //x表明左右,y表明上下搖動,z表明側面 // NSLog(@"x=%lf y=%lf z=%lf",acc.x,acc.y,acc.z);隨之手機的晃動值會改變
} -(void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event{ NSLog(@"開始搖了"); } -(void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event{ NSLog(@"搖完了"); } -(void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event{ NSLog(@"之外中斷了"); } @end
4.GPS (陀螺儀)CLLocationManager #import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
@interface ViewController ()<CLLocationManagerDelegate> @property (nonatomic, strong)CLLocationManager *manager; @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // 詢問是否開啓了位置服務
if ([CLLocationManager locationServicesEnabled]) { self.manager = [[CLLocationManager alloc]init]; // 設置精度
[self.manager setDesiredAccuracy:kCLLocationAccuracyBest]; // 設置更新距離 距離越小越精準 越費電
[self.manager setDistanceFilter:20]; self.manager.delegate = self; //開始更新經緯度
[self.manager startUpdatingLocation]; //獲取方向 陀螺儀的值
[self.manager startUpdatingHeading]; } } - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{ CLLocationCoordinate2D coord = newLocation.coordinate; NSLog(@"經度:%lf 維度:%lf",coord.longitude,coord.latitude); } //獲取陀螺儀的值
-(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading{ NSLog(@"角度:%f",newHeading.trueHeading); } @end 真機調試: $99 我的 公司:能夠分配權限(多人使用) 可上線AppStore 只容許100臺設備 $299 大企業 公司內部使用 不限制設備數量 Certificates:證書列表 建立證書時須要用到當前mac電腦的信息 建立出來的證書 只能供當前電腦使用 在當前電腦上導出的證書就能夠應用到別的電腦上了 網上下載的證書格式是cer 導出的是p12 只有p12的才能在別的電腦上使用
Identifiers:標示 限制應用的公司名稱 通常給一個* 不作限制
Devices:設備列表 顯示已經和帳號綁定的設備
Provisioning Profiles:描述文件 會在手機上面和電腦上面都安裝 之後每次 調試 不須要聯網也能夠 和真機相關的知識點: 1.GPS定位 2.重力感應 3.陀螺儀