2011年10月25日 星期二

開啟Mac OS的Root Admin

系統偏好設定>使用者與群組>>登入選項>按下網路帳號伺服"加入"按鈕>打開目錄工具程式>選Menu Bar的"編輯">啟用Root使用者>最後輸入Root使用者新的密碼就大功告成

P.S. 參考網址:http://www.thewwwblog.com/enable-root-user-in-mac-os-x-super-admin-access.html

2011年10月9日 星期日

iOS NSString to NSDate/NSDate to NSString

NSString to NSDate
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
// 把時間設定成世界時間
//[dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSDate* date = [dateFormatter dateFromString:@"Date String"];
[dateFormatter release];

NSDate to NSString
NSDateFormatter* outputFormatter = [[NSDateFormatter alloc] init];
[outputFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSString* dateString = [outputFormatter stringFromDate:date];
[outputFormatter release];

2011年10月3日 星期一

iOS Local Notification

又是時候把學習了的總理一下,
再記錄下來了,
今次的是Local Notification

1.即時的 Local Notification
UIBackgroundTaskIdentifier bgTask;
- (void)applicationDidEnterBackground:(UIApplication *)application {
if(bgTask == UIBackgroundTaskInvalid)
{
UIApplication* app = [UIApplication sharedApplication];

// 開啟了BackgroundTask就要以令以下的queue在Background/Foreground Task都可以運行
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
NSLog(@"System Expiration End Background Task");
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];

// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
UILocalNotification* notification = [[UILocalNotification alloc] init];
notification.alertBody = @"Test";
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
[notification release];

[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
}
}

2.Schedule Local Notification
UILocalNotification* notification = [[UILocalNotification alloc] init];
notification.alertBody = @"Test";
// 在當前時間10秒後發動
notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:10];
// Alert View 不會顯示 View button
notification.hasAction = FALSE;
notification.userInfo = [NSDictionary dictionaryWithObject:@"Key" forKey:@"Key"];
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
[notification release];

3.Cancel Local Notification
// 在 scheduled 的 Local Notification Array 找出要的 Local Notification Object
NSUInteger idx = [[UIApplication sharedApplication].scheduledLocalNotifications indexOfObjectPassingTest:
^(id obj, NSUInteger idx, BOOL *stop)
{
NSDictionary* userData = ((UILocalNotification*)obj).userInfo;
NSInteger key = [[userData valueForKey:@"Key"] integerValue];
if([key isEqualToString:@"Key"])
{
*stop = TRUE;
return YES;
}
return NO;
}];

if(idx != NSNotFound)
{
UILocalNotification* notification = [[UIApplication sharedApplication].scheduledLocalNotifications objectAtIndex:idx];
[[UIApplication sharedApplication] cancelLocalNotification:notification];
}

2011年9月7日 星期三

Windows Phone 7 Live Tile

原來WP7可以用戶API去Create, Update, Delete App Icon,
而且可以用一個人App有2個Icon係數Start Page,
真係幾得意見.......XD

Using dll
//Import the ShellTile namespace
using Microsoft.Phone.Shell;

create second icon
// Look to see whether the Tile already exists and if so, don't try to create it
again.
ShellTile TileToFind = ShellTile.ActiveTiles.FirstOrDefault(x =>
x.NavigationUri.ToString().Contains("DefaultTitle=FromTile"));
// Create the Tile if we didn't find that it already exists.
if (TileToFind == null)
{
    // Create the Tile object and set some initial properties for the Tile.
    // The Count value of 12 shows the number 12 on the front of the Tile. Valid values are 1-99.
    // A Count value of 0 indicates that the Count should not be displayed.
    StandardTileData NewTileData = new StandardTileData
    {
        BackgroundImage = new Uri("Red.jpg", UriKind.Relative),
        Title = "Secondary Tile",
        Count = 12,
        BackTitle = "Back of Tile",
        BackContent = "Welcome to the back of the Tile",
        BackBackgroundImage = new Uri("Blue.jpg", UriKind.Relative)
    };
    // Create the Tile and pin it to Start. This will cause a navigation to Start and a deactivation of our application.
    ShellTile.Create(new Uri("/SecondaryTile.xaml?DefaultTitle=FromTile", UriKind.Relative), NewTileData);
}

