2015年12月29日 星期二

【Oracle ERP Note 】APP-FND-02913: User xxx : The Customer is linked to Customer: yyy (Customer ID) Ther Person is linked to Employee zzz (Employed = zzz) Customer and Employee must be linked to the same persion

在 EBS 新增 user,顯示錯誤訊息如下:

APP-FND-02913: User xxx : The Customer is linked to Customer: yyy (Customer ID) Ther Person is linked to Employee zzz (Employed = zzz) Customer and Employee must be linked to the same persion

Study: 

參考網站 [1] ,

Error Message: 

CTGIMT008W: The account was added, but some attributes failed. 
Attributes: erOraEBSCust
The log file describes the error message as follows: 
java.sql.SQLException: ORA-20001: APP-FND-02913: User user name: The Customer is linked to Customer customer name (Customer ID). The Person is linked to Employee employee name (Employee ID). 
Customer and Employee must be linked to the same person.

Recommended Action:

This error occurs when you specify different values for the Person and the Customer attributes. Ensure that values of both the attributes are same.

Solution:

在 User 視窗,有個欄位 Customer, 更正其值的內容。此次解決刪除其內容


Reference:

1. Troubleshooting the Oracle eBS Adapter errors, http://www-01.ibm.com/support/knowledgecenter/SSTFWV_5.1.0/com.ibm.itim.doc/usr_oracleebs_5137.htm

2015年10月6日 星期二

【Oracle ERP Note 】上 Oracle Patch 16328729 後,以 IE 登入的畫面顯示被更動?

Problem:

上 Oracle Patch 16328729 後,以 IE 登入的畫面顯示被更動? 例如:使用者 Personalized Item 反白,底色淡,無法識別,而 Logout 登出選項也不見了

Solution: 1. 參考 Note: DOC ID 742107.1 的說明,清除 cache 2. 先由 client 端開始,在 IE 點選 工具 > 網際網路選項,然後在瀏覽歷程記錄中,點選刪除按鈕,刪除Temporary Internet Files(T) 這些瀏覽網站時的暫存檔 3. 若仍有異常,那就參考 DOC ID 742107.1 的說明清除 cache Test:

2015年9月9日 星期三

第 2 個程式:SimpleTableView


專案步驟:

1. UI TableView 元件製作:拖曳 UITableView Control 至 Storyboard
2. 設定 Table View 的 Attribute : prototype cell = 1 (原來的值是 0)
3. 設定 Table View 的 Cell Style : Basic
4. 設定 cell 的識別名稱 Identifier = cell
5. 試 Run
6. 在 code 中加入 Table View 需遵循的 protocol : 
   class ViewController : UIViewController, UITableViewDataSource, 
                          UITableViewDelegate
7. Data 準備 :提供 data
8. Protocol 實作 : delegate
9. 建立 UI 與 Code 的 connect : 將 TableView 此 control 拉至 Outline 的  ViewController
10. 試 Run
11. 刪除 Status Bar
12. 試 Run

開啟新專案:

1. UI TableView 元件製作:拖曳 UITableView Control 至 Storyboard
2. 設定 Table View 的 Attribute : prototype cell = 1 (原來的值是 0)
3. 設定 Table View 的 Cell Style : Basic
4. 設定 cell 的識別名稱 Identifier = cell
5. 試 Run
6. 在 code 中加入 Table View 需遵循的 protocol : class ViewController : UIViewController, UITableViewDataSource, UITableViewDelegate
7. Data 準備 :提供 data 8. Protocol 實作 : delegate
9. 建立 UI 與 Code 的 connect : 將 TableView 此元件拉至 Outline 的 ViewController
顯示 connect to data source 與 data delegate
10. 試 Run
11. 刪除 Status Bar
12. 試 Run
後記: 這程式使用 UITableView 元件,增加 protocol 協定的概念。當遵循此 protocol 時,其方法需實作。 參考: 1. UITableView, https://developer.apple.com/library/prerelease/ios/samplecode/TableMultiSelect/Introduction/Intro.html 2. UITableView Class Reference, https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UITableView_Class/ 3. UITableViewDataSource Class Reference, https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UITableViewDataSource_Protocol/index.html#//apple_ref/occ/intf/UITableViewDataSource
4. UITableViewDelegate Reference Class, https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UITableViewDelegate_Protocol/index.html#//apple_ref/occ/intf/UITableViewDelegate

