NSMutableArray *allControllers = [[NSMutableArray alloc] initWithArray:navPick.viewControllers];
for (id object in allControllers) {
// if ([object isKindOfClass:[LoginController class]]) // 此行註解掉,會將容器內所有VC移除
[allControllers removeObject:object];
}
navPick.viewControllers = allControllers;
2011年8月26日 星期五
Remove UIViewController from UINavigationController
2011年8月24日 星期三
Loaded the "NibFileName" nib but didn't get a UITableView
動態載入時 xcode 會報錯,原因是繼承的形態跟 nib 使用的類別不同造成,
原始的宣告如下:
@interface ObjIDPickViewController : UITableViewController
{
}
要把它改成
@interface ObjIDPickViewController : UIViewController
{
}
2011年8月19日 星期五
C# get a string from C++ DLL
TCHAR g_awcMessage[] = L"Hello中文";
char g_aszMessage[] = "Hello中文";
extern "C" __declspec(dllexport) TCHAR* __stdcall GetHelloL()
{
return g_awcMessage;
}
extern "C" __declspec(dllexport) CHAR* __stdcall GetHello()
{
return g_aszMessage;
}
extern "C" __declspec(dllexport) int __stdcall GetInt()
{
return 100;
}
C# P/Invoke:
[DllImport("gpDll.dll")]
public static extern IntPtr GetHello();
[DllImport("gpDll.dll")]
public static extern IntPtr GetHelloL();
[DllImport("gpDll.dll")]
public static extern int GetInt();
private void button1_Click(object sender, EventArgs e)
{
// Not support in CF
//Marshal.PtrToStringAnsi
//Marshal.PtrToStringAuto
// Multibytes 會變成亂碼
string str = Marshal.PtrToStringUni(GetHello());
// Wide Character 顯示正常
string strL = Marshal.PtrToStringUni(GetHelloL());
int n = GetInt();
}
WinCE/Mobile Control Panel Item List
VC++
BOOL ShowControlPanelApplet(int id)
{
TCHAR szParams[32];
SHELLEXECUTEINFO execinfo = {0};
memset(&execinfo, 0, sizeof(execinfo));
execinfo.cbSize=sizeof(execinfo);
execinfo.lpFile=TEXT(“\\windows\\ctlpnl.exe”);
execinfo.lpVerb=TEXT(“open”);
// Id value determines which control applet will be launched
// For e.g. 23 for bluetooth applet
wsprintf(szParams, L”cplmain.cpl,%d”, id);
execinfo.lpParameters = szParams;
BOOL bRet=ShellExecuteEx(&execinfo);
return bRet;
}
VC#
Process.Start(@"\windows\ctlpnl.exe", "cplmain.cpl,19");
Windows Mobile
1 Password
2 Owner Information
3 Power
4 Memory
5 About
6 Brightness
7 Screen
8 Input
9 Sounds & Notifications
10 Remove Programs
11 Menus
12 Buttons
13 Today
14
15 Beam
16 Clocks & Alarms
17 Configure Network Adapters
18 Regional Settings
19 Connections
20
21
22 Manage Certificates
23 Bluetooth
24 Error Reporting
25 GPS Settings
26
27 USB to PC
Windows CE
1 PC Connection - 35#”ctlpnl.exe” \Windows\cplmain.cpl,0
2 Dialing - 35#”ctlpnl.exe” \Windows\cplmain.cpl,1
3 Keyboard - 35#”ctlpnl.exe” \Windows\cplmain.cpl,2
4 Password - 35#”ctlpnl.exe” \Windows\cplmain.cpl,3
5 Owner - 35#”ctlpnl.exe” \Windows\cplmain.cpl,4
6 Power - 35#”ctlpnl.exe” \Windows\cplmain.cpl,5
7 System - 35#”ctlpnl.exe” \Windows\cplmain.cpl,6
8 Display - 35#”ctlpnl.exe” \Windows\cplmain.cpl,7
9 Mouse - 35#”ctlpnl.exe” \Windows\cplmain.cpl,8
10 Stylus - 35#”ctlpnl.exe” \Windows\cplmain.cpl,9
11 Volume & sounds - 35#”ctlpnl.exe” \Windows\cplmain.cpl,10
12 Input Panel - 35#”ctlpnl.exe” \Windows\cplmain.cpl,11
13 Remove Programs - 35#”ctlpnl.exe” \Windows\cplmain.cpl,12
14 Date/Time - 35#”ctlpnl.exe” \Windows\cplmain.cpl,13
15 Certificates - 35#”ctlpnl.exe” \Windows\cplmain.cpl,14
16 Accessibility - 35#”ctlpnl.exe” \Windows\cplmain.cpl,15
SendKeys for .NETCF
So I have to implement it thru APIs,
here is the solutions: SendInput, keybd_event, PostKeybdMessage and SendMessage
[DllImport("coredll.dll", SetLastError = true)]
//[DllImport("user32.dll", SetLastError = true)]
static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
[DllImport("coredll", SetLastError = true)]
//[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow(string _ClassName, string _WindowName);
[DllImport("coredll", SetLastError = true)]
//[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
public static void SendIt()
{
IntPtr ip = FindWindow("notepad", null);
SetForegroundWindow(ip);
const int KEYEVENTF_KEYUP = 0x2;
const int KEYEVENTF_KEYDOWN = 0x0;
byte VK_TAB = 0x0D;
keybd_event(VK_TAB, 0, KEYEVENTF_KEYDOWN, 0);
keybd_event(VK_TAB, 0, KEYEVENTF_KEYUP, 0);
}
Symbolic constant name | Value (hexadecimal) | Keyboard (or mouse) equivalent |
---|---|---|
VK_LBUTTON | 01 | Left mouse button |
VK_RBUTTON | 02 | Right mouse button |
VK_CANCEL | 03 | Control-break processing |
VK_MBUTTON | 04 | Middle mouse button (three-button mouse) |
VK_BACK | 08 | BACKSPACE key |
VK_TAB | 09 | TAB key |
VK_CLEAR | 0C | CLEAR key |
VK_RETURN | 0D | ENTER key |
VK_SHIFT | 10 | SHIFT key |
VK_CONTROL | 11 | CTRL key |
VK_MENU | 12 | ALT key |
VK_PAUSE | 13 | PAUSE key |
VK_CAPITAL | 14 | CAPS LOCK key |
VK_ESCAPE | 1B | ESC key |
VK_SPACE | 20 | SPACEBAR |
VK_PRIOR | 21 | PAGE UP key |
VK_NEXT | 22 | PAGE DOWN key |
VK_END | 23 | END key |
VK_HOME | 24 | HOME key |
VK_LEFT | 25 | LEFT ARROW key |
VK_UP | 26 | UP ARROW key |
VK_RIGHT | 27 | RIGHT ARROW key |
VK_DOWN | 28 | DOWN ARROW key |
VK_SELECT | 29 | SELECT key |
VK_PRINT | 2A | PRINT key |
VK_EXECUTE | 2B | EXECUTE key |
VK_SNAPSHOT | 2C | PRINT SCREEN key |
VK_INSERT | 2D | INS key |
VK_DELETE | 2E | DEL key |
VK_HELP | 2F | HELP key |
30 | 0 key | |
31 | 1 key | |
32 | 2 key | |
33 | 3 key | |
34 | 4 key | |
35 | 5 key | |
36 | 6 key | |
37 | 7 key | |
38 | 8 key | |
39 | 9 key | |
41 | A key | |
42 | B key | |
43 | C key | |
44 | D key | |
45 | E key | |
46 | F key | |
47 | G key | |
48 | H key | |
49 | I key | |
4A | J key | |
4B | K key | |
4C | L key | |
4D | M key | |
4E | N key | |
4F | O key | |
50 | P key | |
51 | Q key | |
52 | R key | |
53 | S key | |
54 | T key | |
55 | U key | |
56 | V key | |
57 | W key | |
58 | X key | |
59 | Y key | |
5A | Z key | |
VK_NUMPAD0 | 60 | Numeric keypad 0 key |
VK_NUMPAD1 | 61 | Numeric keypad 1 key |
VK_NUMPAD2 | 62 | Numeric keypad 2 key |
VK_NUMPAD3 | 63 | Numeric keypad 3 key |
VK_NUMPAD4 | 64 | Numeric keypad 4 key |
VK_NUMPAD5 | 65 | Numeric keypad 5 key |
VK_NUMPAD6 | 66 | Numeric keypad 6 key |
VK_NUMPAD7 | 67 | Numeric keypad 7 key |
VK_NUMPAD8 | 68 | Numeric keypad 8 key |
VK_NUMPAD9 | 69 | Numeric keypad 9 key |
VK_SEPARATOR | 6C | Separator key |
VK_SUBTRACT | 6D | Subtract key |
VK_DECIMAL | 6E | Decimal key |
VK_DIVIDE | 6F | Divide key |
VK_F1 | 70 | F1 key |
VK_F2 | 71 | F2 key |
VK_F3 | 72 | F3 key |
VK_F4 | 73 | F4 key |
VK_F5 | 74 | F5 key |
VK_F6 | 75 | F6 key |
VK_F7 | 76 | F7 key |
VK_F8 | 77 | F8 key |
VK_F9 | 78 | F9 key |
VK_F10 | 79 | F10 key |
VK_F11 | 7A | F11 key |
VK_F12 | 7B | F12 key |
VK_F13 | 7C | F13 key |
VK_F14 | 7D | F14 key |
VK_F15 | 7E | F15 key |
VK_F16 | 7F | F16 key |
VK_F17 | 80H | F17 key |
VK_F18 | 81H | F18 key |
VK_F19 | 82H | F19 key |
VK_F20 | 83H | F20 key |
VK_F21 | 84H | F21 key |
VK_F22 | 85H | F22 key |
VK_F23 | 86H | F23 key |
VK_F24 | 87H | F24 key |
VK_NUMLOCK | 90 | NUM LOCK key |
VK_SCROLL | 91 | SCROLL LOCK key |
VK_LSHIFT | A0 | Left SHIFT key |
VK_RSHIFT | A1 | Right SHIFT key |
VK_LCONTROL | A2 | Left CONTROL key |
VK_RCONTROL | A3 | Right CONTROL key |
VK_LMENU | A4 | Left MENU key |
VK_RMENU | A5 | Right MENU key |
VK_PLAY | FA | Play key |
VK_ZOOM | FB | Zoom key |
Emulate mouse action in .NETCF
SendMessage API:
//Find topmost window of another application
IntPtr parentWnd = WIN32.Window.FindWindow(null, "Form2");
//Find the button
IntPtr hButton = WIN32.Window.FindWindowEx(parentWnd, IntPtr.Zero, null, "Target");
//Click the target button
WIN32.Window.SendMessage(hButton, Window.WM.WM_LBUTTONDOWN, IntPtr.Zero, IntPtr.Zero);
WIN32.Window.SendMessage(hButton, Window.WM.WM_LBUTTONUP, IntPtr.Zero, IntPtr.Zero);
mouse_event API:
[DllImport("coredll.dll", SetLastError = true)]
static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
[DllImport("user32.dll")]
static extern bool SetCursorPos(int X, int Y);
public enum MouseEventFlags
{
LEFTDOWN = 0x00000002,
LEFTUP = 0x00000004,
MIDDLEDOWN = 0x00000020,
MIDDLEUP = 0x00000040,
MOVE = 0x00000001,
ABSOLUTE = 0x00008000,
RIGHTDOWN = 0x00000008,
RIGHTUP = 0x00000010
}
void ClickIt()
{
SetCursorPos(400, 10);
mouse_event((int)(MouseEventFlags.LEFTDOWN), 0, 0, 0, 0);
mouse_event((int)(MouseEventFlags.LEFTUP), 0, 0, 0, 0);
}
2011年8月18日 星期四
SAP: Destination configuration already initialized
SAP Connector 要使用時要進行初始:
// 1.初始 SAP 連接介面 RfcDestinationManager.RegisterDestinationConfiguration(new MyBackendConfig());
這個方法在單執行緒中沒有太大的問題,但是搬到 ASP.NET (web)的世界中就麻煩了,
原因是因為這個方法 RegisterDestinationConfiguration 是靜態方法,
在多執行緒的世界中,程式一不小心就會造成執行階段報錯:Destination configuration already initialized
所以要透過 UnregisterDestinationConfiguration 來進行關閉,
但是要呼叫之前一定要確認傳進去的組態參數是同一個,透過此下的程式碼就可以"沒效率"的解決此問題。
為何說沒效率呢?因為每次呼叫RFC 時,都要 Init & Uninit,浪費資源也浪費時間,
但是目前可能這是唯一的解法,若之後有更好的解決方法再另外補充。
public class HuLane { RfcDestination m_rfcDest = null; RfcRepository m_rfcRepo = null; HLBackendConfig m_Config = null; public bool InitSAP() { bool bRet = false; try { m_Config = new HLBackendConfig(); RfcDestinationManager.RegisterDestinationConfiguration(m_Config); m_rfcDest = RfcDestinationManager.GetDestination("JTC_000"); m_rfcRepo = m_rfcDest.Repository; bRet = true; } catch (Exception ex) { System.Diagnostics.Trace.WriteLine( String.Format("InitSAP(): {0}", ex.Message)); } return bRet; } public bool UninitSAP() { bool bRet = false; try { RfcDestinationManager.UnregisterDestinationConfiguration(m_Config); bRet = true; } catch (Exception ex) { System.Diagnostics.Trace.WriteLine( String.Format("UninitSAP(): {0}", ex.Message)); } return bRet; } }
參考資料來源連結
IRfcTable、DataTable、DataSet 資料轉換模組
撰寫成公用模組,可以很方便的叫用。
public static DataTable GetDataTableFromRfcTable(IRfcTable rfcTable)
{
DataTable dtRet = new DataTable();
for (int liElement = 0; liElement < rfcTable.ElementCount; liElement++)
{
RfcElementMetadata rfcEMD = rfcTable.GetElementMetadata(liElement);
dtRet.Columns.Add(rfcEMD.Name);
}
foreach (IRfcStructure row in rfcTable)
{
DataRow dr = dtRet.NewRow();
for (int liElement = 0; liElement < rfcTable.ElementCount; liElement++)
{
RfcElementMetadata rfcEMD = rfcTable.GetElementMetadata(liElement);
dr[rfcEMD.Name] = row.GetString(rfcEMD.Name);
}
dtRet.Rows.Add(dr);
}
return dtRet;
}
public static DataTable[] GetDataTablesFromRfcTables(IRfcTable[] rfcTables)
{
DataTable[] dtRetTables = null;
if (rfcTables.Length > 0)
{
dtRetTables = new DataTable[rfcTables.Length];
for (int i = 0; i < rfcTables.Length; i++)
{
dtRetTables[i] = GetDataTableFromRfcTable(rfcTables[i]);
}
}
return dtRetTables;
}
public static DataTable[] GetDataTablesFromDataSet(DataSet ds)
{
DataTable[] dtRetTables = new DataTable[ds.Tables.Count];
for (int i = 0; i < ds.Tables.Count; i++)
dtRetTables[i] = ds.Tables[i];
return dtRetTables;
}
public static DataSet GetDataSetFromDataTables(DataTable[] dtTables)
{
DataSet dsRet = new DataSet();
for (int i = 0; i < dtTables.Length; i++)
{
dsRet.Tables.Add(dtTables[i]);
}
return dsRet;
}
2011年8月15日 星期一
呼叫 SAP RFC - 傳入 IRfcTable
相關的元素可是一樣都沒有少(輸出入參數、宣告呼叫方法),
接下來講的是如何把 IRfcTable 當作輸入的參數傳入 SAP RFC 中,
要傳入 IRfcTable 到 SAP RFC 中,有分為以下幾個步驟:
1.初始 SAP 連接介面
2.設定 SAP 連接參數
3.初始 SAP RFC 來源
4.建立 IRfcTable 結構
5.設定 IRfcTalbe 參數
6.呼叫 SAP RFC 返回值
7.取得 SAP RFC 返回值
實際上透過程式碼的實作如下:
using SAP.Middleware.Connector;
using System;
using System.Linq;
using System.Text;
using SAP.Middleware.Connector;
namespace csSAP
{
class Program
{
static void Main(string[] args)
{
// 1.初始 SAP 連接介面
RfcDestinationManager.RegisterDestinationConfiguration(new MyBackendConfig());
//2.設定 SAP 連接參數
RfcDestination prd = RfcDestinationManager.GetDestination("PRD_000");
try
{
//3.初始 SAP RFC 來源
RfcRepository repo = prd.Repository;
IRfcFunction IFunciton = repo.CreateFunction("JTC_BR0002");
//4.建立 IRfcTable 結構
IFunciton.Invoke(prd);
IRfcTable Itab = IFunciton.GetTable("IT_JTC"); // 取得 SAP 中定義的表格結構
//5.設定 IRfcTalbe 參數
Itab.Append(); // 加入一筆record 到表格中
Itab[0].SetValue("FIELD1", "1000");
Itab[0].SetValue("FIELD2", "1001");
Itab.Append(); // 再加入一筆record 到表格中
Itab[1].SetValue("FIELD1", "1001");
Itab[1].SetValue("FIELD2", "1002");
//6.呼叫 SAP RFC 返回值
IFunciton.SetValue("IT_JTC", Itab);
IFunciton.Invoke(prd);
//7.取得 SAP RFC 返回值
IRfcTable IRetTab = IFunciton.GetTable("ET_RETURN");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
public class MyBackendConfig : IDestinationConfiguration
{
public RfcConfigParameters GetParameters(String destinationName)
{
if ("JTC_000".Equals(destinationName))
{
RfcConfigParameters parms = new RfcConfigParameters();
parms.Add(RfcConfigParameters.AppServerHost, "192.168.1.1");
parms.Add(RfcConfigParameters.SystemNumber, "00");
parms.Add(RfcConfigParameters.User, "UserName");
parms.Add(RfcConfigParameters.Password, "UserPassword");
parms.Add(RfcConfigParameters.Client, "100");
parms.Add(RfcConfigParameters.PoolSize, "5");
parms.Add(RfcConfigParameters.MaxPoolSize, "10");
parms.Add(RfcConfigParameters.IdleTimeout, "600");
parms.Add(RfcConfigParameters.SystemID, "JTC");
return parms;
}
else return null;
}
// The following two are not used in this example:
public bool ChangeEventsSupported()
{
return false;
}
public event RfcDestinationManager.ConfigurationChangeHandler ConfigurationChanged;
}
}
2011年8月13日 星期六
Why NSString* retainCount is 2147483647
NSString *test1 = @"Test string"; NSLog(@"test1 retain count is: %d", [test1 retainCount]); // 2147483647 [test1 retain]; NSLog(@"test1 retain count is: %d", [test1 retainCount]); // 2147483647 [test1 release]; NSLog(@"test1 retain count is: %d", [test1 retainCount]); // 2147483647恩,你沒看錯,印出來的 retainCount 都是 2147483647,
接著我們再來看下面這段程式碼:
NSString *test2 = [[NSString alloc] initWithString:@"Test string"]; NSLog(@"test 2 retain count is: %d", [test2 retainCount]); // 猜猜看 [test2 retain]; NSLog(@"test 2 retain count is: %d", [test2 retainCount]); // 猜猜看 [test2 release]; NSLog(@"test 2 retain count is: %d", [test2 retainCount]); // 猜猜看
恩,印出來的值有符合預期的物件參考值:1 2 1 嗎?
答案是沒有,同樣都是 2147483647 這個神奇數字,這個數字到底是什麼東西呢?
其實上述的寫法,在經過 xcode compiler 編譯之後,都會把它改成一個指向常數字串的指標,
而這個神奇的數字,就是因為指標指向常數的時候,使用 retainCount 只會印出 UINT_MAX,
實際上看以下的圖就會更瞭解:
接著再來看這段程式碼:
NSString *test3 = [[NSString alloc]initWithFormat:@"%@", @"Test string"]; NSLog(@"test 3 retain count is: %d", [test3 retainCount]); // 1 [test3 retain]; NSLog(@"test 3 retain count is: %d", [test3 retainCount]); // 2 [test3 release]; NSLog(@"test 3 retain count is: %d", [test3 retainCount]); // 1 這樣就有符合預期的參考值了,差異就在 initWithFormat 這個初始字串的方式, 看出差異了嗎?
資安監控 商機無限大
讓很多從事資訊安全的公司發跡,舉凡防毒軟體、監控軟體..,除了防毒軟體之外,
還有許多型態的資安系統,都是有利可圖、商機無限的方向。
智慧型手機的時代已經來臨了,原本在PC上的應用紛紛的搬到可攜裝置上來,
先來看要錢的:
http://www.youtube.com/watch?v=KuM9egbfwQ4
再來看免錢的:
http://portable.easylife.tw/2722
上述的都是就現有的系統架構下,讓管理監控人員可以方便的在可攜裝置上"控管"。
另外還有一種是控管使用電腦(或可攜裝置)的系統:
http://www.ip-guard.com/
恩...商機無限,而且說實在,
進入的門檻還在可以負擔的範圍內,
值得好好的思考。
2011年8月12日 星期五
呼叫 SAP RFC
1.初始 SAP 連接介面
2.設定 SAP 連接參數
3.初始 SAP RFC 來源
4.呼叫 SAP RFC 函數
5.取得 SAP RFC 返回值
實際上透過程式碼的實作如下:
using SAP.Middleware.Connector;
using System;
using System.Linq;
using System.Text;
using SAP.Middleware.Connector;
namespace csSAP
{
class Program
{
static void Main(string[] args)
{
// 1.初始 SAP 連接介面
RfcDestinationManager.RegisterDestinationConfiguration(new MyBackendConfig());
//2.設定 SAP 連接參數
RfcDestination prd = RfcDestinationManager.GetDestination("JTC_000");
try
{
//3.初始 SAP RFC 來源
RfcRepository repo = prd.Repository;
//4.呼叫 SAP RFC 函數
IRfcFunction stfcReader = repo.CreateFunction("BAPI_COMPANY_GETDETAIL");
// 設定要傳入的參數
stfcReader.SetValue("COMPANYID", "1010");
stfcReader.Invoke(prd);
//5.取得 SAP RFC 返回值
string strRet = stfcReader.GetStructure("COMPANY_DETAIL").GetString("NAME1");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
public class MyBackendConfig : IDestinationConfiguration
{
public RfcConfigParameters GetParameters(String destinationName)
{
if ("JTC_000".Equals(destinationName))
{
RfcConfigParameters parms = new RfcConfigParameters();
parms.Add(RfcConfigParameters.AppServerHost, "192.168.1.1");
parms.Add(RfcConfigParameters.SystemNumber, "00");
parms.Add(RfcConfigParameters.User, "UserName");
parms.Add(RfcConfigParameters.Password, "UserPassword");
parms.Add(RfcConfigParameters.Client, "100");
parms.Add(RfcConfigParameters.PoolSize, "5");
parms.Add(RfcConfigParameters.MaxPoolSize, "10");
parms.Add(RfcConfigParameters.IdleTimeout, "600");
parms.Add(RfcConfigParameters.SystemID, "JTC");
return parms;
}
else return null;
}
// The following two are not used in this example:
public bool ChangeEventsSupported()
{
return false;
}
public event RfcDestinationManager.ConfigurationChangeHandler ConfigurationChanged;
}
}
2011年8月11日 星期四
NSString 常用操作範例
1.字串比較
NSString *str1 = [[NSString alloc]initWithString:@"I am String1"];
NSString *str2 = [[NSString alloc]initWithString:@"I am String2"];
NSLog(@"%@ 與 %@ 是否相同: %@", str1, str2, [str1 isEqualToString:str2] ? @"Y":@"N");
[str1 release];
[str2 release];
2.字串比較(不區分大小寫)
NSString *str1 = [[NSString alloc]initWithString:@"I am String1"];
NSString *str2 = [[NSString alloc]initWithString:@"i am string1"];
NSLog(@"%@ 與 %@ 是否相同(不考慮大小寫): %@", str1, str2,
[str1 caseInsensitiveCompare:str2]==NSOrderedSame ? @"Y":@"N");
[str1 release];
[str2 release];
3.搜尋字串
NSString *str1 = [[NSString alloc]initWithString:@"This is an apple"];
//此處NSRange 為區分大小寫
NSRange searchString1 = [str1 rangeOfString:@"apple"];
NSRange searchString2 = [str1 rangeOfString:@"orange"];
NSLog(@"%@ 是否有apple字串: %@",str1, searchString1.location == NSNotFound ? @"N" : @"Y" );
NSLog(@"%@ 是否有orange字串: %@",str1, searchString2.location == NSNotFound ? @"N" : @"Y" );
[str1 release];
4.取出字串
NSString *str1 = [[NSString alloc]initWithString:@"this is a string"];
NSLog(@"%@ 取出從頭自第2位(不包含第2位)的字串: %@",str1, [str1 substringToIndex:1]);
NSLog(@"%@ 取出第2位(包含) 後所有字串: %@",str1, [str1 substringFromIndex:1]);
NSLog(@"%@ 取出第3位至第7位的字串: %@",str1, [str1 substringWithRange:NSMakeRange(5,4)]);
[str1 release];
5.替換字串
NSString *string1 = [[NSString alloc]initWithString:@"this is a book"];
NSString *string2 = [[NSString alloc]initWithString:@"pen"];
NSLog(@"%@ 替換後 %@",string1,
[string1 stringByReplacingOccurrencesOfString:@"book" withString:@"pen"]);
[string1 release];
[string2 release];
6.字串轉成array
NSString *str1 = [[NSString alloc]initWithString:@"apple,orange,cat,dog,bird"];
NSLog(@"%@",[str1 componentsSeparatedByString:@","]);
[str1 release];
7.array轉成字串
NSArray *array = [[NSArray alloc]initWithObjects:@"apple",@"orange",@"cat",@"bird",nil];
NSLog(@"%@",[array componentsJoinedByString:@","]);
[array release];
NSString 轉換為 NSDate
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSDate *date = [dateFormatter dateFromString:@"2010-08-04 16:01:03"];
NSLog(@"%@", date);
[dateFormatter release];
2011年8月7日 星期日
2011年8月4日 星期四
sendSynchronousRequest 狀態下如何顯示忙碌訊息
是一個同步處理的機制,也就是說當此方法ㄧ被呼叫,該執行緒就會被整個咬住了,
通常來說我們會希望能加入一些畫面提醒的機制(例如轉圈圈),有兩種解決來提供:
解法一(程式碼可以改最少):
- (void)loadInOnePart {
//...other real code
UIAlertView *avBusy = [[[UIAlertView alloc] initWithTitle:@"Busy busy" message:nil delegate:nil
cancelButtonTitle:nil otherButtonTitles:nil] autorelease];
[avBusy show];
UIActivityIndicatorView *aiBusy = [[[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite] autorelease];
[aiBusy startAnimating];
[avBusy addSubview:aiBusy];
aiBusy.center = CGPointMake(avBusy.bounds.size.width / 2, avBusy.bounds.size.height / 2 + 10);
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate date]];
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
[avBusy dismissWithClickedButtonIndex:0 animated:YES];
}
解法二(程式碼分割要考慮整體架構):
- (void)loadPart1 {
activityIndicator = [[[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]
autorelease];
[self.view addSubview:activityIndicator];
[activityIndicator startAnimating];
[self performSelector:@selector(loadPart2) withObject:nil afterDelay:0];
}
- (void)loadPart2 {
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
[activityIndicator stopAnimating];
}
參考資料來源