2011年9月6日 星期二

C# Lambda Expression () =>

今天上了一個Windows Phone 7 course,
入面見到一個我沒見過的話syntax:

void accelerometer_ReadingChanged(object sender, AccelerometerReadingEventArgs e)
{
      Deployment.Current.Dispatcher.BeginInvoke(() => MyReadingChanged(e));
}

點來上網一看,它叫作Lambda Expression(Lambda 表達式),
"=>" 可以解作為 "goes to"


PS. 參考http://msdn.microsoft.com/en-us/library/bb397687.aspx

清除了Project目錄下SVN檔案Command

之前上司教的幾個SVN Command
很有用,共享吧!!

ignore certain pattern
svn propset svn:ignore -F ignore.txt .

Delete all the .svn folder
find . -name ".svn" -type d -exec rm -rf {} \;

2011年8月16日 星期二

令UIImageView擁有簡單的Move, Zoom, Delete, Rotate功能

- (void)viewDidLoad
{
UIImageView* iconView = [[UIImageView alloc] initWithImage:icon];
[iconView setCenter:CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2)];
UILongPressGestureRecognizer* longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
[iconView addGestureRecognizer:longPressGesture];
[longPressGesture release];
UIRotationGestureRecognizer* rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
[iconView addGestureRecognizer:rotationGesture];
[rotationGesture release];
UIPinchGestureRecognizer* pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
[iconView addGestureRecognizer:pinchGesture];
[pinchGesture release];
UIPanGestureRecognizer* panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
[iconView addGestureRecognizer:panGesture];
[panGesture release];
iconView.userInteractionEnabled = TRUE;
[self.view addSubview:iconView];
}

#pragma mark -
#pragma mark Gesture Callback
- (void)adjustAnchorPointForGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state == UIGestureRecognizerStateBegan)
{
UIView *piece = gestureRecognizer.view;
CGPoint locationInView = [gestureRecognizer locationInView:piece];
CGPoint locationInSuperview = [gestureRecognizer locationInView:piece.superview];

piece.layer.anchorPoint = CGPointMake(locationInView.x / piece.bounds.size.width, locationInView.y / piece.bounds.size.height);
piece.center = locationInSuperview;
}
}

-(void)handleGesture:(UIGestureRecognizer*)gestureRecognizer
{
[self adjustAnchorPointForGestureRecognizer:gestureRecognizer];

// Rotate
if([gestureRecognizer isMemberOfClass:[UIRotationGestureRecognizer class]])
{
UIRotationGestureRecognizer* rotationGestureRecognizer = (UIRotationGestureRecognizer*)gestureRecognizer;
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan ||
[gestureRecognizer state] == UIGestureRecognizerStateChanged)
{
[rotationGestureRecognizer view].transform = CGAffineTransformRotate([[rotationGestureRecognizer view] transform], [rotationGestureRecognizer rotation]);
[rotationGestureRecognizer setRotation:0];
}
}
// Zoom
else if([gestureRecognizer isMemberOfClass:[UIPinchGestureRecognizer class]])
{
UIPinchGestureRecognizer* pinchGestureRecognizer = (UIPinchGestureRecognizer*)gestureRecognizer;
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan ||
[gestureRecognizer state] == UIGestureRecognizerStateChanged)
{
[pinchGestureRecognizer view].transform = CGAffineTransformScale([[pinchGestureRecognizer view] transform], [pinchGestureRecognizer scale], [pinchGestureRecognizer scale]);
[pinchGestureRecognizer setScale:1];
}
}
// Menu - Delete
else if([gestureRecognizer isMemberOfClass:[UILongPressGestureRecognizer class]])
{
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan)
{
UIMenuController *menuController = [UIMenuController sharedMenuController];
UIMenuItem *resetMenuItem = [[UIMenuItem alloc] initWithTitle:@"Reset" action:@selector(deleteMenu:)];
CGPoint location = [gestureRecognizer locationInView:[gestureRecognizer view]];


[self becomeFirstResponder];
[menuController setMenuItems:[NSArray arrayWithObject:resetMenuItem]];
[menuController setTargetRect:CGRectMake(location.x, location.y, 0, 0) inView:[gestureRecognizer view]];
[menuController setMenuVisible:YES animated:YES];


[resetMenuItem release];
}
}
// Move
else if([gestureRecognizer isMemberOfClass:[UIPanGestureRecognizer class]])
{
UIView* piece = [gestureRecognizer view];
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan ||
[gestureRecognizer state] == UIGestureRecognizerStateChanged)
{
UIPanGestureRecognizer* panGestureRecognizer = (UIPanGestureRecognizer*)gestureRecognizer;
CGPoint translation = [panGestureRecognizer translationInView:[piece superview]];


[piece setCenter:CGPointMake([piece center].x + translation.x, [piece center].y + translation.y)];
[panGestureRecognizer setTranslation:CGPointZero inView:[piece superview]];
}
}
}

