2015年8月29日 星期六

HTML筆記

What is HTML?

HTML is a markup language for describing web documents (web pages).

HTML功能: 類似word文件裡面編寫文章的架構一下使內容可以更好的被閱讀.

  • HTML stands for Hyper Text Markup Language
  • A markup language is a set of markup tags
  • HTML documents are described by HTML tags
  • Each HTML tag describes different document content

基本架構與語法:

  • HTML tags normally come in pairs like <p> and</p>
  • The first tag in a pair is the start tag, the second tag is the end tag

HTML元素(element): 是建構HTML網頁的基本要素,指的就是開始與結束標籤(tags)與所包夾的內容(content).
結束的tag通常都會有”/”.

<標籤>內容</標籤>

屬性(attributes):
a. 屬性名: 表明要提供元素內什麼類型的額外資訊(必須是小寫).
b. 屬性值: 屬性的資訊或是設定值,必須在雙引號之間.
ex. <p lang="en-us">Paragraph in English</p>

id屬性: 每個HTML元素都可以使用,作用是在將頁面內的所有元素當中,將某個元素獨立出來. 全域屬性
class屬性: 每個HTML元素都可以使用,作用是在將頁面內的所有元素當中,將幾個元素從其他元素中獨立出來.

<div></div> 將一組元素群組起來,讓管理code的工作更容易

HTML Page Structure

enter image description here

The declaration helps the browser to display a web page correctly.

<!DOCTYPE html>是一種文件類別宣告(document type declaration)而非元素喔,是用來宣告(定義)目前HTML文件是使用那一個版本

<!DOCTYPE html>  (告訴瀏覽器 我們使用的HTML版本)
<!-- -->  (註解)
<html>
        <head>
                在這裡面包含了這個頁面的相關資訊.
                <title>在這裡面的內容會出現在瀏覽器的標題上.</title>
        </head>
        <body>
        在這裏面的所有東西都會出現在網頁視窗上.
        </body>
</html>

HTML頁面中文亂碼問題:
enter image description here

解決辦法: 在<head> </head>中間新增

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

PS. <meta> 用來存放頁面的描述資料,關鍵字、描述…等
enter image description here

a) 常見標籤介紹

<h1></h1>...<h6></h6>            標題(數字越小權重越高)
<p></p>                          段落
<br>                             跳行
<br />                           斷行
<hr />                           水平線(分段的)
<b></b>  or <strong></strong>    粗體字
<i></i>  or <em></em>            斜體字
<sup></sup>                      上標
<sub></sub>                      下標
<abbr></abbr>                    縮寫字 (搭配title) ex. <abbr title="Professor">Prof</abbr>            
<cite></cite>                    標示註解 (瀏覽器會顯示斜體字)
<dfn></dfn>                      定義 (defining instance) 用途是標示出一個新術語的定義
<ins></ins>                      顯示被插入文件的內容 (通常是顯示"底線")
<del></del>                      顯是被刪除的內容(顯示刪節線)
<s></s>                          標示不再正確的內容(顯示刪節線)

PS. 當瀏覽器遇到兩個以上的空白時,它只會顯示一個.

<a></a> 超連結
ex.

<a href="http://www.imdb.com">IMDB</a>
<a mailto:""></a>               EMAIL連結                    
<a href="..." target="_blank"></a>   在新視窗開啟連結

連結到同網頁的某個部分: 要做到這件事情需要使用 “id” 這個屬性,id的值必須為字母或是下滑線為開頭,另外在同一個網頁中兩個id屬性不能有相同的值. 要連結到id屬性的元素時,使用<a>,但是href的值要以 “#” 為開頭.
ex.

<a href="#prologue"> Prologue</a>
<h2 id="prologue">Prologue</h2>

b) 清單類型:HTML有三種不同類型的”清單”

a. 編號清單
<ol></ol> 編號清單
<li></li> 清單中的”每一項”都要在這之間
b. 項目清單
<ul></ul> 項目清單
c. 定義清單
<dl></dl> 定義清單
<dt></dt> 被定義的名詞
<dd></dd> 容納其定義
ex.

<dl>
    <dt>Sashimi</dt>
        <dd>
             QWEQWEQWRQRETWERWETEW
        </dd>
</dl>

巢狀清單 (清單裡面包含清單)
ex.

<ul>
<li>apple</li>
    <li>city</li>
        <ul>
            <li>Taipei</li>
            <li>Taichung</li>
        </ul>
    <li>IPhone</li>
</ul>

c) 表格

<table></table>
<tr></tr> 表格列(table row)
<td></td> 表格資料(table data)

colspan 可以用在<th><td>元素上,並指示該儲存格應該跨越多少欄
rowspan 可以用在<th><td>元素上,並指示該儲存格應該跨越多少列
ex.

<td colspan="2">test </td>

<th></th> 功能跟<td>相同,不過此用途為呈現欄或列的標題(table heading 字體加粗並且會在儲存格中央)
ex.

<th scope="row"> test</th>  (or you can use "col")