第 3 個程式: UITableViewController


這裡將 UITableView 改寫為 UITableViewController。此程式需要下列步驟:

1. 刪除 UI 元件 (ViewController)與其相關的 Code (ViewController.swift),這些都是新增 project 的 default 設定。將這些檔案 Move to Trash
2. 新增 UI 元件:拖曳 TableVewController 元件至 Storyboard
3. 指定初始的 Controller : 設定 Is Initial ViewController
4. 新增 Code : 新增一個自訂的 Class
5. 連接 UI 與 Code : 將 UI 的 View Controller 的屬性(Attribute) class 被指定此新的 class
6. 設定 UI 的 Attributes : style = Basic, Identifier = Cell
7. 新增 data source : 提供 Table View 要顯示的資料
8. 檢查 Child Class 除繼承 Parent Class 外,是否遵循 data source 與 delegate 協定
9. 覆寫 overwrite 此 data source 協定的 function
10. 試 Run

新增專案:

1. 刪除 UI 元件 (ViewController)與其相關的 Code (ViewController.swift),這些都是新增 project 的 default 設定。將這些檔案 Move to Trash
若新增一個 Storyboard,其 UI 編輯器沒有任何 UI 元件:
2. 新增 UI 元件:拖曳 TableVewController 元件至 Storyboard 為方便 UI 顯示,指定此專案針對 iPhone 開發,可先關掉 Use Size Class 選項。 即點選 View > Utilities > Show File Inspector , 然後不勾選 User Size Class:
接下來,搜尋 TableViewController:
接著拖曳 TableViewController 元件至 Storyboard:
3. 指定初始的 Controller : 設定 Is Initial ViewController
4. 新增 Code : 新增一個自訂的 TableViewController Class 新增 Cocoa Class 檔案:
設定此新增 Class 的屬性:
此時這新 Class 被新增:
5. 連接 UI 與 Code : 將 UI 的 View Controller 的屬性(Attribute) class 被指定此新的 class
6. 設定 UI 的 Attributes : style = Basic, Identifier = Cell
7. 新增 data source : 提供 Table View 要顯示的資料 8. 檢查 Child Class 除繼承 Parent Class 外,是否遵循 data source 與 delegate 協定
9. 覆寫 overwrite 此 data source 協定的 function 複寫 numberOfRowsInSection:
覆寫 cellForRowAtIndexPath:
覆寫 numberOfSectionsInTableView:
10. 試 Run
後記: Table View 可用 UITableView 實作,亦可用 UITableViewController 實作,兩者皆能製作出我們所要的結果。 iPhone App 的開發,除要熟習 Xcode 的操作之外,另外整個開發的 Flow 要清楚。例如:UI 的建立,Code 的建立,而這兩者之間又該如何建立關係等等。學開發先不求快,但要把每行程式都看懂,看得透徹,明白為何有這行 Code,那將來在開發時,就能得心應手,應用自如了。

製作 Image 的圖變成圓形


將 Image 的圖形由方塊變成圓形時,直覺上會認為由 UIImageView / UIImage,找到其相關的 Attribute 修改。但,事實上這 Attribute 已定義在其 Parent Class 父類別 UIView 中 [1]:

同樣,Image 的 layer 圖層這 Attribute 也被定義在父類別 UIView 中:
若我們要製作圓形的 Image,就要修改 CALayer [2] 這類別下的 cornerRadius 屬性:
由此知道, cornerRaidus 的資料型態 data type 被宣告為 CGFloat (浮點數),但若要製作 Image 為圓形,那其值又該如何設定? 此時理論上我們也會誤以為 Image 大小的屬性會在 UIImageView / UIImage 中宣告,但,這屬性亦在其父類別 UIView 中宣告:
而此 frame 屬性被宣告為:
接著我們往下查看 CGRect 這類別的定義:
再查看 CGSize [5] 的定義:
由此我們知道,要製作圓形的 Image,首先我們要指定 cornerRadius 的值,而這值是由我們現有 Image 的尺寸,由其中心點,畫成圓圈計算得來:

