0%

地圖資訊是手機很大量運用的資訊之一,接下來是來整理關於目前學到的MapKit View地圖的運用

  • 首先先拉一個新的ViewController,並將MapKit View拉近去

  • 接著在ViewController建立參數與MapKit View做對應,這邊需要注意的地方是用Map元件需要import MapKit```swift
    import UIKit
    import MapKit
    class MapViewController: UIViewController {

      @IBOutlet weak var uimap: MKMapView!//地圖元件
    

    override func viewDidLoad() {

      super.viewDidLoad()
    

    }

      override func didReceiveMemoryWarning() {
      super.didReceiveMemoryWarning()
      // Dispose of any resources that can be recreated.
    

    }
    }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

* 取得座標資訊是由一個叫要做CLLocationManager來控制的,又IOS8取得座標資訊必須先取得使用者的授權才可以,所以必須到Info.plist新增NSLocationAlwaysUsageDescription或NSLocationWhenInUseUsageDescription兩種鍵值,而前者表示不管APP在前景或背景執行都會持續取得座標資訊,而後者只有在需要時才會去取座標定位資訊,而這兩個鍵值分別對應到CLLocationManager的requestAlwaysAuthorization和requestWhenInUseAuthorization,這邊的範例已NSLocationWhenInUseUsageDescription為例 ```swift
import UIKit
import CoreLocation
import MapKit
class MapViewController: UIViewController,CLLocationManagerDelegate {

@IBOutlet weak var uimap: MKMapView!//地圖元件
var location : CLLocationManager!; //座標管理元件
override func viewDidLoad() {
super.viewDidLoad();

location = CLLocationManager();
location.delegate = self;
//詢問使用者是否同意給APP定位功能
location.requestWhenInUseAuthorization();
//開始接收目前位置資訊
location.startUpdatingLocation();
}

override func viewDidDisappear(animated: Bool) {
//因為GPS功能很耗電,所以被敬執行時關閉定位功能
location.stopUpdatingLocation();
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
//取得目前的座標位置
let c = locations[0] as CLLocation;
//c.coordinate.latitude 目前緯度
//c.coordinate.longitude 目前經度
let nowLocation = CLLocationCoordinate2D(latitude: c.coordinate.latitude, longitude: c.coordinate.longitude);
//將map中心點定在目前所在的位置
//span是地圖zoom in, zoom out的級距
let _span:MKCoordinateSpan = MKCoordinateSpan(latitudeDelta: 0.0005, longitudeDelta: 0.0005);
self.uimap.setRegion(MKCoordinateRegion(center: nowLocation, span: _span), animated: true);
}
}

接著別忘了去Info.plist新增NSLocationWhenInUsageDescription