row代表行的標題,col代表欄的標題

d) 圖片 (擺放的位置利用CSS來設定)

<img>
ex.

<img src="imges/quokka.jpg" alt=" test " title="test" width="600" height="450">

alt: 當看不到影像時會顯示的敘述
title: 當滑鼠移到影像上方時會出現此屬性內容
width, height: 單位為項訴

e) 表單(form)

<form action="http://www.test.com.test.php" method="get"></form>       

表單
action 值為伺服器上等待接收送出資訊的網頁URL
method 表單送出的方式 get & post

get的使用情況: 表單的值會被加到action屬性所指定的URL後端,適用於短表單、當只是想從網路伺服器取得資料(非新增或刪除資料庫的資訊).
post的情況: 透過HTTP標頭傳送,適用於使用者上傳檔案、表單很長、新增移除資料.

<input /> 製作不同的表單控制選項

type=”text” 文字輸入欄為
ex.

<input type="text" name="username" maxlength="30"  />

type=”password” 密碼輸入
type=”radio” 單選紐
ex.

<input type="radio" name="test" value="rock" checked="checked"  /> Rock
<input type="radio" name="test" value="pop"  />  POP

[value: 該選項要傳到伺服器的值, 同一組選項中要有不同的值。 checked:標示說當頁面再載入時應該預先選好的值]

type=”checkbox” 勾選紐(設定同radio)
type=”file” 檔案輸入區塊 (會自動出現瀏覽按鈕)
type=”submit” 功能: 產生按鈕將表單送到伺服器
ex.

 <input type="summit" name="subscribe" value="Subsscribe">  

value: 控制出現在按鈕上的文字

type=”image” 功能: 上傳影像, 屬性跟依樣
ex.

<input type="summit" name="subscribe" value="Subsscribe">         value: 控制出現在按鈕上的文字

<textarea></textarea> 文字區塊
ex.

<textarea name="comments" cols="20" rows="4">text</textarea>  

<select></select> 下拉式選單欄位
ex.

<select name="test" multiple="multiple">
<option value="test1" selected="selected">test1</option>
<option value="test2">test2</option>
</select>

[name: 要和使用者所選取的值一起送到伺服器的表個名稱。multiple: 開放多選。option: 在這裏面的文字會顯示在下拉選單中]

<fieldset></fieldset> 將表單群組起來 (再加範例)
<legend></legend> 群組起來之後 設定標題用

HTML5 新增功能

<required="required"> 表單驗證 (驗證有無填寫)
type=”date” 日期輸入
type=”email” email 輸入(會順便檢查格式是否正確)
type=”url” 同上
placeholder=”Enter keyword” 在資料輸入欄位之前 顯示的文字

<iframe></iframe> 在網頁中切出一個小視窗,在這個視窗內你可以看到其他網頁的內容
ex.

<iframe width="450" height="350" src="http://maps.google.co.uk/maps?q=moma+new+york&amp;output=embed"  
frameborder="0"   <!-- 是否顯示編框 0 or 1-->
scrolling="no"  <!-- 此屬性在HTML5不支援  yes, no, auto --> > </frame>

<video></video> 新增視訊到網站
內建屬性: poster=”images/…jpg” 當影片正在下載時會顯示的圖片, controls, autoplay, loop.
<audio></audio> 音源
內建屬性: controls, autoplay preload, loop

參考資料:
http://www.w3schools.com/

2015年8月28日 星期五

iOS筆記:AVFoundation.framework

建立播放音樂的app, 先匯入AVFoundation.h 標頭檔以及AVAudioPlayerDelegate協定. 再宣告一個AVAudioPlayer型態的變數audioPlayer來播放音樂.

#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>

@interface ViewController : UIViewController <AVAudioPlayerDelegate>
{
    AVAudioPlayer *audioPlayer;
    NSTimer *timer;
}

@property (strong, nonatomic) IBOutlet UISlider *slider;

- (void)ticker:(NSTimer *)theTimer;

@end

初始化 audioPlayer變數, 並設定代理人類別為ViewController, 目的為當音樂播放過程中被某些因素中斷時, 程式可以回應這個中斷, 並且當中斷因素結束後, 可以恢復音樂播放.

先找到music.mp3的路徑, 再進行初始化等動作.

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"music" ofType:@"mp3"];
    NSData *fileData = [NSData dataWithContentsOfFile:filePath];

    audioPlayer = [[AVAudioPlayer alloc] initWithData:fileData error:nil];

    audioPlayer.delegate = self;

    if (audioPlayer != nil) {
        if ([audioPlayer prepareToPlay]) {
            self.slider.minimumValue = 0;
            self.slider.maximumValue = audioPlayer.duration;
            self.slider.value = 0;
            [audioPlayer play];

           #啟動計時器
            timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(ticker:) userInfo:nil repeats:YES];
        }
    } 
}

當音樂被中斷時呼叫下列方法.