cell.myImage.layer.cornerRadius = cell.myImage.frame.size.width / 2
設定完之後,我們將邊角切掉:

cell.myImage.clipsToBounds = true
這樣圓形的 Image 就製作完成。 後記: 看來很簡單的製作,卻拉雜循序漸進寫了一堆! 若能舉一反三,碰到新的 UI Control 都能循著這思路,把 App 做出來。市面上的書大都只把這 2 行程式碼寫出,就算交代清楚,但怎麼來,對若是初入門的人而言,既使照書上做,頂多也只是學到打字。學 App 製作,不就是要學會如何釣魚,而不是只懂的吃魚嗎? 不過,每本書都各有其優點,都是作者辛苦的精華,在此僅做個補充。 參考: 1. UIView - ClipsToBounds , https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIView_Class/#//apple_ref/occ/instp/UIView/clipsToBounds 2. CALayer, https://developer.apple.com/library/prerelease/ios/documentation/GraphicsImaging/Reference/CALayer_class/index.html#//apple_ref/swift/cl/c:objc(cs)CALayer 3. UIImageView, https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIImageView_Class/ 4. CGRect, https://developer.apple.com/library/prerelease/ios/documentation/GraphicsImaging/Reference/CGGeometry/index.html#//apple_ref/swift/struct/c:@S@CGRect 5. CGSize, https://developer.apple.com/library/prerelease/ios/documentation/GraphicsImaging/Reference/CGGeometry/index.html#//apple_ref/c/tdef/CGRect

第 4 個程式:Table View 中 Cell 的選取


協定 UITableViewDelegate 關於選取Selection 的 被選 / 取消需要實作的函數包含下列:

例如: 假設當 User 點選 Table View 上的 Cell 之後,系統會有何反應? 我們可在 talbeView(_: didSelectionAtIndexPath:) 此函數內寫 code,實作我們要的功能。
即,我們接下來要針對以下定義,實作其內容:

option func tableView(_ tableView: UITableView, 
                         didSelectRowAtIndexPath indexPath: NSIndexPath)


    override func tableView(tableView: UITableView,
        didSelectRowAtIndexPath indexPath: NSIndexPath) {
            
            let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
            if cell.accessoryType == UITableViewCellAccessoryType.None {
                cell.accessoryType = UITableViewCellAccessoryType.Checkmark
            } else {
                cell.accessoryType = UITableViewCellAccessoryType.None
            }
            tableView.deselectRowAtIndexPath(indexPath, animated: true)
    }

相反地,若我們希望取消選取呢?


    override func tableView(tableView: UITableView,
        didDeselectRowAtIndexPath indexPath: NSIndexPath) {
            let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
            if cell.accessoryType == UITableViewCellAccessoryType.None {
                cell.accessoryType = UITableViewCellAccessoryType.Checkmark
            } else {
                cell.accessoryType = UITableViewCellAccessoryType.None
            }
            tableView.deselectRowAtIndexPath(indexPath, animated: false)
    }
最後我來來驗證結果:
後記: 表格 Table View Cell 的選取與取消相當實用。很多書籍另設一個 Boolean 變數,來紀錄判別 Cell 的狀態,而不實作 tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath)。這樣有些缺乏 iOS 的精神。在反覆思考測試後,看到結果與自己預期,這喜悅難以言喻。 附註: 程式碼:MyTableViewController.swift

//
//  MyTableViewController.swift
//  SimpleTableViewControllerDemo
//
//  Created by Elvis Meng on 2015/9/6.
//  Copyright (c) 2015年 Elvis Meng. All rights reserved.
//

import UIKit

class MyTableViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate {
    
    var vocabulary = ["book","pen","queen"]