[![](http://2.bp.blogspot.com/-FwRtS6qlxv0/VPUmFe5sNwI/AAAAAAAAEbI/ZBcSw4FmZKY/s400/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-03-03%2B%E4%B8%8A%E5%8D%8811.09.07.png)](http://2.bp.blogspot.com/-FwRtS6qlxv0/VPUmFe5sNwI/AAAAAAAAEbI/ZBcSw4FmZKY/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-03-03%2B%E4%B8%8A%E5%8D%8811.09.07.png)
  • 接著執行看看!!

    詢問是否授權取得座標資訊

    地圖中心點移到你目前的位置摟~

  • 順帶一提,如果需要把使用者的位置座標顯示出來,在mapkit view設定檔將User Location打勾即可!!

  • 如果你有實際run過這段程式應該會發現你滑動map時,它會一直彈回你目前所在的位置,原因是我們沒有指定移動多少距離才會更新座標位置,所以didUpdateLocations會一直被呼叫,也就一直被彈回你的所在位置摟,告訴app移動多少距離再更新座標資訊即可 ```swift
    location.distanceFilter = CLLocationDistance(10); //表示移動10公尺再更新座標資訊


如果要在換頁時讓PageA傳遞數值給PageB,並且在PageB顯示傳遞的參數時作法如下

  • 先在PageB的Controller新增一個Label,我們將用它來顯示PageA究竟傳了什麼過來```swift
    import UIKit
    class Page_B_ViewController: UIViewController {
    @IBOutlet weak var lblValue: UILabel! //顯示傳遞數值的Label
    var fromA_Value:String!;//儲存Page_A傳遞過來的數值
    override func viewDidLoad() {
      super.viewDidLoad();
      lblValue.text = fromA_Value;
    
    }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

* 接著在PageA Controller新增**prepareForSegue**事件 ```swift
import UIKit
class Page_A_ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
//NavBar
self.navigationController?.navigationBar.barTintColor = UIColor(red: 0.58, green: 0.761, blue: 0.231, alpha: 1)
let titleDic : NSDictionary = [NSForegroundColorAttributeName : UIColor.whiteColor()]; //字的顏色
self.navigationController?.navigationBar.titleTextAttributes = titleDic;
self.navigationController?.navigationBar.tintColor = UIColor.whiteColor() //按鈕的顏色
let barOptionIcon : UIBarButtonItem = UIBarButtonItem(image: UIImage(named: "icon-options"), style: UIBarButtonItemStyle.Plain, target: self, action: "PushToOptionController:");
self.navigationController?.navigationBar.topItem?.setRightBarButtonItem(barOptionIcon, animated: true) ;
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//右上角Button按下時觸發的事件
func PushToOptionController(sender: UIBarButtonItem) {
self.performSegueWithIdentifier("toPageB", sender: self);
}
//準備跳轉頁面的設定
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "toPageB"){
var page_b:Page_B_ViewController? = segue.destinationViewController as? Page_B_ViewController
if(page_b != nil){
page_b?.fromA_Value = "來自A的數值";
}
}
}
}

  • 完成!!!

  • 先拉一個Navigation Controller到StoryBoard,並將起始指標指向它

  • 接著拉個ViewA並且設定他為root view並且執行看看

    執行結果首頁就是剛剛指定root view的那一頁了

  • 接著在拉第二個ViewB,並將ViewA與ViewB做Push的關聯

    接著設定這個push segue的identifier

  • 在ViewA做已下修改 ```swift
    import UIKit
    class Page_A_ViewController: UIViewController {

    override func viewDidLoad() {
    super.viewDidLoad()
    //NavBar
    self.navigationController?.navigationBar.barTintColor = UIColor(red: 0.58, green: 0.761, blue: 0.231, alpha: 1)
    let titleDic : NSDictionary = [NSForegroundColorAttributeName : UIColor.whiteColor()]; //字的顏色
    self.navigationController?.navigationBar.titleTextAttributes = titleDic;
    self.navigationController?.navigationBar.tintColor = UIColor.whiteColor() //按鈕的顏色
    //設定右上角的按鈕let barOptionIcon : UIBarButtonItem = UIBarButtonItem(image: UIImage(named: “icon-options”), style: UIBarButtonItemStyle.Plain, target: self, action: “PushToOptionController:”);
    self.navigationController?.navigationBar.topItem?.setRightBarButtonItem(barOptionIcon, animated: true) ;
    }

    //右上角Button按下時觸發的事件
    func PushToOptionController(sender: UIBarButtonItem) {
    self.performSegueWithIdentifier(“toPageB”, sender: self);
    }

    }

```

  • 完成後試試看,點擊右上角的按鈕即可跳到第二頁了!!

  • 方法一:打開Storyboard移動起始指標,指到的Controller預設就會用那個ViewController為起始頁面

  • 方法二:
    先對在Storyboard的Controller設定Storyboard ID

    然後找到AppDelegate.swift檔案改寫didFinishLaunchingWithOptions ```swift
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { let storyboard = UIStoryboard(name:”Main” , bundle: nil);
    self.window? = UIWindow(frame: UIScreen.mainScreen().bounds);
    //指定Storyboard ID
    self.window?.rootViewController = storyboard.instantiateViewControllerWithIdentifier(“testa”) as? UIViewController;
    self.window?.makeKeyAndVisible();
    return true
    }


前幾篇是透過StoryBoard來建立客製的cell view
這篇則是要寫如何透過xib來完成cell view

  • 一樣先建立一個對應的Class ```swift
    import Uikit
    public class XibCell : UITableViewCell{
    @IBOutlet weak var lblTitle: UILabel! //title的label
    @IBOutlet weak var imgIcon: UIImageView! //icon的小圖片

     public override init(){
    super.init();
    

    }
    public required init(coder aDecoder: NSCoder) {

    super.init(coder: aDecoder);
    

    }
    }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

* 建立一個.xib的View
[![](http://3.bp.blogspot.com/-i547UQ5vRNc/VPQbuDo0_LI/AAAAAAAAEXo/zna_SQsYioA/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-03-02%2B%E4%B8%8B%E5%8D%884.12.47.png)](http://3.bp.blogspot.com/-i547UQ5vRNc/VPQbuDo0_LI/AAAAAAAAEXo/zna_SQsYioA/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-03-02%2B%E4%B8%8B%E5%8D%884.12.47.png)
* 指定xib的class為XibCell
[![](http://3.bp.blogspot.com/-CkRdJKdxYcs/VPQcWDhQ8rI/AAAAAAAAEXw/e334Wa4ZKFc/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-03-02%2B%E4%B8%8B%E5%8D%884.14.39.png)](http://3.bp.blogspot.com/-CkRdJKdxYcs/VPQcWDhQ8rI/AAAAAAAAEXw/e334Wa4ZKFc/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-03-02%2B%E4%B8%8B%E5%8D%884.14.39.png)
* 把UI的關聯拉起來
[![](http://2.bp.blogspot.com/-qDluWRV2fRc/VPQeGTJOPfI/AAAAAAAAEX8/Cna7u8bnTWc/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-03-02%2B%E4%B8%8B%E5%8D%884.23.35.png)](http://2.bp.blogspot.com/-qDluWRV2fRc/VPQeGTJOPfI/AAAAAAAAEX8/Cna7u8bnTWc/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-03-02%2B%E4%B8%8B%E5%8D%884.23.35.png)
* controller的寫法大同小異,但請注意cellForRowAtIndexPath的寫法改變 ```swift
import UIKit
class xibTableViewController: UIViewController ,UITableViewDelegate , UITableViewDataSource{
@IBOutlet weak var uitable: UITableView!
var data :[String]!; //資料來源
override func viewDidLoad() {
super.viewDidLoad();
data = [];
data.append("籃球");
data.append("棒球");
data.append("足球");
uitable.delegate = self;
uitable.dataSource = self;
}
//這個table包含幾個section
func numberOfSectionsInTableView(tableView: UITableView!) -> Int {
return 1
}
//每個section有幾個row
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count;
}
//每個row顯示的內容
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let identifier = "cellid";
var cell : XibCell? = self.uitable.dequeueReusableCellWithIdentifier(identifier) as? XibCell;
if cell == nil{
//載入xib當作cell view
uitable.registerNib(UINib(nibName: "xibcell", bundle: nil), forCellReuseIdentifier: identifier);
cell = self.uitable.dequeueReusableCellWithIdentifier(identifier) as? XibCell;
}
//indexPath.row 可以知道目前是要製作第幾列的view
cell?.lblTitle?.text = data[indexPath.row];
cell?.imgIcon.image = UIImage(named: "icon-factory");
return cell!;
}
}

最後呈現結果

常常看到一些APP可以點擊TableCell時會動態展開看到更多的內容
製作方式如下

  • 在Storyboard將cell的高度調整後,把要顯示的更多資料擺進去,此例子是多了兩顆按鈕
  • [重要]記得要將tablecell的Clip Subviews打勾,這樣才能呈現擇疊的效果,如果沒打勾隱藏起來的按鈕都會跑出來並且蓋到其他cell上面
  • 新增一個CellsValue Class ```swift
    import Foundation
    public class CellsValue{
    var title:String!;//標題
    var expand:Bool = false;//cell是否展開,預設為false
    init(){}
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

* 將controller改寫如下
```swift
import UIKit
class ViewController: UIViewController , UITableViewDelegate , UITableViewDataSource{
@IBOutlet weak var uitable: UITableView!
var data : [CellsValue]!;
override func viewDidLoad() {
super.viewDidLoad()
uitable.dataSource = self;
uitable.delegate = self;
data = [];
var c = CellsValue();
c.title = "便當";
data.append(c);
c = CellsValue();
c.title = "雞腿便當";
data.append(c);
c = CellsValue();
c.title = "排骨便當";
data.append(c);
}

//這個table包含幾個section
func numberOfSectionsInTableView(tableView: UITableView!) -> Int {
return 1
}
//每個section有幾個row
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count;
}
//每個row顯示的內容
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let identifier = "Customer_Cell";
var cell:CustomerCell? = uitable.dequeueReusableCellWithIdentifier(identifier) as? CustomerCell;
if(cell == nil){
cell = CustomerCell(style: UITableViewCellStyle.Default, reuseIdentifier: identifier);
}
//indexPath.row 可以知道目前是要製作第幾列的view
cell?.lblTitle?.text = data[indexPath.row].title;
//依據是第幾個row決定icon的圖片
switch indexPath.row{
case 0:
cell?.imgIcon.image = UIImage(named: "icon-factory");
break;
case 1:
cell?.imgIcon.image = UIImage(named: "icon-location");
break;
case 2:
cell?.imgIcon.image = UIImage(named: "icon-money");
break;
default:
break;
}
return cell!;
}
}