- (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player
{
    NSLog(@"音樂中斷");
}

從flags參數判斷音樂中斷時的狀況.

- (void) audioPlayerEndInterruption:(AVAudioPlayer *)player withOptions:(NSUInteger)flags
{
    NSLog(@"音樂中斷結束");
    if (flags == AVAudioSessionInterruptionOptionShouldResume) {
        [player play];
    }
}

ticker方法為當計數器被觸發後呼叫的. 根據計時器的設定, 這個方法每一秒都會被呼叫一次, 因為在這個方法中我們更新slider的值, 讓他跟音樂的進度一致.

changePlayTime為當我們去調整slider目前的值時會跟著改變音樂的播放進度.

- (void)ticker:(NSTimer *)theTimer
{
    self.slider.value = audioPlayer.currentTime;
}

- (IBAction)changePlayTime:(id)sender
{
    audioPlayer.currentTime = self.slider.value;
}

enter image description here

參考:
http://www.appcoda.com/ios-avfoundation-framework-tutorial/

2015年8月25日 星期二

iOS筆記:UICollectionView & Search Bar (iOS8)

UICollectionView

實現一個UICollectionView和實現一個UITableView基本沒有什麼大區別,它們都同樣是datasource和delegate設計模式的:
datasource為view提供數據源,告訴view要顯示些什麼東西以及如何顯示它們.
delegate提供一些樣式的小細節以及用戶交互的相應.

UICollectionViewDataSource
1. section的數量-numberOfSectionsInCollection:
2. 某個section裡有多少個item -collectionView:numberOfItemsInSection:
3. 對於某個位置應該顯示什麼樣的cell -collectionView:cellForItemAtIndexPath:

為了得到高效的View,對於cell的重用是必須的,避免了不斷生成和銷毀對象的操作,這與在UITableView中的情況是一致的。

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MY_CELL_ID"];  
if (!cell) {    //如果没有可重用的cell,就會生成一個  
    cell = [[UITableViewCell alloc] init]; 
} 
//配置cell.... 
return cell 


- (UICollectionView*)collectionView:(UICollectionView*)cv cellForItemAtIndexPath:(NSIndexPath*)indexPath { 
    MyCell *cell = [cv dequeueReusableCellWithReuseIdentifier:@”MY_CELL_ID”]; 
    // Configure the cell's content 
    cell.imageView.image = ... 
    return cell; 
}

Customizing the Flow Layout Attributes

If all of the items in the collection view are the same size, assign the appropriate width and height values to the itemSize property of the flow layout object. (Always specify the size of items in points.) This is the fastest way to configure the layout object for content whose size does not vary.

If you want to specify different sizes for your cells, you must implement the collectionView:layout:sizeForItemAtIndexPath:method on the collection view delegate. You can use the provided index path information to return the size of the corresponding item. During layout, the flow layout object centers items vertically on the same line. The overall height or width of the line is then determined by the largest item in that dimension.

enter image description here

UICollectionViewDelegateFlowLayout is actually a sub-protocol of UICollectionViewDelegate, so there is no need to list both.

SearchBar Controller

在iOS8中已經將UISearchDisplayController取消了,取而代之的是UISearchController類別. 此類別可以將結果顯示在collection view上.

UISearchController必須符合協定. searchResult陣列負責存放搜尋後的結果. 再來宣告一家UISearchController型態的變數, 負責處理跟搜尋有關的事項.

@interface MovieTableViewController : UITableViewController<...,UISearchResultsUpdating>
{
    NSArray *searchResult;
    UISearchController *searchController;
}
@end
- (void)viewDidLoad {
    [super viewDidLoad];
    ...
#初始化SearchController, 最後一個參數nil表示搜尋結果會顯示在目前的view上.
searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
#設定哪個controller要負責回應searchBar的更新.
searchController.searchResultsUpdater = self;
#NO表示搜尋時背景不會變暗.
searchController.dimsBackgroundDuringPresentation = NO;

#將searchBar的高度設定為40, searchBar才會出現, 預設為0.0
CGRect rect = searchController.searchBar.frame;
rect.size.height = 40;
searchController.searchBar.frame = rect;

#將searchBar放在tableView的上方.
self.tableView.tableHeaderView = searchController.searchBar;
#YES表示 UISearchController的畫面會覆蓋目前的controller.
self.definesPresentationContext = YES;
}

numberOfSectionsInTableView回傳1, 表示表格中有一個區段.

tableView: numberOfRowsInSection修改為判斷搜尋結果是否為nil.

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (searchResult != nil) {
        return [searchResult count];
    }

    return [Movies count];
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *movieidentifier = @"MovieListCell";

    MovieTableCell *cell = [tableView dequeueReusableCellWithIdentifier:movieidentifier];

    if (cell == nil) {
        cell = [[MovieTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:movieidentifier];
    }

    if (searchResult!=nil) {
        Movie *movie = [searchResult objectAtIndex:indexPath.row];
        cell.CellImage.image = [UIImage imageNamed:movie.movieImage];
        cell.CellLabel.text = movie.movieName;
        cell.CellTime.text = movie.movieTime;
    }
    else
    {
        Movie *movie = [Movies objectAtIndex:indexPath.row];
        cell.CellImage.image = [UIImage imageNamed:movie.movieImage];
        cell.CellLabel.text = movie.movieName;
        cell.CellTime.text = movie.movieTime;
    }
    return cell;
}

實作 updateSearchResultForSearchController此方法是當使用者點選搜尋列以及輸入資料時會觸發的方法, 因此在這個方法中根據使用者打的字串, 將搜尋結果放到變數 searchResult中, 最後呼叫tableView: reloadData更新表格內容.

NSPredicate:對self每個對象通過謂詞進行篩選,判斷是否與條件相匹配。Predicate中加入[cd],就能找到英文不區分大小寫的字串囉.
Apple 文件關於NSPredicate: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Predicates/Articles/pUsing.html#//apple_ref/doc/uid/TP40001794-250409
範例:

NSMutableArray *array =
    [NSMutableArray arrayWithObjects:@"Nick", @"Ben", @"Adam", @"Melissa", nil];

NSPredicate *sPredicate = [NSPredicate predicateWithFormat:@"SELF contains[c] 'e'"];
[array filterUsingPredicate:sPredicate];

#Array now contains { @"Nick", @"Ben", @"Melissa" }
If you use the Core Data framework, the array methods provide an efficient means of filtering an existing array of objects without—as a fetch does—requiring a round trip to a persistent data store.
- (void)updateSearchResultsForSearchController:(UISearchController *)mysearchController
{
    if (mysearchController.isActive) {
        NSString *searchString = mysearchController.searchBar.text;

        if ([searchString length] > 0) {
            NSPredicate *p = [NSPredicate predicateWithFormat:@"SELF.movieName CONTAINS[cd] %@", searchString];
            searchResult = [Movies filteredArrayUsingPredicate:p];
        } else{
            searchResult = nil;
        }
    } else {
        searchResult = nil;
    }
    [self.tableView reloadData];
}

參考:
https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/UsingtheFlowLayout/UsingtheFlowLayout.html#//apple_ref/doc/uid/TP40012334-CH3-SW1
http://objccn.io/issue-12-5/
http://www.howzhi.com/group/iosDevelop/discuss/10134
http://stackoverflow.com/questions/7302842/about-searching-by-using-nspredicate

2015年8月4日 星期二

iOS筆記:Core Location & MapKit(2)

How To Get the User Location

Adding Core Location Framework

我們必須手動自己添加 Core Location Framework
enter image description here

Back to the code, and to let the view controller know about the CLLocationManagerDelegate, you first import the corresponding header file. In the “ViewController.h”, add the #import statement and implement the “CLLocationManagerDelegate”.

#import <CoreLocation/CoreLocation.h>

@interface ViewController : UIViewController <CLLocationManagerDelegate>

@property (strong, nonatomic) IBOutlet UILabel *latitudeLabel;
@property (strong, nonatomic) IBOutlet UILabel *longtitudeLabel;
@property (strong, nonatomic) IBOutlet UILabel *addressLabel;
- (IBAction)getCurrentLocetion:(id)sender;

@end

Now go to the “MyLocationViewController.m”. The CLLocationManager is the object that provides you the location data.

@implementation ViewController
{
    CLLocationManager *locationManager;
}

Once you initialize a CLLocationManager object, you can simply call the startUpdatingLocation method to the location service. The service will then continuously send your application a stream of location data.

- (void)viewDidLoad {
    [super viewDidLoad];

    locationManager = [[CLLocationManager alloc] init];
}

The location data is reported to your app via the location manager’s associated delegate object. All the location updates will send to the delegate. To capture the location event, we have to implement the delegate methods as defined in the protocol.

- (IBAction)getCurrentLocetion:(id)sender {

    locationManager.delegate = self;
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    [locationManager requestWhenInUseAuthorization]; 
    #使用程式期間允許獲取位置的數據 (iOS8需要)
    [locationManager startUpdatingLocation];
}
#pragma mark - CLLocationManagerDelegate

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
    NSLog(@"didFailWithError: %@", error);
    UIAlertView *errorAlert = 
    [[UIAlertView alloc] initWithTitle:@"Error" message:@"Failed to Get Your Location" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [errorAlert show];
}

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    #第0個位置資訊,表示為最新的位置資訊
    CLLocation * currentLocation = [locations objectAtIndex:0];
    _longtitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude];

    _latitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.latitude];
}