2011年8月15日 星期一

UIImagePickerController Camera獲取的圖片在CGContext下的正確繪製方法

UIImagePickerController Camera獲取的圖片,
本身是由它的Orientation決定它的方法,
在UIImage draw會無問題,
不過在CGImageRef下就要做一些手腳了

#define CC_DEGREES_TO_RADIANS(__ANGLE__) ((__ANGLE__) / 180.0f * (float)M_PI)
CGContextRotateCTM(context, CC_DEGREES_TO_RADIANS(-90));
CGContextTranslateCTM(context, -size.height, 0);
CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, size.height, size.width), image.CGImage);

由原圖獲取iPhone Photo Library Thumbnail Image的方法

這兩天要給公司完成一個有關相片的話Demo,
所以把以前研究圖片的代碼發上來,
可能有用,加上可以做個筆記,一舉兩得

+ (UIImage*)resizeImage:(UIImage*)image width:(int)width height:(int)height
{
// Create a thumbnail version of the image for the event object.
CGSize size = image.size;
CGSize croppedSize;
CGFloat offsetX = 0.0;
CGFloat offsetY = 0.0;

// check the size of the image, we want to make it
// a square with sides the size of the smallest dimension
if (size.width > size.height)
{
offsetX = (size.height - size.width) / 2;
croppedSize = CGSizeMake(size.height, size.height);
}
else
{
offsetY = (size.width - size.height) / 2;
croppedSize = CGSizeMake(size.width, size.width);
}

// Crop the image before resize
CGRect clippedRect = CGRectMake(offsetX * -1, offsetY * -1, croppedSize.width, croppedSize.height);
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], clippedRect);
// Done cropping

// Resize the image
UIGraphicsBeginImageContext(CGSizeMake(width, height));
CGContextRef bitmap = UIGraphicsGetCurrentContext();
// 以下代碼很特別,
// 如果圖片是由於Photo library/UIImagePickerController獲得來的,
// 圖片本身的方向會90度倒轉了,
// 只要設定一下CGContextSetTextMatrix為1.0, 0.0, 0.0, -1.0, 0.0, 0.0就會回復正常
CGAffineTransform transform = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, 0.0);
CGContextSetTextMatrix(bitmap, transform);
[[UIImage imageWithCGImage:imageRef] drawInRect:CGRectMake(0, 0, width, height)];
UIImage* thumbnail = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Done Resizing

return thumbnail;
}

2011年7月21日 星期四

魔導紀元增加金錢大法