override cell高度的事件heightForRowAtIndexPath ```swift
//每個cell的height
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
let cellValue = data[indexPath.row];
//如果cell是展開的話,回傳高度為120
if(cellValue.expand){
return 120;
}
else{
//否則回傳44
return 44;
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14

* override didSelectRowAtIndexPath事件 ```swift
//cell被選擇的狀況
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
data[indexPath.row].expand = !data[indexPath.row].expand; //將目前狀態相反後存回去
var cell = tableView.cellForRowAtIndexPath(indexPath) as? CustomerCell;
if(cell != nil){
//為了讓cell展開或閉合的效果能呈現,所以要呼叫reloadRowsAtIndexPaths讓cell重繪
uitable.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
//不要讓cell有選擇起來的反黑的效果,用這這個語法可以取消選擇
uitable.deselectRowAtIndexPath(indexPath, animated: false);
}
}

  • 大功告成,點擊後會展開跟收合的Cell就完成了

基於上一篇的基礎語法可以做出簡單的table,但果要客製化每個cell的樣式呢?
已storyboard為例

  • 在storyboard拉cell並且佈置成自己要的樣子

  • 建立相對應的cell Class ```swift
    import Foundation
    import UiKit
    public class CustomerCell:UITableViewCell{
    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {

    super.init(style: style, reuseIdentifier: reuseIdentifier);
    

    }

     //繼承UITableViewCell一定要override的function
    

    public required init(coder aDecoder: NSCoder) {

    super.init(coder: aDecoder);
    

    }
    }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

* 在storyboard指定該cell的class為CustomerCell,並且設定Identifier [![](http://1.bp.blogspot.com/-ccc0-6L5vYk/VPQCFF6QKwI/AAAAAAAAEWY/sOW8wxdPRSc/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-03-02%2B%E4%B8%8B%E5%8D%882.19.52.png)](http://1.bp.blogspot.com/-ccc0-6L5vYk/VPQCFF6QKwI/AAAAAAAAEWY/sOW8wxdPRSc/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-03-02%2B%E4%B8%8B%E5%8D%882.19.52.png)
[![](http://4.bp.blogspot.com/-ZcUAw2yn9OU/VPQCnODddHI/AAAAAAAAEWg/Xs5EhzwGDsI/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-03-02%2B%E4%B8%8B%E5%8D%882.25.39.png)](http://4.bp.blogspot.com/-ZcUAw2yn9OU/VPQCnODddHI/AAAAAAAAEWg/Xs5EhzwGDsI/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-03-02%2B%E4%B8%8B%E5%8D%882.25.39.png)
* 把對應的控制項建立起關聯 ```swift
import Foundation
import UiKit
public class CustomerCell:UITableViewCell{
@IBOutlet weak var lblTitle: UILabel! //title的label
@IBOutlet weak var imgIcon: UIImageView! //icon的小圖片

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier);
}