如果是在iOS8的版本實作的話請記得在Info.plist文件中添加如下配置.
(1)NSLocationAlwaysUsageDescription
(2)NSLocationWhenInUseUsageDescription
enter image description here

Test.
選Location\City Run,表示會以走路的方式模擬手機所在位置,如此就可取得位置變動的資訊,接著即可看到經緯度隨時間一再的變更.
enter image description here

enter image description here

Finding the Address

The CLGeocoder class provides services for converting between a GPS coordinate and the user-readable address of that coordinate. By specify the latitude and longitude of a given location, you can use CLGeocoder to find a user-readable address.
新增 instance variables: geocoder and placemark.

@implementation MyLocationViewController {
    CLLocationManager *locationManager;
    CLGeocoder *geocoder;
    CLPlacemark *placemark;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    locationManager = [[CLLocationManager alloc] init];
    geocoder = [[CLGeocoder alloc] init];
}

Update the “didUpdateToLocation” method to include the code for reverse geocoding:

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations

# Reverse Geocoding
    NSLog(@"Resolving the Address");
    [geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
        NSLog(@"Found placemarks: %@, error: %@", placemarks, error);
        if (error == nil && [placemarks count] > 0) {
            placemark = [placemarks lastObject];
            addressLabel.text = [NSString stringWithFormat:@"%@ %@\n%@ %@\n%@\n%@",                                                                    placemark.subThoroughfare, placemark.thoroughfare,
placemark.postalCode, placemark.locality, placemark.administrativeArea, placemark.country];
        } else {
            NSLog(@"%@", error.debugDescription);
        }
    } ];

