<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3842656223346596627</id><updated>2024-09-15T17:56:53.770-07:00</updated><title type='text'>Ho Wang&#39;s iPhone Development Blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://howanghk-iphone.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3842656223346596627/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://howanghk-iphone.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Ho Wang</name><uri>http://www.blogger.com/profile/11673562870503071613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbPehpP-Zpsgd56Y4aO7u6gdMeMR67fGVXICZ4UiAaOPAPygj8RFm_3AhkLfOAh0iAvL9QBYVK5cKUNPwY0tWxLTMn2QEbDG0E-lRr4C_qnmIBo4UEiCNSHt6pFW-Bmf4/s220/howang.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>5</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3842656223346596627.post-5313229022037441828</id><published>2013-01-02T22:49:00.001-08:00</published><updated>2013-02-03T10:57:57.227-08:00</updated><title type='text'>上傳 git repo 到 server 上用作 remote</title><content type='html'>把 local git repo 上傳到 server 並設定 git remote&lt;br /&gt;
假設:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;用戶名為 user&lt;/li&gt;
&lt;li&gt;伺服器為 server.tld&lt;/li&gt;
&lt;li&gt;repo 名稱為 myrepo&lt;/li&gt;
&lt;li&gt;repo 儲存在 /var/repo/ 中&lt;/li&gt;
&lt;li&gt;remote 名稱為 origin&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: bash&quot; style=&quot;overflow: scroll;&quot;&gt;ssh user@server.tld
mkdir /var/repo/myrepo
exit
tar jcvf myrepo_git.tar.bz2 .git
scp myrepo_git.tar.bz2 user@server.tld:/var/repo/myrepo/
ssh user@server.tld
cd /var/repo/myrepo/
tar jxvf myrepo_git.tar.bz2
git config --bool core.bare true
exit
git remote add origin ssh://user@server.tld/var/repo/myrepo
# try modify some files and commit it to local repo here
git push origin master
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://howanghk-iphone.blogspot.com/feeds/5313229022037441828/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://howanghk-iphone.blogspot.com/2013/01/git-repo-server-remote.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3842656223346596627/posts/default/5313229022037441828'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3842656223346596627/posts/default/5313229022037441828'/><link rel='alternate' type='text/html' href='http://howanghk-iphone.blogspot.com/2013/01/git-repo-server-remote.html' title='上傳 git repo 到 server 上用作 remote'/><author><name>Ho Wang</name><uri>http://www.blogger.com/profile/11673562870503071613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbPehpP-Zpsgd56Y4aO7u6gdMeMR67fGVXICZ4UiAaOPAPygj8RFm_3AhkLfOAh0iAvL9QBYVK5cKUNPwY0tWxLTMn2QEbDG0E-lRr4C_qnmIBo4UEiCNSHt6pFW-Bmf4/s220/howang.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3842656223346596627.post-268493644277352415</id><published>2011-11-18T10:07:00.001-08:00</published><updated>2011-11-18T10:57:34.678-08:00</updated><title type='text'>在 Objective-C 上 delay 執行一段 code</title><content type='html'>有時候，我們需要在 Objective-C 上 delay 執行一段 code，該如何處理呢？以往的做法通常需要新增一個 method，再用 [self performSelector:@selector(xxx) withObject:obj afterDelay:1.23] 的方法。幸好，在 iOS 4.0 / Mac OS X 10.6 之後，Apple 加入了 Grand Central Dispatch 技術，可以使用 Objective-C 的 block 而不用新增 method。&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: objc&quot;&gt;- (void)performBlock:(void (^)(void))block afterDelay:(NSTimeInterval)delay
{
 int64_t delta = (int64_t)(1.0e9 * delay);
 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delta), dispatch_get_main_queue(), block);
}
&lt;/pre&gt;
&lt;br /&gt;
使用方法：&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: objc&quot;&gt;[self performBlock:^{
 // Lines of code
} afterDelay:1.23];
&lt;/pre&gt;
&lt;br /&gt;
&lt;a href=&quot;http://forrst.com/posts/Delayed_Blocks_in_Objective_C-0Fn&quot;&gt;原文&lt;/a&gt; 出自 Matthias Plappert。</content><link rel='replies' type='application/atom+xml' href='http://howanghk-iphone.blogspot.com/feeds/268493644277352415/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://howanghk-iphone.blogspot.com/2011/11/objective-c-delay-code.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3842656223346596627/posts/default/268493644277352415'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3842656223346596627/posts/default/268493644277352415'/><link rel='alternate' type='text/html' href='http://howanghk-iphone.blogspot.com/2011/11/objective-c-delay-code.html' title='在 Objective-C 上 delay 執行一段 code'/><author><name>Ho Wang</name><uri>http://www.blogger.com/profile/11673562870503071613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbPehpP-Zpsgd56Y4aO7u6gdMeMR67fGVXICZ4UiAaOPAPygj8RFm_3AhkLfOAh0iAvL9QBYVK5cKUNPwY0tWxLTMn2QEbDG0E-lRr4C_qnmIBo4UEiCNSHt6pFW-Bmf4/s220/howang.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3842656223346596627.post-8083858990094366264</id><published>2010-08-20T02:07:00.000-07:00</published><updated>2011-11-18T10:58:34.072-08:00</updated><title type='text'>在 Project 中加入 SVN version 和 Build Count</title><content type='html'>為方便加入版本資訊，可使用以下 script，在 Project 的 target 中，right click，New Build Phase，New Run Script Build Phase，之後輸入以下 script，Shell 用 /bin/bash 。&lt;br /&gt;
之後可以 #import &quot;SVNRevision.h&quot; 取得 SVN_REVISION 數值。&lt;br /&gt;
&lt;pre class=&quot;brush: objc&quot; style=&quot;overflow: scroll;&quot;&gt;parse_svnversion()
{
    if [[ &quot;$1&quot; = *:* ]]; then
        arr[0]=${1%:*}
        arr[2]=${1//[0-9:]/}
        tmp_arr[1]=${1#*:}
        arr[1]=${tmp_arr[1]//${arr[2]}/}
    else
        arr[2]=${1//[0-9:]/}
        arr[0]=${1//${arr[2]}/}
        arr[1]=${arr[0]}
    fi

    echo $( (( ${arr[0]} &gt; ${arr[1]} )) &amp;&amp; echo ${arr[0]} || echo ${arr[1]} )
}

SVN_REV=$(parse_svnversion `svnversion -n`)
echo &quot;#define SVN_REVISION @\&quot;$SVN_REV\&quot;&quot; &gt; &quot;${PROJECT_DIR}/Classes/SVNRevision.h&quot;
exit 0
&lt;/pre&gt;parse_svnversion 出自 SiegeX 大大，&lt;a href=&quot;http://stackoverflow.com/questions/1905980/split-svnversion-output-in-bash/1906542&quot;&gt;原文&lt;/a&gt;在 StackOverflow 上。</content><link rel='replies' type='application/atom+xml' href='http://howanghk-iphone.blogspot.com/feeds/8083858990094366264/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://howanghk-iphone.blogspot.com/2010/08/project-svn-version-build-count.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3842656223346596627/posts/default/8083858990094366264'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3842656223346596627/posts/default/8083858990094366264'/><link rel='alternate' type='text/html' href='http://howanghk-iphone.blogspot.com/2010/08/project-svn-version-build-count.html' title='在 Project 中加入 SVN version 和 Build Count'/><author><name>Ho Wang</name><uri>http://www.blogger.com/profile/11673562870503071613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbPehpP-Zpsgd56Y4aO7u6gdMeMR67fGVXICZ4UiAaOPAPygj8RFm_3AhkLfOAh0iAvL9QBYVK5cKUNPwY0tWxLTMn2QEbDG0E-lRr4C_qnmIBo4UEiCNSHt6pFW-Bmf4/s220/howang.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3842656223346596627.post-1091558723713066002</id><published>2010-06-22T09:34:00.000-07:00</published><updated>2011-11-18T11:00:03.733-08:00</updated><title type='text'>NSInvocation 用在 class method 上</title><content type='html'>為了能簡單地調用 NSInvocation 去 invoke class method (+)，特意寫了一個 HWInvocation，是 NSInvocation 的 category，加入了一個新的 constructor。寫完後也順手寫了 instance method (-) 版本的 constructor。&lt;br /&gt;
HWInvocation 利用了 Objective-C 的 &lt;a href=&quot;http://developer.apple.com/mac/library/qa/qa2005/qa1405.html&quot;&gt;Variable Arguments&lt;/a&gt; 功能，不用 call 無數個 setArgument，可以在 constructor 中一次過輸入所有 arguments。&lt;br /&gt;
另外 Sample Code 中示範了怎樣傳 NSObject 和非 NSObject 類變數到 NSInvocation 中，其秘訣是使用 address of (&amp;) 去取得 memory address (pointer)。&lt;br /&gt;
&lt;br /&gt;
SampleCode.m&lt;br /&gt;
&lt;pre class=&quot;brush: objc&quot; style=&quot;overflow: scroll&quot;&gt;#import &quot;HWInvocation.h&quot;

// ... other code skipped ...

+ (void)setSomething:(BOOL)yesOrNo str:(NSString *)string
{
 NSLog(@&quot;setSomething: %@ - %@&quot;,(yesOrNo == YES ? @&quot;YES&quot; : @&quot;NO&quot;),string);
}

- (void)setOtherThing:(int)num str:(NSString *)string
{
 NSLog(@&quot;setOtherThing: %d - %@&quot;,num,string);
}

- testInvocation {
 NSString *str = @&quot;Testing HWInvocation&quot;;
 BOOL yes = YES;
 int num = 123;
 NSInvocation *invocation;
 
 invocation = [NSInvocation classMethodInvocationWithSelectorName:@&quot;setSomething:str:&quot; baseClass:[SampleCode class] args:&amp;yes,&amp;str];
 [invocation tryInvoke];
 
 invocation = [NSInvocation invocationWithSelectorName:@&quot;setOtherThing:str:&quot; target:self args:&amp;num,&amp;str];
 [invocation tryInvoke];
}
&lt;/pre&gt;&lt;br /&gt;
HWInvocation.h&lt;br /&gt;
&lt;pre class=&quot;brush: objc&quot; style=&quot;overflow: scroll&quot;&gt;#import &amp;lt;Foundation/Foundation.h&amp;gt;

@interface NSInvocation (HWInvocation)

+ (NSInvocation *)classMethodInvocationWithSelectorName:(NSString *)selname baseClass:(Class)class args:(void *)buffer, ...;
+ (NSInvocation *)invocationWithSelectorName:(NSString *)selname target:(id)target args:(void *)buffer, ...;
- (BOOL)tryInvoke;

@end
&lt;/pre&gt;HWInvocation.m&lt;br /&gt;
&lt;pre class=&quot;brush: objc&quot; style=&quot;overflow: scroll&quot;&gt;#import &quot;HWInvocation.h&quot;
#import &amp;lt;objc/runtime.h&amp;gt; // Needed for the ISA pointer

@implementation NSInvocation (HWInvocation)

+ (NSInvocation *)classMethodInvocationWithSelectorName:(NSString *)selname baseClass:(Class)class args:(void *)buffer, ...
{
 SEL aSelector;
 NSMethodSignature *signature;
 NSInvocation *invocation;
 int numOfArgs;
 int i = 3; // Index to place the first variable argument
 void *buf;
 va_list argumentList;
 
 aSelector = NSSelectorFromString(selname);
 if (aSelector == NULL) return nil;
 
 signature = [class-&gt;isa instanceMethodSignatureForSelector:aSelector];
 if (signature == nil) return nil;
 
 numOfArgs = [signature numberOfArguments];
 
 invocation = [NSInvocation invocationWithMethodSignature:signature];
 if (invocation == nil) return nil;
 
 [invocation setTarget:class];
 [invocation setSelector:aSelector];
 
 if (numOfArgs &gt;= i)
 {
  [invocation setArgument:buffer atIndex:2];
  va_start(argumentList, buffer);
  while (i &lt; numOfArgs)
  {
   buf = va_arg(argumentList, id);
   [invocation setArgument:buf atIndex:i++];
  }
  va_end(argumentList);
 }
 
 return invocation;
}

+ (NSInvocation *)invocationWithSelectorName:(NSString *)selname target:(id)target args:(void *)buffer, ...
{
 SEL aSelector;
 NSMethodSignature *signature;
 NSInvocation *invocation;
 int numOfArgs;
 int i = 3; // Index to place the first variable argument
 void *buf;
 va_list argumentList;
 
 aSelector = NSSelectorFromString(selname);
 if (aSelector == NULL) return nil;
 
 signature = [target methodSignatureForSelector:aSelector];
 if (signature == nil) return nil;
 
 numOfArgs = [signature numberOfArguments];
 
 invocation = [NSInvocation invocationWithMethodSignature:signature];
 if (invocation == nil) return nil;
 
 [invocation setTarget:target];
 [invocation setSelector:aSelector];
 
 if (numOfArgs &gt;= i)
 {
  [invocation setArgument:buffer atIndex:2];
  va_start(argumentList, buffer);
  while (i &lt; numOfArgs)
  {
   buf = va_arg(argumentList, id);
   [invocation setArgument:buf atIndex:i++];
  }
  va_end(argumentList);
 }
 
 return invocation;
}

- (BOOL)tryInvoke
{
 @try
 {
  [self invoke];
  return YES;
 }
 @catch (NSException * e)
 {
  NSLog(@&quot;Invoke failed: %@&quot;,NSStringFromSelector([self selector]));
  return NO;
 }
 return NO;
}

@end
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://howanghk-iphone.blogspot.com/feeds/1091558723713066002/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://howanghk-iphone.blogspot.com/2010/06/nsinvocation-class-method.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3842656223346596627/posts/default/1091558723713066002'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3842656223346596627/posts/default/1091558723713066002'/><link rel='alternate' type='text/html' href='http://howanghk-iphone.blogspot.com/2010/06/nsinvocation-class-method.html' title='NSInvocation 用在 class method 上'/><author><name>Ho Wang</name><uri>http://www.blogger.com/profile/11673562870503071613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbPehpP-Zpsgd56Y4aO7u6gdMeMR67fGVXICZ4UiAaOPAPygj8RFm_3AhkLfOAh0iAvL9QBYVK5cKUNPwY0tWxLTMn2QEbDG0E-lRr4C_qnmIBo4UEiCNSHt6pFW-Bmf4/s220/howang.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3842656223346596627.post-2259343489020762631</id><published>2010-06-20T09:09:00.000-07:00</published><updated>2011-11-18T11:00:55.671-08:00</updated><title type='text'>Objective-C 神奇的 exchange implementation</title><content type='html'>在 Objective-C 中，我們可以交換兩個相同 method signature 的 method 內的 implementation，會令 call method A 時實際上運行 method B 的 code，而 call method B 時會運行 method A 的 code。&lt;br /&gt;
我們可以利用這個功能，去 &quot;hook&quot; 一些 API，修改其運作方式，對於新手來說這個功能是很危險的，但對於清楚 API 運作的高手來說，這個功能很有用，可以做一些 API 本身沒有的功能。&lt;br /&gt;
&lt;br /&gt;
ExchangeImp.h&lt;br /&gt;
&lt;pre class=&quot;brush: objc&quot; style=&quot;overflow: scroll&quot;&gt;
@interface NSObject (ExchangeImp)

+ (BOOL)exchangeMethod:(SEL)origSelector withMethod:(SEL)newSelector;

@end
&lt;/pre&gt;&lt;br /&gt;
ExchangeImp.m&lt;br /&gt;
&lt;pre class=&quot;brush: objc&quot; style=&quot;overflow: scroll&quot;&gt;#import &quot;ExchangeImp.h&quot;

@implementation NSObject (ExchangeImp)

+ (BOOL)exchangeMethod:(SEL)origSelector withMethod:(SEL)newSelector
{
    Method orgMethod = class_getInstanceMethod(self, orgSelector);
    Method newMethod = class_getInstanceMethod(self, newSelector);

    if ((orgMethod != NULL) &amp;&amp; (newMethod != NULL))
    {
        if (class_addMethod(self, orgSelector, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)))
        {
            class_replaceMethod(self, newSelector, method_getImplementation(orgMethod), method_getTypeEncoding(orgMethod));
        }
        else
        {
            method_exchangeImplementations(origMethod, newMethod);
        }
        return YES;
    }
    return NO;
}

@end
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://howanghk-iphone.blogspot.com/feeds/2259343489020762631/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://howanghk-iphone.blogspot.com/2010/06/objective-c-exchange-implementation.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3842656223346596627/posts/default/2259343489020762631'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3842656223346596627/posts/default/2259343489020762631'/><link rel='alternate' type='text/html' href='http://howanghk-iphone.blogspot.com/2010/06/objective-c-exchange-implementation.html' title='Objective-C 神奇的 exchange implementation'/><author><name>Ho Wang</name><uri>http://www.blogger.com/profile/11673562870503071613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbPehpP-Zpsgd56Y4aO7u6gdMeMR67fGVXICZ4UiAaOPAPygj8RFm_3AhkLfOAh0iAvL9QBYVK5cKUNPwY0tWxLTMn2QEbDG0E-lRr4C_qnmIBo4UEiCNSHt6pFW-Bmf4/s220/howang.png'/></author><thr:total>0</thr:total></entry></feed>