public required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder);
}
}

  • 改寫cellForRowAtIndexPath這個事件 ```swift
    //每個row顯示的內容
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let identifier = “Customer_Cell”;
    var cell:CustomerCell? = uitable.dequeueReusableCellWithIdentifier(identifier) as? CustomerCell;
    if(cell == nil){
    cell = CustomerCell(style: UITableViewCellStyle.Default, reuseIdentifier: identifier);
    
    }
    //indexPath.row 可以知道目前是要製作第幾列的view
    cell?.lblTitle?.text = data[indexPath.row];
    //依據是第幾個row決定icon的圖片
    switch indexPath.row{
    case 0:
       cell?.imgIcon.image = UIImage(named: "icon-factory");
       break;
    case 1:
       cell?.imgIcon.image = UIImage(named: "icon-location");
       break;
    case 2:
       cell?.imgIcon.image = UIImage(named: "icon-money");
       break;
    default:
       break;
    
    }
    return cell!;
    }

```

  • 最後呈現的結果

首先必須讓Controller符合UITableViewDelegate , UITableViewDataSource的規範,並將table元件的delegate與datasource指定為自己這個controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class OptionViewController: UIViewController , UITableViewDelegate , UITableViewDataSource {
@IBOutlet weak var UIOptionTable: UITableView!
var data : [String]!; //資料來源
override func viewDidLoad() {
super.viewDidLoad();
self.UIOptionTable.delegate = self;
self.UIOptionTable.dataSource = self;

data = [];
data.append("便當");
data.append("雞腿便當");
data.append("排骨便當");
}
}

