H:/0730/00_多線程4種售票_ViewController.h//
// ViewController.h
// 賣票
//
// Created by apple on 13-7-29.
// Copyright (c) 2013年 itcast. All rights reserved.
//
#import
@interface ViewController : UIViewController
// 多行文本提示框
@property (weak, nonatomic) IBOutlet UITextView *infoTextView;
// NSThread售票
- (IBAction)threadSales:(id)sender;
// NSInvocationOperation售票
- (IBAction)invocationSales:(id)sender;
// NSBlockOperation售票
- (IBAction)blockSales:(id)sender;
// GCD售票
- (IBAction)gcdSales:(id)sender;
@end
H:/0730/00_多線程4種售票_ViewController.m
// ViewController.m
// 賣票
// Created by apple on 13-7-29.
#import "ViewController.h"
@interface ViewController ()
{
NSInteger _tickets;
// 線程鎖NSLock,必須是成員變量,不能是局部變量
NSLock *_lock;
}
// 下面的atomic成員,結合同步代碼塊使用,@synchronized (self) {}
@property (assign, atomic) NSInteger tickets;
/*
1. 在做多線程NSOperation和GCD技術的時候,搶奪的內存資源必須是“原子屬性”——atomic
2. 搶奪的資源在使用的時候,
//一定要用屬性的self.xxx或者object.xxx,這樣才getter,才atomic發揮作用
3. 要在Operation和GCD中搶奪資源,需要使用到“同步鎖”,@synchronized(self){...}
//目的是,鎖住與搶奪資源相關的代碼,包括讀和寫
4. 平時,盡量不要用搶奪資源去做判斷條件,並且同步鎖的范圍越小越好!
*/
@end
@implementation ViewController
/*
// 同步鎖是要手敲出來的
@synchronized (self) {
}
*/
// 為了在TextView裡面增加文本,更新界面,需要先寫一個方法處理。
// 1. 讀出當前文本框的內容
// 2. 把要追加的文本附加在當前文本框內容的後面
// 3. 重新為文本框賦值
// 這是負責更新界面的UI
- (void)appendTextView:(NSString *)text
{
NSMutableString *str = [NSMutableString stringWithString:_infoTextView.text];
[str appendFormat:@"\n%@", text];
[_infoTextView setText:str];
// 定義一個NSRange,代表文本框需要滾動到的位置
NSRange range = NSMakeRange(str.length, 1);
// 我們現在想要滾動到最後,這個方法的參數是一個NSRange
[_infoTextView scrollRangeToVisible:range];
}
// 多線程一:響應按鈕點擊,啟動NSThread售票
- (IBAction)threadSales:(id)sender
{
_tickets = 100;
// 創建線程 NSThread1
NSThread *thread1 = [[NSThread alloc]initWithTarget:self
selector:@selector(threadSaleMethod) object:nil];
// 設置線程1的名字
[thread1 setName:@"售票線程-1"];
// 啟動線程 NSThread1 只有NSThread需要手動start
[thread1 start];
// 創建線程 NSThread2
NSThread *thread2 = [[NSThread alloc]initWithTarget:self
selector:@selector(threadSaleMethod) object:nil];
// 設置線程2的名字
[thread2 setName:@"售票線程-2"];
// 啟動線程 NSThread2 只有NSThread需要手動start
[thread2 start];
}
// 多線程一:實際NSThread售票運行的代碼,線程跑的方法
#pragma mark - 自定義方法,NSThread售票核心代碼
- (void)threadSaleMethod
{
// 1. 判斷是否還有票
// 2. 更新界面,提示當前票數
// 3. 總票數-1
// 4. 模擬延時
// 要解決一個問題:在threadSaleMethod這一個方法裡面,我們就把所有的票賣光!!!
// 線程鎖:所謂線程鎖,就是:在修改或者判斷共享資源的時候,
//需要把共享資源加鎖,防止別的線程對
// 共享資源進行修改。
// 使用線程鎖的方式:
// 1. 定義鎖,懶加載,且鎖必須是成員變量
if (_lock == nil) {
_lock = [[NSLock alloc]init];
}
while (YES) {
// 2. 使用共享資源之前,加鎖
[_lock lock];
if (_tickets > 0) {
// 做了一個字符串,顯示提示信息
NSString *str = [NSString stringWithFormat:@"當前票數是%d,售票線程是%@", _tickets, [[NSThread currentThread]name]];
// 主線程,UI界面中顯示一下票數
// 在多線程方法裡面不能這樣使用的
// [self appendTextView:@"12"];
// waitUntilDone 的意思是:是否等待主線程更新完畢
[self performSelectorOnMainThread:@selector(appendTextView:)
withObject:str waitUntilDone:YES];
// 售完一張,票數減1
_tickets--;
// 3. 使用共享資源完畢,立即解鎖
[_lock unlock];
// 模擬不同售票效率
if ([[[NSThread currentThread]name] isEqualToString:@"售票線程-1"]) {
[NSThread sleepForTimeInterval:0.2];
} else {
[NSThread sleepForTimeInterval:0.3];
}
} else {
// 3. 使用共享資源完畢,立即解鎖
[_lock unlock];
// 結束時,打印下線程名
NSString *str = [NSString stringWithFormat:@"票已售完%@",
[[NSThread currentThread]name]];
// 主線程,UI界面中顯示一下哪個線程結束了
[self performSelectorOnMainThread:@selector(appendTextView:)
withObject:str waitUntilDone:YES];
NSLog(@"%@", str);
// 退出循環
break;
}
}
}
// 多線程二:響應按鈕點擊,通過NSInvocationOperation添加到NSOperationQueue售票
- (IBAction)invocationSales:(id)sender
{
_tickets = 20;
// 1. 定義2個NSInvocationOperation操作
// 1.1. 操作需要調用一個target對象的selector方法,類似NSThread
// 1.2. 第3個參數object代表:方法是可以接收參數的,且只能接收一個。
NSInvocationOperation *operation1 = [[NSInvocationOperation alloc]initWithTarget:self
selector:@selector(operationSaleMethod:) object:@"Operation - 1"];
NSInvocationOperation *operation2 = [[NSInvocationOperation alloc]initWithTarget:self
selector:@selector(operationSaleMethod:) object:@"Operation - 2"];
// 2. 定義1個操作隊列NSOperationQueue
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
// 3. 將2個操作逐一添加到操作隊列,自動啟動
[queue addOperation:operation1];
[queue addOperation:operation2];
}
// 多線程二:通過NSInvocationOperation添加到NSOperationQueue售票運行的代碼,線程跑的方法
// 同樣也是多線程三:通過NSOperationQueue的block售票的核心代碼,線程跑的方法
#pragma mark - NSOperation售票,使用@synchronized(self){}
// NSOperation售票方法,參數是上面方法定義的操作名稱
- (void)operationSaleMethod:(NSString *)operationName
{
// 賣票流程——在這一個方法裡面,我們需要把所有的票賣光!!!
// 1. 是否有票
// 2. 顯示當前票數
// 3. 票數-1
// 4. 通過延時,模擬效率
while (YES) {
// !!!同步鎖要鎖住所有搶奪資源的代碼
// 平時,盡量不要用搶奪的資源做判斷條件,會增加同步鎖的范圍,降低效率!
@synchronized(self) {
if (self.tickets > 0) {
NSString *str = [NSString stringWithFormat:@"當前票數:%d,線程名稱:%@",
self.tickets, operationName];
// 主線程隊列“只”負責更新UI
// 把所有的成員變量調用的位置都改成了getter方式調用,發揮atomic關鍵字
// 屬性調用是通過getter,這樣調用才能發揮atomic的作用
[[NSOperationQueue mainQueue]addOperationWithBlock:^{
// 在NSOperationQueue的主隊列中,只負責更新界面UI
[self appendTextView:str];
}];
self.tickets--;
// 通過延時,模擬不同售票效率
if ([operationName isEqualToString:@"Operation - 1"] ||
[operationName isEqualToString:@"Block - 1"]) {
[NSThread sleepForTimeInterval:0.2];
} else {
[NSThread sleepForTimeInterval:1.0];
}
} else {
NSString *str = [NSString stringWithFormat:@"票已售完,線程名稱:%@",
operationName];
// 在NSOperationQueue的主隊列中,只負責更新界面UI
[[NSOperationQueue mainQueue]addOperationWithBlock:^{
[self appendTextView:str];
}];
break;
}
}//同步代碼塊@synchronized,到這兒才結束
}
}
// 多線程三:響應按鈕點擊,通過NSOperationQueue的block售票
- (IBAction)blockSales:(id)sender
{
_tickets = 20;
// 1,定義NSOperationQueue操作隊列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
// 2,通過block給操作隊列添加自定義方法,並執行
[queue addOperationWithBlock:^{
[self operationSaleMethod:@"Block - 1"];
}];
// 2,通過block給操作隊列添加自定義方法,並執行
[queue addOperationWithBlock:^{
[self operationSaleMethod:@"Block - 2"];
}];
// 2,通過block給操作隊列添加自定義方法,並執行
[queue addOperationWithBlock:^{
[self operationSaleMethod:@"Block - 3"];
}];
// 3,設置NSOperationQueue操作隊列,最大並發執行任務個數
[queue setMaxConcurrentOperationCount:2];
}
// 多線程四:響應按鈕點擊,通過GCD grand central dispatch售票
- (IBAction)gcdSales:(id)sender
{
_tickets = 20;
// 1. 獲取全局隊列 dispatch_get_global_queue,參數1為默認優先級,
// 參數2標記永遠是0
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 2. 創建小組 dispatch_group_create
dispatch_group_t group = dispatch_group_create();
// 3. 向小組添加異步任務一,dispatch_group_async
// 參數1,小組名
// 參數2,全局隊列名
// 參數3,block,即指定具體要執行的方法,可帶參數:名字
dispatch_group_async(group, queue, ^{
[self gcdSaleMethod:@"GCD-1"];
});
// 3. 向小組添加異步任務二,dispatch_group_async
// 參數1,小組名
// 參數2,全局隊列名
// 參數3,block,即指定具體要執行的方法,可帶參數,名字
dispatch_group_async(group, queue, ^{
[self gcdSaleMethod:@"GCD-2"];
});
// 4. 監聽小組通知
// 參數1,小組名
// 參數2,獲得主隊列 dispatch_get_main_queue()
// 參數3,block代碼塊:所有異步任務都完成時,要做的事情!!!
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 提示用戶沒有票了!更新到界面UI
[self appendTextView:@"票已售完!"];
});
}
// 多線程四:通過GCD向小組添加的異步任務,即線程跑的方法
#pragma mark - GCD售票 具體賣票流程
- (void)gcdSaleMethod:(NSString *)gcdName
{
// 1. 確認票數
// 2. 更新界面
// 3. 票數-1
// 4. 模擬延時
while (YES) {
if (_tickets > 0) {
// 1. 確定要更新的內容
NSString *str = [NSString stringWithFormat:@"當前票數:%d, 售票線程:%@",
_tickets, gcdName];
// 2. dispatch_async(),開啟異步任務,
// 參數1,要在哪個地方執行該異步任務:dispatch_get_main_queue()
// 參數2,block指明要執行的具體異步任務:更新UI界面,並且票數-1
dispatch_async(dispatch_get_main_queue(), ^{
[self appendTextView:str];
// GCD中 對共用資源的修改也要放到獲得的主隊列裡
_tickets--;
});
// 通過延時,模擬不同售票效率
if ([gcdName isEqualToString:@"GCD-1"]) {
[NSThread sleepForTimeInterval:0.2];
} else {
[NSThread sleepForTimeInterval:1.0];
}
} else {
break;
}
}
}
@end
H:/0730/01_ASI_ViewController.h// ViewController.h
// ASI演練
// Created by apple on 13-7-30.
// Copyright (c) 2013年 itcast. All rights reserved.
#import
#import "ASIHTTPRequest.h"
@interface ViewController : UIViewController
// 響應按鈕點擊,下載文件
- (IBAction)downloadFile:(id)sender;
@end
H:/0730/01_ASI_ViewController.m// ViewController.m
// ASI演練
/*
ASI工程注意事項:
1,不能選ARC
2,更改IOS 部署 目標為 IOS5.0
3,將ASI壓縮包,解壓,拖動Classes文件夾和External目錄拖進工程
4,嘗試編譯,出現錯誤:無法找到libxml/HTMLparser.h
解決方法:
進入build settings,找到_head search paths頭文件搜索目錄_添加:
${SDK_DIR}/usr/include/libxml2,並回車
5,再次嘗試編譯,出現錯誤:ASITestCase.h:12:9: 'GHUnitIOS/GHUnit.h' file not found
錯誤原因:沒有GHUnit框架
解決辦法:
進入build phases
展開compile sources
將tests結尾的文件全部移除,按減號,即測試文件,不參與編譯
即刪除單元測試部分的代碼引用
6,再次command B 編譯,85個錯誤
解決方法:
很簡單,進入summary,找到鏈接的框架和引用,+號,添加下列iOS框架引用即可
CFNetwork.framework
SystemConfiguration.framework
MobileCoreServices.framework
libz.dylib
libxml2.dylib
7,上述框架,在ASI提供的工程樣本中可以看到,再次編譯OK
8,為了解壓縮,還要添加SSZipArchive框架
將以下文件加入工程:
SSZipArchive.h
SSZipArchive.m
minizip文件夾
9,編譯OK
*/
// Created by apple on 13-7-30.
// Copyright (c) 2013年 itcast. All rights reserved.
#import "ViewController.h"
#import "SSZipArchive.h"
// 遵守兩個ASI協議
@interface ViewController ()
{
// 下載文件的大小,頭信息字典中的文件長度,在後面進度中要用到
CGFloat _fileLength;
}
@end
@implementation ViewController
#pragma mark - 響應按鈕點擊,開始啟動ASI框架斷點續傳下載文件
- (IBAction)downloadFile:(id)sender
{
// 1. 指定下載文件地址
NSString *urlString = @"http://teacher.local/~apple/itcast/download/iTunesConnect_DeveloperGuide_CN.zip";
NSURL *url = [NSURL URLWithString:urlString];
// 2. 設定文件保存路徑及臨時緩存路徑
NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
//保存路徑
NSString *downloadPath = [documents[0]stringByAppendingPathComponent:@"book.zip"];
//緩存路徑
NSString *tempPath = [documents[0]stringByAppendingPathComponent:@"book.tmp"];
// 3. 通過URL,初始化ASIHTTPRequest實例對象,不支持ARC
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc]initWithURL:url]autorelease];
// 4. 設置代理為當前控制器——ASI是通過代理回調的方式處理網絡請求的
[request setDelegate:self];
// 5. 設置下載完畢的保存路徑
[request setDownloadDestinationPath:downloadPath];
// 6. 設置臨時緩存路徑
[request setTemporaryFileDownloadPath:tempPath];
// 7. 設置允許斷點續傳
[request setAllowResumeForFileDownloads:YES];
// 8. 設置下載進程代理——用戶想知道下載的實際進展情況
[request setDownloadProgressDelegate:self];
// 9. 啟動異步請求
[request start];
}
#pragma mark - ASI代理方法
// 2. 接收到響應頭 didReceiveResponseHeaders 目的獲得文件長度
- (void)request:(ASIHTTPRequest *)request didReceiveResponseHeaders:(NSDictionary *)responseHeaders
{
// 通過Log,我們看到了"Content-Length" = 6105204;
// 貌似可以用來監控下載進度
// 暫時不去管它
NSLog(@"請求頭%@", responseHeaders);
// 在這裡,我們能夠知道文件長度,如果我們在這裡記錄下來文件的長度,假設100M
// 需要獲得的是文件的兆數會更加人性化 字節->K->M(1024)
NSInteger length = [responseHeaders[@"Content-Length"]integerValue];
// 文件長度計算之後,是一個小數,需要改變一下成員變量的類型
_fileLength = (CGFloat)length / 1024 / 1024;
}
#pragma mark - 下載進度的代理方法
- (void)setProgress:(float)newProgress
{
// 傳回來的參數是一個下載進度的百分比
// 那麼,我們告訴用戶還差多少M下載完成?
NSLog(@"%.2f", newProgress * _fileLength);
// 100M * 0.2 = 20M
}
#pragma mark - ASI代理方法
// 3. 請求完成 requestFinished
- (void)requestFinished:(ASIHTTPRequest *)request
{
NSLog(@"請求完成");
// 我們可以去做解壓縮的工作了。因為下載工作已經完成了!
// 需求:
// 1. 知道文件保存路徑
// 2. 解壓縮文件
// 2.1 定義一個壓縮文件
NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *downloadPath = [documents[0]stringByAppendingPathComponent:@"book.zip"];
// 2.3 調用SSZipArchive的類方法解壓縮,參數2是一個目錄
[SSZipArchive unzipFileAtPath:downloadPath toDestination:documents[0]];
// 3. 通過文件管理者(單例),刪除壓縮文件
[[NSFileManager defaultManager]removeItemAtPath:downloadPath error:nil];
}
#pragma mark - ASI代理方法
// 代理方法之1. 請求開始
- (void)requestStarted:(ASIHTTPRequest *)request
{
NSLog(@"請求開始");
}
#pragma mark - ASI代理方法
// 代理方法之4. 請求失敗
- (void)requestFailed:(ASIHTTPRequest *)request
{
NSLog(@"請求失敗");
}
@end
H:/0730/02_AFN_ViewController.h//
// ViewController.h
// AFN斷點續傳演練
//
// Created by apple on 13-7-30.
// Copyright (c) 2013年 itcast. All rights reserved.
//
#import
@interface ViewController : UIViewController
// 下載文件
- (IBAction)downloadFiles:(id)sender;
@end
H:/0730/02_AFN_ViewController.m// ViewController.m
// AFN斷點續傳演練
// Created by apple on 13-7-30.
// Copyright (c) 2013年 itcast. All rights reserved.
/*
AFN使用步驟:
1,新建工程的時候,勾選ARC(畢竟AFN有是人在維護的)
2,拖動文件夾AFNetworking到工程中
3,將解壓要用到的文件夾SSZipArchive拖到工程中
同時導入它依賴的libz.dylib框架
4,編譯,彈出2個warning,缺少框架
SystemConfiguration.framework
MobileCoreServices.framework
5,展開supporting files文件夾,找到-->
工程名-Prefix.pch文件,在#endif的前面添加
#import
#import
6,再次編譯ok
*/
#import "ViewController.h"
#import "AFNetworking.h"
#import "SSZipArchive.h"
@interface ViewController ()
@end
@implementation ViewController
#pragma mark - 下載文件
- (IBAction)downloadFiles:(id)sender
{
// 1. 指定下載文件地址
NSURL *url = [NSURL URLWithString:@"http://169.254.98.245/~apple/itcast/download/iTunesConnect_DeveloperGuide_CN.zip"];
// 2. 指定文件保存路徑
NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *downloadPath = [documents[0]stringByAppendingPathComponent:@"book.zip"];
// 3. 創建NSURLRequest
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 4. 通過固定請求,創建AFURLConnectionOperation,多態
AFURLConnectionOperation *operation = [[AFHTTPRequestOperation alloc]
initWithRequest:request];
// 5. 設置操作的輸出流(在網絡中的數據是以流的方式傳輸的,
//告訴操作把文件保存在第2步設置的路徑中)
[operation setOutputStream:[NSOutputStream
outputStreamToFileAtPath:downloadPath append:NO]];
// 6. 設置下載進程處理塊代碼
// 6.1 bytesRead 讀取的字節——這一次下載的字節數
// 6.2 totalBytesRead 讀取的總字節——已經下載完的
// 6.3 totalBytesExpectedToRead 希望讀取的總字節——就是文件的總大小
[operation setDownloadProgressBlock:^(NSUInteger bytesRead,
long long totalBytesRead, long long totalBytesExpectedToRead) {
// 做下載進度百分比的工作
NSLog(@"下載百分比:%f", (float)totalBytesRead / totalBytesExpectedToRead);
}];
// 7. 操作完成塊代碼
[operation setCompletionBlock:^{
// 解壓縮的順序
// 1. 定義要解壓縮的文件 —— downloadPath
// 2. 要解壓縮的目標目錄,必須是目錄
// 3. 調用類方法解壓縮
[SSZipArchive unzipFileAtPath:downloadPath toDestination:documents[0]];
// 使用文件管理者,刪除壓縮包
[[NSFileManager defaultManager]removeItemAtPath:downloadPath error:nil];
}];
// 8 啟動操作
[operation start];
}
@end
H:/0730/04_UIWebView_ViewController.h//
// ViewController.h
// UIWebView演練
//
// Created by apple on 13-7-30.
// Copyright (c) 2013年 itcast. All rights reserved.
//
#import
@interface ViewController : UIViewController
// 成員屬性:UIWebView控件
@property (weak, nonatomic) IBOutlet UIWebView *localWebView;
// 點擊,加載PDF文件按鈕
- (IBAction)clickPDFButton:(id)sender;
// 點擊,加載HTMLString
- (IBAction)loadHTMLString:(id)sender;
// 點擊,使用loadData加載數據
- (IBAction)loadData:(id)sender;
@end
H:/0730/04_UIWebView_ViewController.m// ViewController.m
// UIWebView演練
// Created by apple on 13-7-30.
// Copyright (c) 2013年 itcast. All rights reserved.
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// 通過自定義方法獲得MIMETYPE
[self mimeType];
}
// 自定義方法,獲取MIMEType
// 因為我們不能記住所有類型文檔的MIMEType,所以我們自己動手,寫一個方法
- (NSString *)mimeType
{
// 一。本地文件URL生成的過程
// 1. 絕對路徑
NSString *path = [[NSBundle mainBundle]pathForResource:@"關於.docx" ofType:nil];
// 2 絕對路徑轉FILEURL
NSURL *fileURL = [NSURL fileURLWithPath:path];
// 二。網絡文件URL生成的過程
// 1. 網絡地址字符串
NSString *urlString = @"http://www.baidu.com";
// 2. 生成URL
NSURL *webURL = [NSURL URLWithString:urlString];
// 1. 定義固定請求
NSURLRequest *request = [NSURLRequest requestWithURL:fileURL];
// 2. 定義響應,到時候,傳入地址,到時候方便接收返回的response
NSURLResponse *response = nil;
// 3. NSConnection靜態方法,發送同步請求,傳入接收響應的地址
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
NSLog(@"MIMEType %@", response.MIMEType);
return response.MIMEType;
}
// 響應按鈕點擊事件,
- (IBAction)clickPDFButton:(id)sender
{
[self viewLocalPDFFile];
}
// 1. 我們現在准備了一個素材是PDF
// 2. 我們要把這個PDF顯示在webView裡面
// 顯示本地PDF文件在WebView
- (void)viewLocalPDFFile
{
// 1. 定義URL
// 1. 全路徑
NSString *path = [[NSBundle mainBundle]pathForResource:@"iTunesConnect_DeveloperGuide_CN.pdf" ofType:nil];
// 2 全路徑得到fileURL
NSURL *fileURL = [NSURL fileURLWithPath:path];
// 2. 通過fileURL構建請求
NSURLRequest *request = [NSURLRequest requestWithURL:fileURL];
// 4. 重要!!!!!!設置WebView的數據偵測類型:為偵測所有類型
[_localWebView setDataDetectorTypes:UIDataDetectorTypeAll];
// 5. 使用WebView加載這個請求即可
[_localWebView loadRequest:request];
}
// 響應按鈕點擊,加載HTMLString
- (IBAction)loadHTMLString:(id)sender
{
// 暫時不考慮baseURL,集中在String上面
// 用“iOS 正則表達式”去搜索相關知識點,可以做新聞類的應用!
NSString *fullHTML = @"hello我愛你";
NSString *partHTML = @"我愛你!!!";
// webview是可以顯示部分html代碼的
[_localWebView loadHTMLString:partHTML baseURL:nil];
}
// 響應按鈕點擊,加載“data數據”——NSData
- (IBAction)loadData:(id)sender
{
// 1. pdf文件絕對路徑
NSString *path = [[NSBundle mainBundle]pathForResource:@"iTunesConnect_DeveloperGuide_CN.pdf"
ofType:nil];
// 2 通過 絕對路徑 生成fileURL
NSURL *fileURL = [NSURL fileURLWithPath:path];
// 2. 用NSData類方法加載數據,參數為fileURL
NSData *data = [NSData dataWithContentsOfURL:fileURL];
// 3. 使用webView加載data類型數據
[_localWebView loadData:data MIMEType:@"application/pdf"
textEncodingName:@"UTF-8" baseURL:nil];
}
@end
H:/0730/05_UIWebView浏覽器綜合應用_ViewController.h//
// ViewController.h
// UIWebView Demo
//
// Created by apple on 13-7-21.
// Copyright (c) 2013年 itcast. All rights reserved.
//
#import
@interface ViewController : UIViewController
// URL文本
@property (weak, nonatomic) IBOutlet UITextField *urlText;
// 回退按鈕
@property (weak, nonatomic) IBOutlet UIBarButtonItem *goBackButton;
// 前進按鈕
@property (weak, nonatomic) IBOutlet UIBarButtonItem *goForwardButton;
// 重載按鈕
@property (weak, nonatomic) IBOutlet UIBarButtonItem *reloadButton;
// 停止按鈕
@property (weak, nonatomic) IBOutlet UIBarButtonItem *stopButton;
// Web視圖
@property (weak, nonatomic) IBOutlet UIWebView *webView;
// 回退
- (IBAction)goBack:(id)sender;
// 前進
- (IBAction)goForward:(id)sender;
// 刷新
- (IBAction)reloadURL:(id)sender;
// 提交表單
- (IBAction)submit:(id)sender;
@end
H:/0730/05_UIWebView浏覽器綜合應用_ViewController.m// ViewController.m
// UIWebView 浏覽器綜合演示
// Created by apple on 13-7-21.
// Copyright (c) 2013年 itcast. All rights reserved.
#import "ViewController.h"
@interface ViewController ()
// 訪問指定URL字符串的內容,僅由文本框回車事件調用
- (void)gotoURLString:(NSString *)urlString;
// 訪問指定的URL內容
- (void)gotoURL:(NSURL *)url;
// 獲得本地文件的MIMEType
- (NSString *)MIMEType:(NSString *)fileName;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self MIMEType:@"001.網絡基礎.pdf"];
// 調用自定義測試方法
[self testLoadHTMLFile];
}
// 測試加載本地HTML文件
- (void)testLoadHTMLFile
{
// 測試加載本地HTML文件,需要指定MIMETYPE
NSString *dataPath = [[NSBundle mainBundle]pathForResource:@"demo.html" ofType:nil];
// baseURL基址,以便查找CSS JS jpg等
NSURL *baseURL = [NSURL fileURLWithPath:[[NSBundle mainBundle]resourcePath]
isDirectory:YES];
// 只有加載的html文件才需要指定baseURL路徑,告訴浏覽器去哪裡找圖片、樣式表等文件
[_webView loadData:[NSData dataWithContentsOfFile:dataPath]
MIMEType:@"text/html" textEncodingName:@"UTF-8" baseURL:baseURL];
}
// 自定義方法,獲得本地文件的MIMEType
- (NSString *)MIMEType:(NSString *)fileName
{
// 根據文件名,得到絕對路徑
NSString *path = [[NSBundle mainBundle]pathForResource:fileName ofType:nil];
// 根據絕對路徑,得到fileURL
NSURL *url = [NSURL fileURLWithPath:path];
// 根據url 創建固定請求
NSURLRequest *request = [NSURLRequest requestWithURL: url];
// 定義響應,以便接收響應內容
NSURLResponse *response = nil;
// 發送同步請求,並傳入響應的地址,以便接收響應
[NSURLConnection sendSynchronousRequest:request
returningResponse:&response error:nil];
NSLog(@"MIMEType is %@", [response MIMEType]);
return [response MIMEType];
}
#pragma mark - UIWebView加載內容的測試方法
// 加載HTML字符串
- (void)testLoadHTMLString
{
// 測試加載HTML字符串
NSString *html = @"紅樓夢世外仙姝
";
[_webView loadHTMLString:html baseURL:nil];
}
// 加載部分HTML字符串測試
- (void)testLoadPartHTMLString
{
// 測試加載部分HTML字符串,不需要顯示整個網頁內容時,通常使用此方法
NSString *partHtml = @"寂寞林
";
[_webView loadHTMLString:partHtml baseURL:nil];
}
// 加載本地PDF文件
- (void)testLoadPDFFile
{
// 測試加載本地PDF,需要指定MIMETYPE
NSString *dataPath = [[NSBundle mainBundle]pathForResource:@"001.網絡基礎.pdf" ofType:nil];
[_webView loadData:[NSData dataWithContentsOfFile:dataPath]
MIMEType:@"application/pdf" textEncodingName:@"UTF-8" baseURL:nil];
}
// 加載本地文本文件
- (void)testLoadTextFile
{
// 測試加載本地文本文件,需要指定MIMETYPE
NSString *dataPath = [[NSBundle mainBundle]pathForResource:@"關於.txt" ofType:nil];
[_webView loadData:[NSData dataWithContentsOfFile:dataPath]
MIMEType:@"text/plain" textEncodingName:@"UTF-8" baseURL:nil];
}
#pragma mark - UITextField代理方法
// 文本框回車事件
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
// 如果被回車的是地址欄,且不為空
if (textField == _urlText && textField.text.length > 0) {
// 退出鍵盤
[textField resignFirstResponder];
// 調用自定義方法,轉到URLstring方法
[self gotoURLString:textField.text];
}
return YES;
}
#pragma mark - 自定義方法,回車後,調用訪問指定URL內容
// 訪問指定URL字符串的內容,僅由文本框事件調用,文本框回車時候調用的
- (void)gotoURLString:(NSString *)urlString
{
NSURL *url = nil;
// 判斷是否是httpURL
if ([urlString hasPrefix:@"http://"]) {
// URL中有中文的,是需要加百分號的!
url = [NSURL URLWithString:[urlString
stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
} else if ([urlString hasPrefix:@"file://"]) {
// 判斷給定參數是否已經是完整的url路徑,避免出現前進後退後,
//URL變成完整URL無法訪問的情況
if ([urlString hasPrefix:@"file://localhost/"]) {
// 注意此處不能使用fileURLWithPath方法???????????
// 因為fileURLWithPath是將絕對路徑,轉成fileURL
// 而此時,已經是fileURL了
url = [NSURL URLWithString:urlString];
} else {
// 如果沒有localhost前綴的,說明是新輸入的本地文件,需要轉換url。
// 檢測字串范圍
NSRange range = [urlString rangeOfString:@"file://"];
// 截取剩余部分作為文件名
NSString *fileName = [urlString substringFromIndex:range.length];
// 根據文件名,生成文件絕對路徑
NSString *path = [[NSBundle mainBundle]pathForResource:fileName ofType:nil];
// 判斷絕對路徑是否存在
if ([[NSFileManager defaultManager]fileExistsAtPath:path]) {
// 若存在,將絕對路徑轉成fileURL
url = [NSURL fileURLWithPath:path];
} else {
url = nil;
}
}
}
// 如果到這兒url仍為空,說明,轉換失敗,輸入地址欄內容有誤
if (url == nil) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示"
message:@"輸入地址不正確,請重新輸入!"
delegate:nil
cancelButtonTitle:@"確定"
otherButtonTitles:nil, nil];
[alert show];
// 設置文本框輸入焦點
[_urlText becomeFirstResponder];
} else {
// 地址正確,下一步,調用自定義方法,訪問指定的URL內容
[self gotoURL:url];
}
}
// 地址正確,下一步,調用自定義方法,訪問指定的URL內容
- (void)gotoURL:(NSURL *)url
{
// 使用轉換後的URL字符串替代用戶輸入的URL文本框內容
// absoluteString???
[_urlText setText:[url absoluteString]];
// 1, 根據url 創建固定請求
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 2, 設置浏覽器,自動偵測所有數據類型
[_webView setDataDetectorTypes:UIDataDetectorTypeAll];
// 3, webView 加載請求
[_webView loadRequest:request];
}
// 響應按鈕點擊,JS 提交表單
- (IBAction)submit:(id)sender
{
// 獲取當前頁面的url
NSString *url = [_webView
stringByEvaluatingJavaScriptFromString:@"document.location.href"];
NSLog(@"url %@", url);
// 獲取當前頁面的標題
NSString *title = [_webView
stringByEvaluatingJavaScriptFromString:@"document.title"];
NSLog(@"title %@", title);
// 提交表單
[_webView stringByEvaluatingJavaScriptFromString:@"document.forms[0].submit(); "];
}
#pragma mark - UIWebViewDelegate 代理方法
// 網頁中的每一個請求都會被觸發這個方法,返回NO代表不執行這個請求(常用於JS與iOS之間通訊)
- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType
{
NSLog(@"將要加載請求");
return YES;
}
#pragma mark - IBActions
// 調用浏覽器webView默認的,回退操作
- (IBAction)goBack:(id)sender
{
[_webView goBack];
}
// 調用浏覽器webView默認的,前進操作
- (IBAction)goForward:(id)sender
{
[_webView goForward];
}
// 調用浏覽器webView默認的,刷新操作
- (IBAction)reloadURL:(id)sender
{
[_webView reload];
}
#pragma mark - UIWebViewDelegate 代理方法
// 網頁開始加載的時候調用
- (void)webViewDidStartLoad:(UIWebView *)webView
{
NSLog(@"開始加載");
}
#pragma mark - UIWebViewDelegate 代理方法
// 網頁加載完成的時候調用
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
NSLog(@"加載完成");
}
#pragma mark - UIWebViewDelegate 代理方法
// 網頁加載出錯的時候調用
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
NSLog(@"加載出錯%@", [error localizedDescription]);
}
@end