我都很久沒在這個blog出過post啦,最近和朋友愛上玩iOS的魔導紀元,前陣它免費了所以下來就玩.
不過就是怪太強,錢太少,加上我一向都沒有心機玩RPG,我最多只會欣賞它的故事,人手升LV真係少之又少,幸好這遊戲本身就有比錢升級的功能,真是很像當年的J2ME RPG遊戲,所以我就拎左遊戲的save檔改錢啦.

要拎iPhone App入面嫁file就梗係要JB啦,不過我最近發現個叫iPhone Explorer的software,用佢就可以拎到iPhone App入面嫁file又不用JB,兩個字--方便.

Step 1:

當然是在iPhone到找出哪隻遊戲啦!!!

Step 2:

找到了,我一下子就把App Folder全拿了出來.

Step 3:

去$(App Folder)/Documents,找magicTime.rms.這裡真令我估不到,檔尾是rms--是J2ME遊戲最常用的儲存文件,真想用JSME開哪文件試試,不過最後都是只改了金錢,有機會再試!!!

Step 4:

最後記好這個位置,紅圈的就是金錢位置了,我只改了FF FF,即是65535,應該可以更大,不過65535我已經夠了=o=

2011年7月5日 星期二

當IOS App發生Exception時生成自定義Log Report

昨天看到有人POST一遍程序異常退出時發送郵件報告的代碼的文章,
今天試了一次,發現很實用,
可以幫助我們Developer在沒有Debug Console的情況下建立Log Report,
可惜是BAD_EXC_ACCESS的Exception就不能捕捉到Log Report了,
不過還是有用的,所以發上來。

// Define exception handler callback function
void UncaughtExceptionHandler(NSException* exception)
{
    // Get the exception detail infomation
    NSArray* arr = [exception callStackSymbols];
    NSString* reason = [exception reason];
    NSString* name = [exception name];
    NSString* exceptionStr = [NSString stringWithFormat:@"Exception Name : %@\nReason : %@\n Call Stack Symbols :\n%@", name,reason,[arr componentsJoinedByString:@"\n"]];

    // Save to log file and file encoding was UTF-8
    [exceptionStr writeToFile:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, TRUE) objectAtIndex:0] stringByAppendingPathComponent:@"exception.log"] atomically:TRUE encoding:NSUTF8StringEncoding error:nil];

    // Print the exception message in debug console
    NSLog(exceptionStr);
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Setup the exception callback handler
    NSSetUncaughtExceptionHandler (&UncaughtExceptionHandler);

    return TRUE;
}

2011年6月27日 星期一

利用AirPrint列印UIWebView當前顯示的範圍