再來override幾個主要的事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//這個table包含幾個section
func numberOfSectionsInTableView(tableView: UITableView!) -> Int {
return 1
}

//每個section有幾個row
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count;
}

//每個row顯示的內容
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let identifier = "cellid";

var cell:UITableViewCell? = uitable.dequeueReusableCellWithIdentifier(identifier) as? UITableViewCell;
if(cell == nil){
cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: identifier);
}

//indexPath.row 可以知道目前是要製作第幾列的view
cell?.textLabel?.text = data[indexPath.row];
return cell!;
}

結果~

最近因為公司需要,開始學習如何用Xamarin開發 IOS,雖然主打用C#開發APP,但無論生命週期跟呼叫的function跟傳統的windows forms或ASP MVC都有相當大的差異性,有很大的一段GAP要跨過就是.

這邊紀錄一下我開發**IOS**時遇到的問題跟心得
  • AppDelegate,程式的進入點

    1
    2
    3
    4
    5
    6
    public override bool FinishedLaunching(UIApplication app, NSDictionary options){    // 指定APP符合螢幕大小
    UIWindow window = new UIWindow(UIScreen.MainScreen.Bounds);
    // 指定APP Root的View,這邊Config.MainStoryboard是我為了避免每次重複一直寫一樣的code
    // 所以把抓取Storyboard的程式碼整合到config,原本應該是UIStoryboard.FromName ("MainStoryboard", null)
    window.RootViewController = Config.MainStoryboard.InstantiateInitialViewController () as UIViewController; // make the window visible window.MakeKeyAndVisible(); return true;}

  • Storyboard,編輯流程的地方,只要把對應的Controller抓進來並且命名,Xamarin Studio會將Class檔案自動建好

  • 取得Storyboard裡面的ViewController方法

    1
    2
    UIStoryboard.FromName ("MainStoryboard", null).InstantiateViewController (viewcontroller_name) as UIViewController;

  • IOS頁面間的流程靠的是對NavigationController的操作,以下是針對NavigationController的一些設定
    ```csharp
    public override void ViewDidLoad ()
    {
    //edit control in viewdidload //NavigationBar的背景色
    NavigationController.NavigationBar.BarTintColor = new UIColor(0.58f,0.761f,0.231f,1f);

     //字的顏色
    

    NavigationController.NavigationBar.TitleTextAttributes = new UIStringAttributes (){ ForegroundColor = UIColor.White }; //NavigationBar Button的顏色
    NavigationController.NavigationBar.TintColor = UIColor.White; //設定NavigationBar的右邊按鈕為何
    UIBarButtonItem barOptionIcon = new UIBarButtonItem (UIImage.FromBundle (“icon-options”), UIBarButtonItemStyle.Plain,
    (sender, args) => { // button clicked NavigationController.PushViewController(Config.GetStoryboardViewController(“OptionViewController”),true); });
    NavigationController.NavigationBar.TopItem.SetRightBarButtonItem (barOptionIcon,true); //OptionIcon
    }

1
2
3
4
5
6
7
8
9
10
11

* IOS抓取對應圖片的方式
[![](//3.bp.blogspot.com/-yKVU6385RPk/VGRo5f3lZII/AAAAAAAAET0/Kz-_aQWVyLA/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2014-11-13%2B%E4%B8%8B%E5%8D%884.15.59.png)](https://3.bp.blogspot.com/-yKVU6385RPk/VGRo5f3lZII/AAAAAAAAET0/Kz-_aQWVyLA/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2014-11-13%2B%E4%B8%8B%E5%8D%884.15.59.png)```csharp
//FromBundle的方式IOS會自動對應不同的裝置抓取預備好給他的圖
//圖片檔名命名方式//[imageName]~iphone.png
//[imageName]~ipad.png
//[imageName]@2~ipad.png for retina顯示器
UIImage.FromBundle ("icon-options");
//FromFile不管任何解析度都是用這張來顯示,所以用前者的方式較佳
UIImage.FromFile ("icon-options.png");

  • TableViewController的製作方式
    ```csharp
    //製作TableSource的Class
    public class TableSource : UITableViewSource
    {
    string cellIdentifier = “OptionsTableCell”;
    public List TABLE_ITEMS{ get; set;} //每列資料 public event EventHandler Cell_RowSelected;//給外層cell click事件

     public TableSource ()
    

    {

    TABLE_ITEMS = new List<tablecell> ();
    

    }

     public override nint RowsInSection (UITableView tableview, nint section)
    

    {

    return TABLE_ITEMS.Count;
    

    }

     public override UITableViewCell GetCell (UITableView tableView, Foundation.NSIndexPath indexPath)
    

    {

    UITableViewCell cell = tableView.DequeueReusableCell (cellIdentifier);
    
        //if there are no cells to reuse , cerate a new one
    if (cell == null) cell = new UITableViewCell (UITableViewCellStyle.Default, cellIdentifier);
    
        cell.TextLabel.Text = TABLE_ITEMS [indexPath.Row].TITLE;
    cell.TextLabel.Font = UIFont.SystemFontOfSize(15f);
    cell.TextLabel.TextColor = new UIColor (0.453f, 0.453f, 0.453f, 1);
    cell.ImageView.Image = UIImage.FromBundle (TABLE_ITEMS[indexPath.Row].IMAGE); //cell front Image
    cell.Accessory = UITableViewCellAccessory.DisclosureIndicator;
    return cell;
    

    }

      public override void RowSelected (UITableView tableView, Foundation.NSIndexPath indexPath)
    

    {
    //把值拋到OptionViewController的Cell_RowSelected的事件
    if (Cell_RowSelected != null) Cell_RowSelected(this,new TableRowSelectedEventArgs(){ indexPath = indexPath});
    tableView.DeselectRow (indexPath, true); //cancel select row style
    }
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    ```csharp
    //製作TableSource的Class
    public class TableSource : UITableViewSource
    {
    string cellIdentifier = "OptionsTableCell";
    public List<tablecell> TABLE_ITEMS{ get; set;} //每列資料 public event EventHandler<tablerowselectedeventargs> Cell_RowSelected;//給外層cell click事件

    public TableSource ()
    {
    TABLE_ITEMS = new List<tablecell> ();
    }

    public override nint RowsInSection (UITableView tableview, nint section)
    {
    return TABLE_ITEMS.Count;
    }

    public override UITableViewCell GetCell (UITableView tableView, Foundation.NSIndexPath indexPath)
    {
    UITableViewCell cell = tableView.DequeueReusableCell (cellIdentifier);

    //if there are no cells to reuse , cerate a new one
    if (cell == null) cell = new UITableViewCell (UITableViewCellStyle.Default, cellIdentifier);

    cell.TextLabel.Text = TABLE_ITEMS [indexPath.Row].TITLE;
    cell.TextLabel.Font = UIFont.SystemFontOfSize(15f);
    cell.TextLabel.TextColor = new UIColor (0.453f, 0.453f, 0.453f, 1);
    cell.ImageView.Image = UIImage.FromBundle (TABLE_ITEMS[indexPath.Row].IMAGE); //cell front Image
    cell.Accessory = UITableViewCellAccessory.DisclosureIndicator;
    return cell;
    }

    public override void RowSelected (UITableView tableView, Foundation.NSIndexPath indexPath)
    {
    //把值拋到OptionViewController的Cell_RowSelected的事件
    if (Cell_RowSelected != null) Cell_RowSelected(this,new TableRowSelectedEventArgs(){ indexPath = indexPath});
    tableView.DeselectRow (indexPath, true); //cancel select row style
    }
    }

    1
    2
    //Table Cell Classpublic class TableCell{   public string TITLE { get; set; } //標題   public string IMAGE { get; set;} //圖片   public TableCell () { }
    public TableCell (string title , string image) { TITLE = title; IMAGE = image; }}

    然後在ViewController這麼做 ```csharp
    public OptionViewController (IntPtr handle) : base (handle){ _tableview = SetTable (); this.Add (_tableview); //把Table加進去View裡面}///

    /// Set Table Data/// /// The table.private UITableView SetTable(){ UITableView tv = new UITableView (View.Bounds); TableSource _source = new TableSource (); List celllist = new List (); //將options的menu選項加進table cell裡面 foreach (Options item in Enum.GetValues(typeof(Options))) { string[] descript = Tools.GetEnumDescription (item).Split(new String[]{“;”}, StringSplitOptions.RemoveEmptyEntries);

        celllist.Add(new TableCell (descript[0], descript[1]));//標題;圖片    }    _source.TABLE_ITEMS = celllist; tv.Source = _source;    //cell click觸發的事件    _source.Cell_RowSelected += (object sender, TableRowSelectedEventArgs e) =&gt;    {       switch ((Options)e.indexPath.Row)       {          case Options.BuildAge:NavigationController.PushViewController(Config.GetStoryboardViewController("Options_BuildAgeViewController"),true);       break;       }
    

    }; return tv;}

```

