I os 072. 內容⼤大綱
• UIScrollView
• QV089:圖⽚片捲動
• QV090:圖⽚片捲動⽴立即顯⽰示縮放⽐比例
• Samples:Scrolling
• iOS 之多⼯工與⽣生命週期
• UIApplicationDelegate 的運作
• QV100:⽣生命週期的測試及通知
• Notification 通知
• 應⽤用程式的執⾏行流程
• QV037:Empty + SingleView
• QV038:Empty (未使⽤用rootViewController)
8. ViewController.m (1/2)
- (void)viewDidLoad
{
[super viewDidLoad];
// 實際完整的內容 (要被縮放的圖形 )
myImageView = [[UIImageView alloc] initWithImage:[UIImage
imageNamed:@"image.jpg"]];
// 框起來要顯⽰示的部份
myScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(10,10,300,440)];
myScrollView.delegate = self; // 這列要寫在前⾯面
// 設定可縮放倍率,把虛擬畫⾯面設定成與 myImageView ⼀一樣⼤大⼩小
myScrollView.contentSize = myImageView.frame.size;
myScrollView.minimumZoomScale = 0.2f;
myScrollView.maximumZoomScale = 2.0f;
myScrollView.zoomScale = 0.5f;
// 讓圖形的中⼼心定位在畫⾯面中央
myScrollView.contentOffset = CGPointMake((myImageView.frame.size.width-300)/2,
(myImageView.frame.size.height-440)/2);
myScrollView.showsHorizontalScrollIndicator = YES;
myScrollView.showsVerticalScrollIndicator = YES;
myScrollView.pagingEnabled = NO;
[myScrollView addSubview:myImageView];
// 置於主畫⾯面上
[self.view addSubview:myScrollView];
}
12. ViewController.m (1/2)
放在畫⾯面中央位置
- (void)viewDidLoad
{
****** 省略部份程式 ******
// ⽤用來顯⽰示倍率的 Label
! scaleRatioLabel = [[UILabel alloc]
initWithFrame:CGRectMake(160-25,240-12.5,50,25)];
! [scaleRatioLabel setBackgroundColor:[UIColor clearColor]];
! [self.view addSubview:scaleRatioLabel];
}
13. ViewController.m (2/2)
// 處理結束縮放事件
- (void) scrollViewDidEndZooming:(UIScrollView *)scrollView
withView:(UIView *)view atScale:(float)scale
{
! [self.view bringSubviewToFront:scaleRatioLabel];
! [scaleRatioLabel setAlpha:0.6f];
! [scaleRatioLabel setBackgroundColor:[UIColor lightGrayColor]];
! scaleRatioLabel.text = [NSString stringWithFormat:@" x%.1f ",scale];
[UIView transitionWithView:scaleRatioLabel
duration:2.0f
options:UIViewAnimationOptionCurveEaseInOut
animations:^(void){
scaleRatioLabel.alpha = 0.0f;
}
completion:nil];
}
19. 假多⼯工的優勢
(相較於真多⼯工)
• 省電 (不佔⽤用 CPU)
• 省記憶體 (釋放後仍能接續執⾏行,故系統
能夠任意釋放記憶體)
• 順暢 (前景程式可以⽤用到近 100% 的 CPU
與更多記憶體)
22. 補充參考
• iOS 與 Android 的多⼯工機制
(http://ffk0716.blogspot.com/2011/07/iosandroid.html)
• 為什麼 Android 開始使⽤用假多⼯工
(http://ffk0716.blogspot.com/2011/12/android.html)
31. iOS App 多⼯工的⽣生命週期
• UIApplicationDelegate
• -(BOOL) applicaton: (UIApplication *)application
didFinishLaunchingWithOptions: (NSDictionary
*)launchOptions
• - (void) applicationWillResignActive:
• - (void) applicationDidEnterBackground:
• - (void) applicationWillEnterForeground:
• - (void) applicationDidBecomeActive:
• - (void) applicationWillTerminate:
32. 動作⼀一:初次執⾏行 App
• App 的誕⽣生
• application:
didFinishLaunchingWithOptions: 被呼叫
• 可在此使⼀一些初始化的動作
• 進⼊入 active 狀態
• applicationDidBecomeAtive: 被呼叫
33. 動作⼆二:按下 home 按鈕
• 進⼊入 inactive 狀態,讓 App 沈睡
• applicationWillResignActive: 被呼叫
• 進⼊入背景模式
• applicationDidEnterBackground: 被呼叫
• 只有很短的時間做休息前的最後運算
• 進⼊入冬眠模式
• 不做動作 (故沒有 method 被呼叫)
• 在記憶體裡仍保有先前建⽴立的物件
34. 動作三:再次按下 App Icon
• 進⼊入前景模式
• applicationWillEnterForeground: 被呼叫
• 進⼊入 active 狀態
• applicationDidBecomeActive: 被呼叫
35. 動作四:進⼊入 lock 狀態
• 進⼊入背景模式
• applicationWillResignActive: 被呼叫
• applicationWillEnterBackground: 被呼叫
• 注意:在 4.3 版中...
• 不會進⼊入背景模式,只是進⼊入 inactive 狀
態
• 沒有事件被呼叫,⽽而時間仍然繼續在⾛走
37. App 的死亡原因
• 使⽤用者在 home 畫⾯面下,再雙擊 home 進⼊入殺⼿手模
式,刪除 App
• 開發者製作的 App 有問題,執⾏行到某個地⽅方當掉
• 執⾏行中的 App 佔了太多記憶體,被系統強制殺掉
• 系統的記憶體不⾜足,於是系統會將進⼊入沈睡模式的
App 殺掉 (佔⽤用愈多記憶體的,優先被刪除)
• App 在進⼊入背景模式 applicationDidEnterBackground:
裡頭執⾏行了太⻑⾧長的時間
• 重新開機
38. 程式終⽌止,善盡責任
• 單⼯工時代的 applicationWillTerminate: 很重要,多⼯工
時代幾乎不⽤用
• 多⼯工後,在 applicationDidEnterBackground: 裡增加
⼀一些預防措施
• 經常狀況
• 例如:簡訊⽂文字輸⼊入到⼀一半、遊戲進⾏行到哪個關
卡......應有預先儲存
• 降低記憶體⽤用量,例如將⼀一些畫⾯面上的 UI 物件
清除。改採記錄當時的畫⾯面資訊,之後可再還原
40. AppDelegate.m
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSLog(@"!!! %@", NSStringFromSelector(_cmd));
*** 省略部份程式 ***
} 指定各處使⽤用相同的程式
- (void)applicationWillResignActive:(UIApplication *)application
{
NSLog(@"!!! %@", NSStringFromSelector(_cmd));
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(@"!!! %@", NSStringFromSelector(_cmd));
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
NSLog(@"!!! %@", NSStringFromSelector(_cmd));
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
NSLog(@"!!! %@", NSStringFromSelector(_cmd));
}
- (void)applicationWillTerminate:(UIApplication *)application
{
NSLog(@"!!! %@", NSStringFromSelector(_cmd));
}
41. ViewController.h
Notification 的測試
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
{
int count;
IBOutlet UILabel *display;
}
-(void)sayGoodBye:(NSNotification*)notification;
-(void)sayHello:(NSNotification*)notification;
@end
43. ViewController.m (2/2)
返回前景狀態的通知
-(void)sayHello:(NSNotification*)notification
{
NSLog(@"Say Hello from %@", notification);
count++;
display.text = [NSString stringWithFormat:
@"Hello ⼜又⾒見⾯面啦!這是第 %d 次重相⾒見", count];
}
- (void)viewDidLoad
{
*** 省略部份程式 ***
count = 1;
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(sayHello:)
name:UIApplicationWillEnterForegroundNotification
object:[UIApplication sharedApplication]];
}
45. 狀態變更的通知
• 狀態變更的通知 (notification)
• UIApplicationDelegate 最清楚,但⼤大部份
時候,控制畫⾯面顯⽰示內容的,卻是 view
controller,故需要被通知
• notification 機制可⽤用在任何物件 (不只是
view controller)
• ⽤用法:由物件申請在狀態發⽣生時被通知
46. Notification 名稱
UIApplicationDelegate method Notification 名稱
application:didFinishLaunchingWithOptions: UIApplicationDidFinishLaunchingNotification
applicationWillResignActive: UIApplicationWillResignActiveNotification
applicationDidBecomeActive: UIApplicationDidBecomeActiveNotification
applicationDidEnterBackground: UIApplicationDidEnterBackgroundNotification
applicationWillEnterForeground: UIApplicationWillEnterForegroundNotification
applicationWillTerminate: UIApplicationWillTerminateNotification
47. 享有背景⼯工作的特權
• 無時間限制 (Multitasking)
• 位置追蹤
• ⾳音樂播放
• VOIP
• GCD (Grand Center Dispatch)
• 開發者可⾃自訂程式功能 (有時間限制)
• beginBackgroundTaskWithExpirationHandler:
49. Project QV037
從樣版 Empty Application
新增⼀一個專案,在上⾯面切
換到另⼀一個 View 畫⾯面
此範例中⾃自訂NextView,
其實就相當於SingleView
Application專案中的
ViewController
51. 選擇 File -> New -> File......
新增加檔案:NextView.h, NextView.m, NextView.xib
53. AppDelegate.h
@class⽤用法在於告訴編譯器,有⼀一個
類別 NextView。也可以改⽤用
#import "NextView.h"
#import <UIKit/UIKit.h>
@class NextView;
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) NextView *nextView;
@end
54. AppDelegate.m
#import "AppDelegate.h"
#import "NextView.h"
@implementation AppDelegate
新增加的程式碼
@synthesize window = _window;
@synthesize nextView = _nextView;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:
(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.nextView = [[NextView alloc] initWithNibName:@"NextView" bundle:nil];
self.window.rootViewController = self.nextView;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
// 部分程式省略
@end
57. #import "AppDelegate.h" AppDelegate.m
@implementation AppDelegate
@synthesize window = _window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:
(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor blueColor];
// 開始⼀一個view
UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0,0,320,480)];
UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
[label setFont:[UIFont boldSystemFontOfSize:18]];
[label setTextAlignment:UITextAlignmentCenter];
[label setBackgroundColor:[UIColor clearColor]];
[label setTextColor:[UIColor whiteColor]];
[label setText:@"Hello"];
[view addSubview:label];
[_window addSubview:view];
[self.window makeKeyAndVisible];
return YES;
}
只在此檔案內加⼊入此段
程式,其餘都沒動
58. 補充
⽅方法參考:How to add a simple new
UIView in a window based application
programmatically in iphone。
http://stackoverflow.com/questions/801426/how-to-add-a-simple-new-uiview-in-
a-window-based-application-programmatically-in
為什麼不好?
正確⽅方法參考 QV037;或直接產⽣生
SingleView 的 Application 專案