// Get the UIWebView content and convert to UIImage
UIViewPrintFormatter* printFormatter = [_webView viewPrintFormatter];
UIGraphicsBeginImageContext(_webView.frame.size);
[printFormatter.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// For Testing check the view layer size
//[UIImagePNGRepresentation(newImage) writeToFile:@"/Users/kito/Desktop/testfile.png" atomically:TRUE];

// Assign the AirPrint Job
UIPrintInteractionController* printController = [UIPrintInteractionController sharedPrintController];
printController.printingItem = newImage;

// Present the AirPrint Dialog from Bar Button
[printController presentFromBarButtonItem:barBtn animated:TRUE completionHandler:nil];

2011年6月26日 星期日

AirPrint Sample

AirPrint一開始還以為會很煩同複雜,
看過Document才發現,不是哪回事,
簡單幾行就要以了,IOS真係很為開發者著想。

UIPrintInteractionController* printController = [UIPrintInteractionController sharedPrintController];

UIPrintInfo *printInfo = [UIPrintInfo printInfo];
printInfo.outputType = UIPrintInfoOutputGeneral;
printInfo.jobName = @"Print Job - 1";
printController.printInfo = printInfo;
printController.printFormatter = [_webView viewPrintFormatter];

[printController presentAnimated:TRUE completionHandler:cUIPrintInteractionCompletionHandler];

2011年6月23日 星期四

MySQL一個聰明的sql,當Record沒有增加,存在會更新

今天又學了新的技巧,
所以下班了就立刻上載上Blogger做好備份,
今天的又是一個聰明的sql,
可以說是昨天的進化版。
昨天的sql沒有才會加入Record,
不過今天就是加了新功能,
存在Record的會自動更新
代碼如下:

// INSERT代碼
INSERT INTO tabTesting (user, token)
VALUES ('$user', '$token')
// 關鍵所在ON DUPLICATE KEY,即是Column為Key時,加入的Data重複了就會運行以下代碼
ON DUPLICATE KEY
// Update代碼
UPDATE user='$user';

PS. 假如你的Table本身有了Primary Key Column哪怎辦?
其實你可以把你想做檢測Data的Column做成Unique Key,
SQL就會懂得幫你去檢測了 XD

2011年6月21日 星期二

MySQL一個聰明的sql,當Record沒有的時候才增加

今天幫Project做maintain,
發現同事寫的一行SQL代碼,我不太明白,
細問之下原來功用十分奇妙!!
學到新野,我梗係即時記下來,
就是insert時,當Record沒有的時候才insert一個新的,
大大簡化了一個Coding上的一大段檢測代碼。
代碼如下:

// insert command
insert into myfavorite (songname,songid,singername,singertype)
// select command用作制造一個visual record
select 'MAKE IT REAL','G023203','(null)',0
// where用作檢測not exists的結果
where not exists
(
    // select相同的table,record存在就return 1,不存在為NULL
    select 1 from myfavorite
    where songid = 'G023203'
);

iOS App進入Background Process也可不中斷(二)

之前一次已經說過iOS App進入Background Process也可不中斷連線下載的方法,
不過上次的方法有一個壞處,
就是用戶再開啟App,App是不會更新畫面,
只會出Default Image要直到Callback完成
所以今天看了一下Help Document,
終於找到最好的方法了

UIBackgroundTaskIdentifier bgTask;
if(bgTask == UIBackgroundTaskInvalid)
{
    UIApplication* app = [UIApplication sharedApplication];

    // 開啟了BackgroundTask就要以令以下的queue在Background/Foreground Task都可以運行
    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
        NSLog(@"System Expiration End Background Task");
        [app endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    }];

    // Start the long-running task and return immediately.
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    // Do the work associated with the task.
    for (int i = 0; i < 1000; i++)
    {
        NSLog(@"Sleep %d", i);
        // 返回Main Process更新UI
        dispatch_async(dispatch_get_main_queue(), ^{
            UIButton* btn = (UIButton*)[viewController.view viewWithTag:100];
            [btn setTitle:[NSString stringWithFormat:@"Sleep %d", i] forState:UIControlStateNormal];
        }); 
        [NSThread sleepForTimeInterval:5];
    }

    NSLog(@"Completed State End Background Task");
    [app endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;
    });
}

UISearchBar小技巧(二)-修改UISearchBar內其他完件的大小

今天有項目要把UISearchBar放大,
不過只係設定UISearchBar的Frame Size就只會把UISearchBar背景放大,
而中間的Text Field沒有放大,
於是又用到找Subview的方法,
找出Text Field來放大,
不過要放大UISearchBar內其他完件的大小,
不可以在平時的Method Call完成,
要用到Override UIView下layoutSubviews method才可以完成

@implementation UISearchBar (Override)

- (void)layoutSubviews
{
   UITextField *searchField;
   for(int i = 0; i < [self.subviews count]; i++)
   {
      if([[self.subviews objectAtIndex:i] isKindOfClass:[UITextField class]])
      {
         searchField = [self.subviews objectAtIndex:i];
      }
   }
}

@end

2011年6月12日 星期日

UISearchBar小技巧

今早有朋友問我如何令UISearchBar的Keyboard彈出,
不過早上太多工作沒時間回他們,
所以現在Lunch時間寫出來,
給他們看看,方便我不用在MSN上說多一次

UISearchBar* searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];

// 獲取所有UISearchBar Subviews的內容
//NSLog(@"%@", [searchBar.subviews description]);