    override func viewDidLoad() {
        super.viewDidLoad()

        // Uncomment the following line to preserve selection between presentations
        // self.clearsSelectionOnViewWillAppear = false

        // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
        // self.navigationItem.rightBarButtonItem = self.editButtonItem()
        
    }

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

    // MARK: - Table view data source

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        // #warning Potentially incomplete method implementation.
        // Return the number of sections.
        return 1
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete method implementation.
        // Return the number of rows in the section.
        return self.vocabulary.count
    }
   
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        
        let cellIdentifier = "Cell"
        let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! UITableViewCell

        // Configure the cell...
        cell.textLabel?.text = vocabulary[indexPath.row]
        
        return cell
    }

    override func tableView(tableView: UITableView,
        didSelectRowAtIndexPath indexPath: NSIndexPath) {
            
            let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
            if cell.accessoryType == UITableViewCellAccessoryType.None {
                cell.accessoryType = UITableViewCellAccessoryType.Checkmark
            } else {
                cell.accessoryType = UITableViewCellAccessoryType.None
            }
            tableView.deselectRowAtIndexPath(indexPath, animated: true)
    }
    
    override func tableView(tableView: UITableView,
        didDeselectRowAtIndexPath indexPath: NSIndexPath) {
            let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
            if cell.accessoryType == UITableViewCellAccessoryType.None {
                cell.accessoryType = UITableViewCellAccessoryType.Checkmark
            } else {
                cell.accessoryType = UITableViewCellAccessoryType.None
            }
            tableView.deselectRowAtIndexPath(indexPath, animated: false)
    }

    /*
    // Override to support editing the table view.
    override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if editingStyle == .Delete {
            // Delete the row from the data source
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        } else if editingStyle == .Insert {
            // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
        }    
    }
    */

    /*
    // Override to support rearranging the table view.
    override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {

    }
    */

    /*
    // Override to support conditional rearranging of the table view.
    override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        // Return NO if you do not want the item to be re-orderable.
        return true
    }
    */

    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        // Get the new view controller using [segue destinationViewController].
        // Pass the selected object to the new view controller.
    }
    */

}
參考: 1. UITableViewDelegate, https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UITableViewDelegate_Protocol/ 2. UITableViewCell, https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UITableViewCell_Class/ 3. http://www.fanli7.net/a/bianchengyuyan/C__/20141215/491181.html 4. iOS Swift Tutorial - Building a Checklists App Part 1b, http://blog.mayankkapoor.com/post/89993926313/ios-swift-tutorial-building-a-checklists-app

第 5 個程式:Table View 中 Cell 的刪除 1


要刪除 Table View Cell 的資料,該如何做? 其執行步驟如下:

1. 開啟 Table View 的 Data Model 為 Edit 編輯模式
2. 在此模式下刪除資料
3. UI 畫面重整 Refresh

Table View Cell 的資料來源依據 MVC (Model-View-Controller) 這架構,其來源是由其協定 UITableViewDataSource 實作。參考 UITableViewDataSource [1] 文件,其提供下列方法:

方法 tableView(_:commitEditingStyle:forRowAtIndexPath:) 會將此 Data Model 切換成 Edit 編輯模式,讓我們可以修改資料,此方法詳細內容如下:
由以上說明得知: 當開啟此 Edit 編輯模式之後,除 insertion (green plus) control 外,亦提供 deletion (red minus) control 用來刪除 Cell 上的資料。 我們使用 func tableView(_ tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) 這方法來開啟成 Edit 模式。然後,在此模式下實作我們要刪除的資料。

    override func tableView(tableView: UITableView,
        commitEditingStyle editingStyle: UITableViewCellEditingStyle,
        forRowAtIndexPath indexPath: NSIndexPath) {
            
            if editingStyle == .Delete {
                self.vocabulary.removeAtIndex(indexPath.row)
            }
    }