Saving Battery Power

一直開啟GPS是一件非常耗電的事情, 因為他會一直update現在的位置, 即使你位置沒有變動.
Use the “stopUpdatingLocation” method to disable the location update.

[locationManager stopUpdatingLocation];

MapKit API and Add an Annotation on Map

enter image description here

Make sure add both “CoreLocation” and “MapKit” frameworks.
enter image description here

Zoom Into the Current Location

#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>

@interface MyLocationViewController : UIViewController <MKMapViewDelegate>

@property (nonatomic, strong) IBOutlet MKMapView *mapView;

@end

The MKMapViewDelegate protocol defines a set of optional methods that you can use to receive map-related update messages. The mapView:didUpdateUserLocation method is called whenever a new location update is received by the map view.

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.mapView.delegate = self;
}

Annotation: mapkit提供的是一個藍色的原點來代表位置, 透過下面的方式可以得到一個pin來顯在自己的位置, 這麼pin的顏色可以更換或是自訂圖案, 再點選之後也可以出現照片等等…

To place a pin in the correct location on map, we first create a MKPointAnnotation object and assign it with the coordinate of user’s location. We also assign the title and subtitle for the call-out that appears when you tap on the pin. Lastly, we call the addAnnotation: method to add the annotation object to the map view.

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
    MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
    [self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
}
    # Add an annotation
    MKPointAnnotation *point1 = [[MKPointAnnotation alloc] init];
    point1.coordinate = CLLocationCoordinate2DMake(25.0335, 121.5651);
    point1.title = @"Taipei";
    point1.subtitle = @"ROC";
    [self.mapview addAnnotation:point1];
#建立MapPin時會呼叫的函式
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {

    #判斷Pin如果是目前位置就不修改
    if ([annotation isKindOfClass:[MKUserLocation class]]) {
        return nil;
    }

    MKPinAnnotationView *pinView = [[MKPinAnnotationView alloc]
                                    initWithAnnotation:annotation reuseIdentifier:@"PinView"];

    #設定顏色
    pinView.pinColor = MKPinAnnotationColorGreen;

    UIImage *image = [UIImage imageNamed:@"tomorrowland.jpg"];
    UIImageView  *imageView = [[UIImageView alloc] initWithImage:image];

    #重設圖片大小與座標
    imageView.frame = CGRectMake(0, 0, 46, 46);

    #設定註解內的圖片
    pinView.leftCalloutAccessoryView = imageView;

    #點擊時是否出現註解
    pinView.canShowCallout = YES;

    return pinView;
}

參考:
http://www.bkjia.com/IOSjc/987975.html
http://lokanghung.blogspot.tw/2014/05/ios-cllocationmanager.html
http://www.appcoda.com/how-to-get-current-location-iphone-user/
http://www.appcoda.com/ios-programming-101-drop-a-pin-on-map-with-mapkit-api/
http://furnacedigital.blogspot.tw/2011/01/map-view-pin.html

2015年8月2日 星期日

一週一GT:Ed Sheeran - Photograph

Ed Sheeran - Photograph KEY:E

Verse Palm muted-Strokes: E / C#m / B / A

Prechorus Palm muted-Strokes: C#m / A / E / B

Chorus Palm-Strokes: E / B / C#m / A

Loving can hurt, loving can hurt sometimes
But it’s the only thing that I know
When it gets hard, you know it can get hard sometimes
It is the only thing that makes us feel alive

We keep this love in a photograph
We made these memories for ourselves
Where our eyes are never closing
Hearts are never broken
And time’s forever frozen still

So you can keep me
Inside the pocket of your ripped jeans
Holding me closer ‘til our eyes meet
You won’t ever be alone, wait for me to come home

Loving can heal, loving can mend your soul
And it’s the only thing that I know, know
I swear it will get easier,
Remember that with every piece of you
Hm, and it’s the only thing we take with us when we die

Hm, we keep this love in this photograph
We made these memories for ourselves
Where our eyes are never closing
Hearts were never broken
And time’s forever frozen still