最近有寫Excel報表的需求,ClosedXML真的是個不錯的套件

1
2
3
4
5
6
7
8
9
10
var workbook = new XLWorkbook(); //new Excel
var sheet_A = workbook.Worksheets.Add("Sheet_A"); //新增Sheet到 Excel

//塞資料到Sheet中
worksheet.Cell(_index, 1).Value = "欄位一";
worksheet.Cell(_index, 2).Value = "欄位二";
worksheet.Cell(_index, 3).Value = "欄位三";
worksheet.Cell(_index, 4).Value = "欄位四";
worksheet.Cell(_index, 5).Value = "欄位五";

用法還滿簡單的,如果有更深入的用法想瞭解也可以到ClosedXml網站看文件
在使用的過程有遇到一個情況就是從DB裡面撈出大量的資料倒入Excel時,匯出打開檔案會顯示Excel已經損毀,可是直接把DB撈出來的資料用複製貼上卻可以完整地貼到Excel中,存檔再打開也不會壞掉。這個問題搞了好久…最後查到大陸網站得到以下的解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/// <summary>
/// 提示??,??信息如下: 十六?制值 0x0B 是?效的字符??
///?生原因是xml文件中包含低位非打印字符造成的
///?理方法:在?生xml文件的?候,??低位非打印字符
/// </summary>
/// <param name="tmp" />
/// <returns></returns>
public static string ReplaceLowOrderASCIICharacters(string tmp)
{
StringBuilder info = new StringBuilder();
foreach (char cc in tmp)
{
int ss = (int)cc;
if (((ss >= 0) && (ss <= 8)) || ((ss >= 11) && (ss <= 12)) || ((ss >= 14) && (ss <= 32)))
info.AppendFormat(" ", ss);//&#x{0:X};
else info.Append(cc);
}
return info.ToString();
}

把字元丟到這個function去過濾後就可以避免錯誤了!!