// 令UISearchBar的Keyboard彈出
[((UIControl*)[searchBar.subviews objectAtIndex:1]) becomeFirstResponder];

// 令UISearchBar沒有了背景
[((UIView*)[searchBar.subviews objectAtIndex:0]) removeFromSuperview];

[self.view addSubview:searchBar];
[searchBar release];

iOS劃分Debug/Release代碼的方法

有時寫代碼的時候有一些Log信息只想在Debug Mode下才顯示,
哪麼以下代碼就很合適了

#ifdef __OPTIMIZE__
// Release Mode
#else
// Debug Mode
#endif

2011年6月10日 星期五

讓MKMapView懂得自動移去兩個地圖子針之間

今天Project要加入一個新功能,
就是令MKMapView懂得自動移去兩個地圖子針之間的位置,
令用戶可以知道目的地同自己差多遠,
最後看了一下MKMapView的Document就找到了,
倒不算太難,
留下來作筆記XD

// 獲取用戶的位置範圍
MKMapPoint userMapPoint = MKMapPointForCoordinate(userLocation.location.coordinate);
MKMapRect userRect = MKMapRectMake(userMapPoint.x, userMapPoint.y, 50, 50);

// 獲取目的地的位置範圍
MKMapPoint targetMapPoint = MKMapPointForCoordinate(_coordinate);
MKMapRect targetRect = MKMapRectMake(targetMapPoint.x, targetMapPoint.y, 50, 50);

// 把範圍Union
MKMapRect unionRect = MKMapRectUnion(userRect, targetRect);
// 叫MKMapView移去指定範圍
[_mapView setVisibleMapRect:unionRect animated:TRUE];

2011年6月8日 星期三

令iOS App進入Background Process也可以進行連線下載

其實要令到iOS App進入Background Process也可以進行連線下載不中斷,
其實有一個很簡單的方法,
就是用NSTimer啦!!
利用NSTimer,在NSTimer的Callback Function,
即是App進入Background Process,
iOS還是會讓NSTimer的Callback Function完成,
才會在Background Process停下來。

PS:不過這方法有一個問題,就是NSTimer的Callback沒完成,用戶再開啟App,App是不會更新畫面,只會出Default Image要直到Callback完成,才會更新

[NSTimer scheduledTimerWithTimeInterval:0.1f target:self selector:@selector(timerLoadUpdate) userInfo:nil repeats:FALSE];

2011年5月26日 星期四

Objective C 小技巧 ﹣ 由Object獲取Class的所有Method名

今天做實驗,
想試出有什麼方法可以更改iOS SDK中一些私有API,
而又可以理論上通過App Store的審核。
不過作為私有API,我們根本就無法看得到Class的Header File,
哪麼最簡單更改方法就只好由Method入手,
因為Objective C有Categories的Override功能,
十分好用,可作某Method下的覆寫。

代碼如下
// 必須的Header file
#import <objc/runtime.h>

// 找Method名的代碼
unsigned int methodCnt = 0;
Method* methodList = class_copyMethodList([obj class], &methodCnt);
for (int i = 0; i < methodCnt; i++)
{
   Method method = methodList[i];
   // Print Method Name
   NSLog(@"%@", NSStringFromSelector(method_getName(method)));
}

2011年5月24日 星期二

iOS UIWindow 小技巧﹣令UIViewController收不到Interface Orientation Callback的原因

今天開始接手同事的iPhone項目,
我主要的工作是把項目轉為同時支援iPad的版本

剛開始就發現項目不論在iPhone或是iPad都不支持Interface Orientation,
經過同事和我的努力,
即使在plist和UIViewController的Interface Orientation Callback,
設定了都不可以收到Interface Orientation

最後同事發現到原來是Interface Builder,
把viewController的view加到UIWindow中就會引發這個問題,
他之後改為programme code去把viewController的view加到UIWindow中就沒事了
// 把viewController的view加到UIWindow中
[self.window addSubview:viewController.view];

2011年5月22日 星期日