So you can keep me
Inside the pocket of your ripped jeans
Holding me closer ‘til our eyes meet
You won’t ever be alone

And if you hurt me
That’s okay baby, only words bleed
Inside these pages you just hold me
And I won’t ever let you go
Wait for me to come home
Wait for me to come home
Wait for me to come home
Wait for me to come home

You can fit me
Inside the necklace you got when you were sixteen
Next to your heartbeat where I should be
Keep it deep within your soul

And if you hurt me
Well, that’s okay baby, only words bleed
Inside these pages you just hold me
And I won’t ever let you go

When I’m away, I will remember how you kissed me
Under the lamppost back on Sixth street
Hearing you whisper through the phone,
“Wait for me to come home.”

Youtube:
https://www.youtube.com/watch?v=SPKBtZHuzKY

2015年7月30日 星期四

iOS筆記:Core Location & MapKit(1)

Framework for managing location and heading! No user-interface. Basic object is CLLocation

@propertys: coordinate, altitude, horizontal/verticalAccuracy, timestamp, speed, course!

基本宣告

@property (readonly) CLLocationCoordinate2D coordinate;
 typedef {
CLLocationDegrees latitude; # a double
CLLocationDegrees longitude; # a double 
} CLLocationCoordinate2D;

@property (readonly) CLLocationDistance altitude; # meters

The more accuracy you request, the more battery will be used!
Device “does its best” given a specified accuracy request.

How close to that latitude/longitude is the actual location?

@property (readonly) CLLocationAccuracy horizontalAccuracy; # in meters 
@property (readonly) CLLocationAccuracy verticalAccuracy; # in meters 

A negative value means the coordinate or altitude (respectively) is invalid.

kCLLocationAccuracyBestForNavigation // phone should be plugged in to power source
kCLLocationAccuracyBest
kCLLocationAccuracyNearestTenMeters
kCLLocationAccuracyHundredMeters
kCLLocationAccuracyKilometer
kCLLocationAccuracyThreeKilometers

@property (readonly) CLLocationSpeed speed; # in meters/second
@property (readonly) CLLocationDirection course; # in degrees, 0 is north, clockwise
@property (readonly) NSDate *timestamp;

- (CLLocationDistance)distanceFromLocation:(CLLocation *)otherLocation; // in meters

How do you get a CLLocation?

Almost always from a CLLocationManager (sent to you via its delegate).

General approach to using it:

  1. Check to see if the hardware you are on/user supports the kind of location updating you want.
  2. Create a CLLocationManager instance and set the delegate to receive updates.
  3. Configure the manager according to what kind of location updating you want.
  4. Start the manager monitoring for location changes.

Checking to see what your hardware can do!
+ (CLAuthorizationStatus)authorizationStatus; // Authorized, Denied or Restricted (parental, enterprise)
+ (BOOL)locationServicesEnabled; // user has enabled (or not) location services for your application
+ (BOOL)significantLocationChangeMonitoringAvailable;
+ (BOOL)isMonitoringAvailableForClass:(Class)regionClass; //[CLBeacon/CLCircularRegionclass]
+ (BOOL)isRangingAvailable; // device can tell how far it is from beacons!

You can also limit updates to only occurring if the change in location exceeds a certain distance .

@property CLLocationDistance distanceFilter;

Starting and stopping normal position monitoring!

- (void)startUpdatingLocation;
- (void)stopUpdatingLocation;

Be sure to turn updating off when your application is not going to consume the changes!!
Get notified via the CLLocationManager’s delegate! -