當資料刪除後,我們必須讓 UI 畫面重整 Refresh。UITableView 提供一個方法 reloadData() 來 refresh UI:

    override func tableView(tableView: UITableView,
        commitEditingStyle editingStyle: UITableViewCellEditingStyle,
        forRowAtIndexPath indexPath: NSIndexPath) {
            
            if editingStyle == .Delete {
                self.vocabulary.removeAtIndex(indexPath.row)
                self.tableView.reloadData()
            }
    }

驗證: 在模擬器上,選取一行資料 Cell,然後左滑:
此時這行的右邊會顯示 Delete 刪除這按鈕。當我們點選這按鈕後,這行會被刪除嗎?
Yeah! 這行真的被刪除了!這下可以鬆口氣! 後記: 這整個步驟是參考書中的練習,以及 Apple 的網站,先由一個該怎麼做的概念去進行,把該有的 code 準備好後,才發現原來 TableViewController 這 Template 很貼心幫我們準備好 code 如下,但貼上自己寫的,整個觀念會更清楚。

  /*
    // Override to support editing the table view.
    override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if editingStyle == .Delete {
            // Delete the row from the data source
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        } else if editingStyle == .Insert {
            // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
        }    
    }
   */
附記: 程式碼:

//
//  MyTableViewController.swift
//  SimpleTableViewControllerDemo
//
//  Created by Elvis Meng on 2015/9/6.
//  Copyright (c) 2015年 Elvis Meng. All rights reserved.
//

import UIKit

class MyTableViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate {
    
    var vocabulary = ["book","pen","queen","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15"]

    override func viewDidLoad() {
        super.viewDidLoad()

        // Uncomment the following line to preserve selection between presentations
        // self.clearsSelectionOnViewWillAppear = false

        // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
        // self.navigationItem.rightBarButtonItem = self.editButtonItem()
        
    }

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

    // MARK: - Table view data source

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        // #warning Potentially incomplete method implementation.
        // Return the number of sections.
        return 1
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete method implementation.
        // Return the number of rows in the section.
        return self.vocabulary.count
    }
   
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        
        let cellIdentifier = "Cell"
        let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! UITableViewCell

        // Configure the cell...
        cell.textLabel?.text = vocabulary[indexPath.row]
        
        return cell
    }

    override func tableView(tableView: UITableView,
        didSelectRowAtIndexPath indexPath: NSIndexPath) {
            
            let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
            if cell.accessoryType == UITableViewCellAccessoryType.None {
                cell.accessoryType = UITableViewCellAccessoryType.Checkmark
            } else {
                cell.accessoryType = UITableViewCellAccessoryType.None
            }
            tableView.deselectRowAtIndexPath(indexPath, animated: true)
    }
    
    override func tableView(tableView: UITableView,
        didDeselectRowAtIndexPath indexPath: NSIndexPath) {
            let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
            if cell.accessoryType == UITableViewCellAccessoryType.None {
                cell.accessoryType = UITableViewCellAccessoryType.Checkmark
            } else {
                cell.accessoryType = UITableViewCellAccessoryType.None
            }
            tableView.deselectRowAtIndexPath(indexPath, animated: false)
    }

    override func tableView(tableView: UITableView,
        commitEditingStyle editingStyle: UITableViewCellEditingStyle,
        forRowAtIndexPath indexPath: NSIndexPath) {
            
            if editingStyle == .Delete {
                self.vocabulary.removeAtIndex(indexPath.row)
                self.tableView.reloadData()
            }
    }

  /*
    // Override to support editing the table view.
    override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if editingStyle == .Delete {
            // Delete the row from the data source
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        } else if editingStyle == .Insert {
            // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
        }    
    }
   */

    /*
    // Override to support rearranging the table view.
    override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {

    }
    */

    /*
    // Override to support conditional rearranging of the table view.
    override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        // Return NO if you do not want the item to be re-orderable.
        return true
    }
    */

    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        // Get the new view controller using [segue destinationViewController].
        // Pass the selected object to the new view controller.
    }
    */

}

參考: 1. UITableViewDataSource Protocol Reference, https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UITableViewDataSource_Protocol/ 2. UITableView Class Reference, https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UITableView_Class/index.html#//apple_ref/occ/cl/UITableView
prettyPrint();