2013年4月23日 星期二

使用 UIBezierPath 製作圖片

之上一篇 " 解決經常使用相同的圖片所造成記憶體使用量增加的問題 " 其實有另外一個用法
就是搭配 UIBezierPath 來繪製圖片
所以這邊就教簡單的 UIBezierPath 繪製多邊形的方法
首先 UIBezierPath 可以使用在兩種情況下
一個是寫在 - (void)drawRect:(CGRect)rect Method 裡面
但是這個 Method 只會在繼承 UIView Class 中出現
在 UIViewController 中沒有這個 Method
所以變成要轉換成 UIImge 才能使用
接下來的教學會以用這顏色來區分這兩者的差異

深灰色為不會在 - (void)drawRect:(CGRect)rect Method 出現的 Code
橘色為只會在 - (void)drawRect:(CGRect)rect Method 出現的 Code

// 建立繪圖的畫布,其中的 Size 是畫布的大小
UIGraphicsBeginImageContext(self.view.bounds.size);
// 建立畫布的 Context
CGContextRef context = UIGraphicsGetCurrentContext();


// 建立繪圖的路徑
UIBezierPath *additionPolygon = [UIBezierPath bezierPath];
// 建立路徑的起始點
[additionPolygon moveToPoint:view.center]
// 建立一條線從起始點到指定的點;
[additionPolygon addLineToPoint:CGPointMake(x, y)];
// 再畫另一條線
[additionPolygon addLineToPoint:CGPointMake(width, y)];
// 封閉這個路徑
[additionPolygon closePath];

// 建立填滿這個路徑的顏色
CGContextSetFillColorWithColor(context, [[UIColor redColor] CGColor]);
[[UIColor redColor] setFill];
// 將顏色填滿這個路徑
[additionPolygon fill];

// 建立路徑邊線的顏色
CGContextSetStrokeColorWithColor(context, [[UIColor redColor] CGColor]);
[[UIColor redColor] setStroke];
// 設定邊線的粗細
[additionPolygon setLineWidth:10.0f];
// 將顏色填滿這個路徑的邊線
[additionPolygon stroke];


// 將這個路徑轉成 UIImage 的形態
UIImage *bezierImage = UIGraphicsGetImageFromCurrentImageContext();

// 結束這個畫布
UIGraphicsEndImageContext();

// 將畫出來的圖片放入 imageView
UIImageView *imageView = [UIImageView imageViewWithFrame:self.view.bounds];
[imageView setImage:bezierImage];

[self.view addSubview:imageView];



這樣子就可以靠程式碼畫一張簡單的圖片了
UIBezierPath 是一個萬能的繪圖路徑
它也有弧線、貝茲曲線、圓角矩形等路徑可以使用
另外我也推薦一個可以更快速繪圖的程式 PaintCode
它像是 Photoshop 一樣可以透過圖形介面進行繪畫
畫完後會自動轉成程式碼給你使用,只不過需要 NTD 2990
倒是有點貴就是了。

2013年4月16日 星期二

解決經常使用相同的圖片所造成記憶體使用量增加的問題

這次是一個 Category 的進階應用
在某些時候會需要經常重複使用同一張圖片
有可能會造成記憶體使用量的增加,造成不必要的記憶體消耗
這時候可以使用以下方法

先建立一個基於 UIImage 的 Catagory
在 h 檔中建立以下 Code
+ (id)aImage

之後在 m 檔建立以下 Code
其中 aImage 是可以由你自行決定名稱
static UIImage aImage = nil;

+ (id)aImage
{
	if (aImage == nil) {
		aImage = [[UIImage imageNamed:@"__imageName__"] retain];
	}
	
	return aImage;
}

這時候在需要使用這張圖的時候可以直接使用 [UIImage aImage]; 就可以調用這張圖片
而且用過後會一直保留在記憶體中,直到這個程式被終結掉為止,
這樣子就不用一直將相同的圖片重新載入記憶體而造成記憶體的消耗。

2013年3月19日 星期二

發佈自定的 Notification

在之前的 Remote Control 的教學中有說到可以做在 appDetegate 中
但是在其他的 ViewController 要怎麼收到這些訊息了?
最簡單的是使用 Notification,但是要如何使用了?

在絕大部分的教學書都有說到如何接收 NotificationCenter 的訊息
但是很少書本有說到要如何發佈自定的 Notification 訊息,
其實很簡單,作法如下
[[NSNotificationCenter defaultCenter] postNotificationName:@"發佈的訊息名稱" object:nil];

這樣子就會在觸發這行時發佈出 Notification 訊息,這時候在需要接收的 Class 中做註冊 NotificationCenter 的動作
[[NSNotificationCenter defaultCenter] addObserver:self selector:接收到訊息所觸發的動作  name:@"發佈的訊息名稱" object:nil];

這時候就可以收到訊息時做相對映的動作了,當然有註冊訊息就有注銷訊息,
在你不需要接收訊息的時候就要做注銷的動作,注銷的方法如下,
[[NSNotificationCenter defaultCenter] removeObserver:self  name:@"發佈的訊息名稱" object:nil];

注銷後就不會再接收到訊息的,除非你再度註冊。

這次的教學就到此為止,下次的教學再見了。

2013年2月28日 星期四

Remote Control

這次是教如何使用多工列左邊的 Remote Control 來控制你的音樂播放
要使用這個功能很簡單,只要在 viewWillAppear 的時候宣到要接收 Remote Control 的事件
宣告如下:
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];

這樣子就會開始接收到了,但是有開始必定有結束
所以結束時要在 viewDidDisappear 的時候宣告停止接收 Remote Control 的事件
宣告如下:
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];

這樣子開始與結束接收 Remote Control 的事件都完成了
但是光是接收到事件是不夠的,還要做相對應的動作
這時候就要建立
- (void)remoteControlReceivedWithEvent:(UIEvent *)event
這個 Method 來實作相對應的動作

但是這個 Method 的傳入值 event 有可能會是 Touch event 、Shake event
所以要先過濾掉,實作的內容如下
- (void)remoteControlReceivedWithEvent:(UIEvent *)event
{
	if (event.type != UIEventTypeRemoteControl) return;

	switch (event.subtype) {
		case UIEventSubtypeRemoteControlTogglePlayPause:
		// 按下播放/暫停時的動作
			break;

		case UIEventSubtypeRemoteControlNextTrack:
		// 按下下一首歌的動作
			break;

		case UIEventSubtypeRemoteControlPreviousTrack:
		// 按下上一首歌的動作
			break;

		case UIEventSubtypeRemoteControlBeginSeekingForward:
		// 長按下一首歌時開始快進的動作
			break;

		case UIEventSubtypeRemoteControlEndSeekingForward:
		// 長按下一首歌時結束快進的動作
			break;

		case UIEventSubtypeRemoteControlBeginSeekingBackward:
		// 長按上一首歌時開始快退的動作
			break;

		case UIEventSubtypeRemoteControlEndSeekingBackward:
		// 長按上一首歌時結束快退的動作
			break;

		default:
			break;
	}
}

完成上面的實作後,這時候就可以按照你的播放器的作法放入相對應的動作了
另外現在只有在這個播放器的畫面下 Remote Control 才有作用
如果想不在播放器的畫面下時 Remote Control 也要有作用的話
我是建議將它實作到 appDelegate.m 裡面

不過要如何將那些動作傳入到播放器的畫面下?
這就要自己想想摟,這次的教學就到這邊,下次再見了