(void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations; # of CLLocation! 

Similar API for heading (CLHeading, et. al.)

It is possible to receive these kinds of updates in the background.

There are 2 ways to get location notifications.
1. Significant location change monitoring in CLLocationManager, this works even if your application is not running.You will get launched and your Application Delegate will receive the message!

- (void)startMonitoringSignificantLocationChanges;
- (void)stopMonitoringSignificantLocationChanges;

#function
application:didFinishLaunchingWithOptions: #with an options dictionary that will contain UIApplicationLaunchOptionsLocationKey
  1. Region-based location monitoring in CLLocationManager!
    一個圓形半徑的範圍, 如果用戶進入就會發送訊息.
- (void)startMonitoringForRegion:(CLRegion *)region; # CLCircularRegion/CLBeaconRegion - (void)stopMonitoringForRegion:(CLRegion *)region;

Get notified via the CLLocationManager’s delegate!

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region; 
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region;
- (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region
withError:(NSError *)error;

To be a beacon is a bit more involved!

Need to check out CBPeripheralManager (Core Bluetooth Framework).

Map Kit

User interface of location.
enter image description here

enter image description here

enter image description here

enter image description here

To use MKMapView: Create with alloc/init or drag from object palette in Xcode! Displays an array of objects which implement MKAnnotation

@property (readonly) NSArray *annotations; # contains id <MKAnnotation> objects ! 

MKAnnotation protocol

@protocol MKAnnotation <NSObject>
@property (readonly) CLLocationCoordinate2D coordinate;
@optional
@property (readonly) NSString *title; 
@property (readonly) NSString *subtitle;
@end

#require
typedef { 
    CLLocationDegrees latitude; 
    CLLocationDegrees longitude;
} CLLocationCoordinate2D;

Note that the annotations property is readonly, so …

@property (readonly) NSArray *annotations; # contains id <MKAnnotation> objects 

Must add/remove annotations explicitly

  • (void)addAnnotation:(id )annotation;
  • (void)addAnnotations:(NSArray *)annotations;
  • (void)removeAnnotation:(id )annotation;
  • (void)removeAnnotations:(NSArray *)annotations;

What happens when you touch on an annotation (e.g. the pin)?

Depends on the MKAnnotationView that is associated with the annotation (more on this later). By default, nothing happens, but if canShowCallout is YES in the MKAnnotationView, then
a little box will appear showing the annotation’s title and subtitle.
And this little box (the callout) can be enhanced with left/rightCalloutAccessoryViews.

How are MKAnnotationViews created & associated w/annotations?!

Very similar to UITableViewCells in a UITableView(CellForRowAtIndex 給section and row 就得到一個cell ).

enter image description here

Using didSelectAnnotationView: to load up callout accessories

- (void)mapView:(MKMapView *)sender didSelectAnnotationView:(MKAnnotationView *)aView 
{
    if ([aView.leftCalloutAccessoryView isKindOfClass:[UIImageView class]]) {
        UIImageView *imageView = (UIImageView *)aView.leftCalloutAccessoryView;
imageView.image = ...; 
#if you do this in a GCD queue, be careful, views are reused! 
    }
}

enter image description here

Controlling the region (part of the world) the map is displaying

@property MKCoordinateRegion region; 
typedef struct {
    CLLocationCoordinate2D center;
    MKCoordinateSpan span; 
} MKCoordinateRegion; 
typedef struct {
    CLLocationDegrees latitudeDelta;
    CLLocationDegrees longitudeDelta; 
}
- (void)setRegion:(MKCoordinateRegion)region animated:(BOOL)animated; # animate

This is a good place to “chain” animations to the map.!
When you display somewhere new in the map that is far away, zoom out, then back in.! This method will let you know when it’s finished zooming out, so you can then zoom in.

- (void)mapView:(MKMapView *)mapView didChangeRegionAnimated:(BOOL)animated;

MKLocalSearch: Searching for places in the world

Can search by “natural language” strings asynchronously (uses the network)

MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init]; 
request.naturalLanguageQuery = @“Ike’s”;
request.region = ...;
MKLocalSearch *search = [[MKLocalSearch alloc] initWithRequest:request];
[search startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error) {
  # response contains an array of MKMapItem which contains MKPlacemark 
}];

You can open one of these MapItem in the Maps app

- (BOOL)openInMapsWithLaunchOptions:(NSDictionary *)options; // options like region, show traffic

enter image description here

Add overlays to the MKMapView and it will later ask you for a renderer to draw the overlay.

- (void)addOverlay:(id <MKOverlay>)overlay level:(MKOverlayLevel)level;

Level is (currently) either AboveRoads or AboveLabels (over everything but annotation views).

- (void)removeOverlay:(id <MKOverlay>)overlay;

Built-in Overlays and Renderers for numerous shapes …

MKCircleRenderer
MKPolylineRenderer
MKPolygonRenderer
MKTileOverlayRenderer #can also be used to replace the map data from Apple

Embed Segues

Drag out a Container View from the object palette into the scene you want to embed it in. Automatically sets up an “Embed Segue” from container VC to the contained VC.

2015年7月29日 星期三

iOS筆記:UITableView (2)

Cell Type

enter image description here

如果TableView是屬於static cell的話, static means that these cells are set, up in the storyboard only, You can edit them however you want
including dragging butto

UITableView Protocols

UITableViewController
Automatically sets itself as its UITableView’s delegate & dataSource.!
Also has a property pointing to its UITableView:!

@property (nonatomic, strong) UITableView *tableView;
#(this property is actually == self.view in UITableViewController! 但我們不這樣用)

The delegate is used to control how the table is displayed. include what if someone touch the row, we want to react that, and how we arrange things.

The dataSource provides the data what is displayed inside the cells. 指的是TableView的內容(content), 從database出來要填入表格的數據.dataSource is a protocol to bring the model’s data into the View.

UITableViewDataSource

We have to implement these 3 to be a “dynamic” (arbitrary number of rows) table . static的tableView已經在storyboard中設置好了.

  1. How many sections in the table?
  2. How many rows in each section?
  3. Give me a UITableViewCell to use to draw each cell at a given row in a given section.
- (UITableViewCell *)tableView:(UITableView *)sender
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   #get a cell to use (instance of UITableViewCell)
   UITableViewCell *cell;