MySQL﹣一行SQL可以把別的Table內容加到當前Table中

今天錯手刪了公司DB中一個重要得Table內容,
我即時向上司回報,
幸好哪Table是Match用的Table,
上司即時教我把Data由別的Tablel中Recove,
真是有驚無險

INSERT INTO MatchTable ( id, index )
SELECT  OtherTable.id, OtherTable.index
FROM OtherTable
WHERE state=1;

2011年5月6日 星期五

iOS UITableView 小投巧(二)﹣修改Section Header方便方法

一般大家修改Section Header都會用
// 修改Header高度
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
// 修改Header介面的View
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

但是今天我發現可以利用UITableView本身的property tableHeaderView
不過它只會出現在UITableView的最上方,
因為它根不就不是一個Section Header,
只是在UITableView用到一Section Header,
就可以用它來簡化代碼
UILabel* titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 245, 50)];
[titleLabel setText:@"Title"];
[titleLabel setFont:[UIFont boldSystemFontOfSize:22]];
//[titleLabel setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];
[titleLabel setTextAlignment:UITextAlignmentCenter];
[titleLabel setBackgroundColor:[UIColor clearColor]];
[titleLabel setTextColor:[UIColor whiteColor]];
self.tableView.tableHeaderView = titleLabel;
[titleLabel release];

iOS UITableView 小投巧(一)﹣優化效能

最近一位同事要利用UITableView載入二萬個Record
不過UITableView用了約兩分鐘才完成初始化
真是慢得無朋友

最後我們發現他原來用了UITableView Delegate Callback的heightForHeaderInSection Function
去修改Record的高度
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return 100;
}

我們都覺得是Function Call太多的關係
是令UITableView慢原因
最好的方法都是用UITableView的property rowHeight去修改
_tableView.rowHeight = 100;

iPhone Three20 Framework中修改TTTabBar顏色的方法

今天小弟第一次使用Three20 Framework被它的Demo UI吸引,
所以在工作中用上了,
發覺TTTabBar沒有setBackgroundColor這類的Function去修改TabBar的介面顏色
後來我發現了,
原來大部的UI所用的介面顏色都是由TTDefaultStyleSheet Class所控制
所以我利用了Objective C的Categories特性,
修改了TTDefaultStyleSheet Class控制TabBar顏色部份

代碼如下
@implementation TTDefaultStyleSheet (CategoriesOverride)

- (TTStyle*)tabBar
{
   UIColor* border = [TTSTYLEVAR(tabBarTintColor) multiplyHue:0 saturation:0 value:0.7];

      return
         [TTSolidFillStyle styleWithColor:[UIColor blackColor] next:
            [TTFourBorderStyle styleWithTop:nil right:nil bottom:border left:nil width:1 next:nil]];
}

@end

P.S. 粗體黃字為修改的背景色

2011年5月3日 星期二

自定義UIPageControl的介面

今天工作時發現要修改UIPageControl的介面,
不過上Google找不到想要的答案,
只好自己試出來了XD

其實修改2個Function就可以做到
- (void)setNumberOfPages:(NSInteger)pages;
- (void)setCurrentPage:(NSInteger)page;

- (void)setNumberOfPages:(NSInteger)pages
{
// super class function
[super setNumberOfPages:pages];

// search all page image view
for (int i = 0; i < [self.subviews count]; i++)
{
UIImageView* imageView = [self.subviews objectAtIndex:i];
[imageView setFrame:CGRectMake(0, 0, 25, 25)];
// if image view no subview
if([imageView.subviews count] == 0)
{
// add a new subview cover image view
UILabel* numLabel = [[UILabel alloc] initWithFrame:imageView.frame];
[numLabel setText:[NSString stringWithFormat:@"%d", i + 1]];
[numLabel setBackgroundColor:[UIColor blackColor]];
[numLabel setTextAlignment:UITextAlignmentCenter];
[numLabel setTextColor:[UIColor whiteColor]];
[imageView addSubview:numLabel];
[numLabel release];
}

// edit the page image view each position
[imageView setCenter:CGPointMake(40 * i, self.frame.size.height / 2)];
imageView.layer.borderWidth = 2;
imageView.layer.borderColor = [UIColor grayColor].CGColor;
imageView.layer.cornerRadius = 8;
imageView.layer.masksToBounds = TRUE;
}
}