cell = [self.tableView dequeueReusableCellWithIdentifier:@“Flickr Photo Cell” forIndexPath:indexPath];                                         

   #dequeueReusableCell只創建會出現在螢幕上的行數,當往下滑TableView時, 離開螢幕的行會補到下面再次填上資料出現

   #set @propertys on the cell to prepare it to display
   ...
   return cell;
}

How does a dynamic table know how many rows there are?
Number of sections is 1 by default, if you don’t implement numberOfSectionsInTableView:, it will be 1.

- (NSInteger)numberOfSectionsInTableView:(UITableView *)sender; !
- (NSInteger)tableView:(UITableView *)sender numberOfRowsInSection:(NSInteger)section; 
#This is a required method in this protocol

What about a static table?

Do not implement these dataSource methods for a static table. UITableViewController will take care of that for you.

UITableViewDelegate.

負責如何顯示表格, 而不是任何關於顯示出來的數據內容.The delegate also lets you observe what the table view is doing.The classic “will/did” sorts of things.

- (void)tableView:(UITableView *)sender didSelectRowAtIndexPath:(NSIndexPath *)path ! {!
# go do something based on information about my Model! # corresponding to indexPath.row in indexPath.section
}

UITableView Segue

The sender of prepareForSegue:sender: is the UITableViewCell! Use the important method indexPathForCell:to find out the indexPath of the row that’s segueing.!

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
# prepare segue.destinationController to display based on information
# about my Model corresponding to indexPath.row in indexPath.section }

UITableView Spinner

當內容是透過網路加載的時候, 用spinner可以讓使用者知道正在透過其他queue下載資料.You get it via this property in UITableViewController.

@property (strong) UIRefreshControl *refreshControl;
# Start it with ...
- (void)beginRefreshing;
# Stop it with ...
- (void)endRefreshing;

enter image description here

What if your Model changes?

- (void)reloadData;
# 這會把整個資料重新更新會使程式變慢
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animationStyle;
# 只更新有變化的部分

Universal Applications

The iPad has more screen real estate, so it can present MVCs in a couple of other ways.
enter image description here

UISplitViewController

enter image description here

@property (strong) UISplitViewController *splitViewController; !

The UISplitViewController has a property which is an array containing Master and Detail:

@property (copy) NSArray *viewControllers; 
# index 0 is Master, 1 is Detail!

UISplitViewControllerDelegete

You must set this delegate very early, probably in awakeFromNib.

e.g., UISplitViewController starts sending its delegate methods way before viewDidLoad.! And then, unfortunately, when its delegate methods get sent to you, your outlets aren’t set yet!! This can make being a UISplitViewController’s delegate a real pain.!

常使用的有:
Never hide the left side (Master) behind a bar button

- (BOOL)splitViewController:(UISplitViewController *)sender shouldHideViewController:(UIViewController *)master
                 inOrientation:(UIInterfaceOrientation)orientation
{
return NO; // never hide it
}

Hide Master in portrait orientation only (the default)

- (BOOL)splitViewController:(UISplitViewController *)sender shouldHideViewController:(UIViewController *)master
                  inOrientation:(UIInterfaceOrientation)orientation
    {
        return UIInterfaceOrientationIsPortrait(orientation);
}

If you forget to set the delegate, you’ll get this …
enter image description here
This gets called in your delegate when the master gets hidden …

- (void)splitViewController:(UISplitViewController *)sender
     willHideViewController:(UIViewController *)master
          withBarButtonItem:(UIBarButtonItem *)barButtonItem
       forPopoverController:(UIPopoverController *)popover
{
barButtonItem.title = master.title;
# this next line would only work in the Detail
# and only if it was in a UINavigationController self.navigationItem.leftBarButton = barButtonItem;
}

This gets called in your delegate when the master reappears .

    - (void)splitViewController:(UISplitViewController *)sender
         willShowViewController:(UIViewController *)master
      invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
    {
# this next line would only work in the Detail
# and only if it was in a UINavigationController self.navigationItem.leftBarButton = nil;
}

Updating the Detail when the Master is touched

  1. Target/Action!
    Example (code in the Master view controller)
  - (IBAction)doit
  {
      id detailViewController = self.splitViewController.viewControllers[1];
[detailViewController setSomeProperty:...]; 
# might want some Introspection first }
  1. Replace Segue (entirely replaces the Detail view controller)
    Segue 只會重新產生新的view, 而不會重新利用同一個view controller.

Popovers

Creating a Popover Segue in your Storyboard!

Just drag from the UI element you want to cause the popover to the scene you want to pop up. In your prepareForSegue:sender:, the argument will be isKindOf:UIStoryboardPopoverSegue.!
And UIStoryboardPopoverSegue has a @property you can use to get the UIPopoverController:
- (UIPopoverController *)popoverController;
Example:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue isKindOfClass:[UIStoryboardPopoverSegue class]]) {
        UIPopoverController *popoverController =
            ((UIStoryboardPopoverSegue *)segue).popoverController;
...
} }

參考:
http://lokanghung.blogspot.tw/2013/06/ios-delegate-protocol.html