- (void)setCurrentPage:(NSInteger)page
{
// super class function
[super setCurrentPage:page];

// clean all image view select state
for (int i = 0; i < [self.subviews count]; i++)
{
UIImageView* imageView = [self.subviews objectAtIndex:i];
UILabel* numLabel = [imageView.subviews objectAtIndex:0];
[numLabel setBackgroundColor:[UIColor blackColor]];
[numLabel setTextColor:[UIColor whiteColor]];
}

// update the current select page image view state
UIImageView* imageView = [self.subviews objectAtIndex:page];
UILabel* numLabel = [imageView.subviews objectAtIndex:0];
[numLabel setBackgroundColor:[UIColor whiteColor]];
[numLabel setTextColor:[UIColor blackColor]];
}

2011年4月12日 星期二

修改UIActionSheet的Button風格

利用UIActionSheetDelegate的Callback Function就可以做到自定義風格


- (void)willPresentActionSheet:(UIActionSheet *)actionSheet  // before animation and showing view
{
    // 搜尋UIActionSheet中的Action Sheet Button View
    for (UIView* view in [actionSheet subviews])
    {
        if ([[[view class] description] isEqualToString:@"UIThreePartButton"])
        {
            if ([view respondsToSelector:@selector(title)])
            {
                // 修改位置
                NSString* title = [view performSelector:@selector(title)];
                if ([title isEqualToString:@"Button 1"] && [view respondsToSelector:@selector(setEnabled:)])
                {
                    [view performSelector:@selector(setEnabled:) withObject:NO];
                }
            }
        }
    }
}

2011年2月23日 星期三

UITabBar更改背景色彩方法

今天在做介面設計時,
突然之間想利用UITabBar,
不過UITabBar本身背景色係黑色,
太單調了,所以想到要清空它的背景色,
於是在網上找到思路,實現了

其實原理很簡單,哪個黑色背景原來是在UIView的drawRect:畫上去的,
因此我利用了Objective-c的method特性就完成了我的目的

@implementation UITabBar (CustomBackgound)
- (void)drawRect:(CGRect)rect {
}
@end

之後alloc UITabBar時設定它的背景色為clear color即可。

PS.1:其實你還可以利用subclass去達到相同效果
PS.2:這個方法不止可以清空背景,還可以利用圖片去作UITabBar的背景

UISlider不見了軌道的方法

@interface UINoBgSlider : UISlider
{
}

@end

@implementation UINoBgSlider

// implementation this method to not draw the slider track
- (CGRect)trackRectForBounds:(CGRect)bounds
{
return CGRectZero;
}

// implementation this method to handle the slider thumb control position
- (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value
{
return CGRectMake(x, y, width, height);
}

@end

2011年2月16日 星期三

令iPhone SDK代碼分辨是「模擬器」還是「真機」

在開發 iPhone 軟件的過程中,有時會用到一些功能是無法在模擬器內運作。
可以用以下方法去使用SDK代碼分辨是「模擬器」還是「真機」

#if (TARGET_IPHONE_SIMULATOR)
// Simulator
#endif

#if !(TARGET_IPHONE_SIMULATOR)
// Real device
#endif

轉貼至:Pacess Laboratory

iPhone SDK-使用NSTimerInterval計算時差

今日用到NSTimerInterval去計算時間,
NSTimerInterval本身是以秒為單為,
所以兩個NSTimerInterval相減就可以得到時間差

NSTimerInterval轉為分鐘:
minutes = floor(NSTimerInterval/60);

NSTimerInterval轉為小時:
minutes = floor(NSTimerInterval/3600);