2013年6月26日 星期三

觸發特定點擊區域

- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event{
   
    //如果touch到closeButton的區域,就觸發closeButton
    CGPoint pt = [[touches anyObject]locationInView:self.view];
    if (pt.x>closeButton.frame.origin.x &&
        pt.x<closeButton.frame.origin.x+closeButton.frame.size.width &&
        pt.y>closeButton.frame.origin.y &&
        pt.y<closeButton.frame.origin.y+closeButton.frame.size.height)
    {
        [self closeButtonTapped:touches];
    }

}

2013年6月24日 星期一

讀取tmp路徑

NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"temp.pdf"];

2013年6月18日 星期二

objective C 也有 try catch方法

 NSString *test = @"test";
    unichar a;
    int index = 5;

    @try {
        a = [test characterAtIndex:index];
    }
    @catch (NSException *exception) {
        NSLog(@"%@", exception.reason);
    }
    @finally {
        NSLog(@"Char at index %d cannot be found", index);
        NSLog(@"Max index is: %d", [test length]-1);
    }
Log:
[__NSCFConstantString characterAtIndex:]: Range or index out of bounds
Char at index 5 cannot be found
Max index is: 3

C++ assert()的意思

assert 的用法

可用來除錯。

用法很簡單。沒有回傳值,只要 assert() 括號內的值是 false 就直接結束程式,並印出是哪一行、什麼情況下跳出的。

使用前需 include assert.h。

多UIView間touch事件傳值

原本是用一個delegate去選擇touch要停留在那一個UIView回應,
後來發現下面這個方式更好,你可以隨意選擇你要按那一個UIView甚至可以同時觸發二個以上!

把要touch事件trigger寫在UIViewController中,如下面三個function,
然後把要觸發的UIView都加到這個UIViewController中,用下列方式呼叫,
這樣的好處是也可以對父類別的touch事件做呼叫

// Pass touches on to the AR view (EAGLView)
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
  
    // pass events down to parent ViewController
    // super是用來呼叫父類別的方法
    [super touchesBegan:touches withEvent:event];

    // 對自己view做匯入,之後以自己收到的touch去呼叫view的touch事件
    [arViewController.arView touchesBegan:touches withEvent:event];
}


- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
    [arViewController.arView touchesEnded:touches withEvent:event];
}


- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    // Implemented only to prevent the super class methods from executing
}

// 在使用這個方式前,記得在其他view加入下面指令,以確保touch事件都能直接觸到parientViewController
        self.userInteractionEnabled = NO;

2013年6月17日 星期一

XCODE註解與取消註解

縮排 command + [
反向縮排 command + ]
註解 command + /
取消註解 先用反縮排把//移到行首,再按command + / ,即可取消註解

2013年6月13日 星期四

在xcode把沒有git的專案加入git

一,先把專案丟到桌面
二,用xcode在你原本放專案的地方建立一個同名的新專案,記得把create repository打勾
三,關掉xcode
四,刪除新專案資料匣的所有檔案
五,把桌面上你原來專案的檔案拉到新建立同名專案的資料夾中
六,點二下開始專案,就可以看到GIT已經存在了
七,去commit一個新initial commit,因為原來的initial commit是剛剛那個空專案
八,have fun!!

2013年6月10日 星期一

在objective-C宣告singleton

在YourClass中加入下列的初始化方法
status YourClass* singleton;
+ ( YourClass* ) initWithSingleton{

    @synchronized( self ){
   
        if ( ! singleton )
            singleton = [ [ YourClass alloc ] init ];

    }

    return singleton;

}

這邊的重點有四個
第一:以+宣告Class method,讓我們可以在實例被宣告之前就可以呼叫這個method。
第二:以status將singleton宣告為靜態實例。
第三:合成實例時,對getter做手腳,如果實例已經存在,則不宣告新的實例,直接return已存在的。
第四:用@synchronized()來控制不會被其他執行緒存取

另一種
+(BooksManager *)sharedInstance
{
    @synchronized(self)
    {
        if (sharedInstance == nil)
        {
            sharedInstance = [[self alloc] init];
        }
    }
    return sharedInstance;
}

下載影片

// 大影片(35 MB)
#define LARGE_URL @"http://www.archive.org/download/BettyBoopCartoons/Betty_Boop_More_Pep_1936_512kb.mp4"

// 小影片(3 MB)
#define SMALL_URL @"http://www.archive.org/download/Drive-inSaveFreeTv/Drive-in--SaveFreeTv_512kb.mp4"

// 無效的影片網址
#define FAKE_URL @"http://www.idontbelievethisisavalidurlforthisexample.com"

#define DEST_PATH    [NSHomeDirectory() stringByAppendingString:@"/Documents/Movie.mp4"]


// 選擇下載哪個項目
    NSArray *items = [NSArray arrayWithObjects: SMALL_URL, LARGE_URL, FAKE_URL, nil];
    NSString *whichItem = [items objectAtIndex:seg.selectedSegmentIndex];
    NSURL *sourceURL = [NSURL URLWithString:whichItem];

    // 移除任何已存在的資料
    if ([[NSFileManager defaultManager] fileExistsAtPath:DEST_PATH])
        [[NSFileManager defaultManager] removeItemAtPath:DEST_PATH error:nil];
   
    // 啟動網路活動指示器
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
   
    // 在新的NSOperationQueue裡進行下載
    [[[NSOperationQueue alloc] init] addOperationWithBlock:
     ^{
         [self getData:sourceURL];
         [[NSOperationQueue mainQueue] addOperationWithBlock:^{
             // 在主緒程裡處理收尾工作
             [self downloadFinished];
         }];
     }];

iOS App沙箱路徑

//用來得到App的存放目錄的路徑,在該目錄下有三個folder:一、Documents,二、Library,三、Temp,除此之外還有一個編譯完程式碼.app檔。
//這個目錄就是app的sandbox,代表這個iOS App只能存取這個目錄的範圍。
NSString *path = NSHomeDirectory();

//沙箱中的路徑
NSString *moviePath = [NSHomeDirectory() stringByAppendingString:@"/Documents/Movie.mp4"]; 

//公司測試機的沙箱路徑
/var/mobile/Applications/DEA6AF92-2D7C-435D-A318-XXXXXXXXXXXX/Documents/Movie.mp4


iPhone的檔案系統

因為安全性的因素,在iPhone OS下,每一個軟體的檔案以及資料夾都是被獨立隔開的,而每一個軟體可以讀取、寫入的檔案系統,大概可以用下列的結構顯示:
  • <程式根目錄>
    • 我的程式.app (程式的主要資料夾,只能讀取)
      • 我的程式
      • MainWindow.xib
      • 其他在Xcode中所加入的Resources
    • Documents
    • Library
      • Cache
      • Preference
以上這些資料,大多都會在iTunes同步時備份起來,而那我們要如何取得這些資料夾的路徑呢?請參考以下方法:
// 基本的目錄
NSString *homePath = NSHomeDirectory(); // 根目錄
NSString *tmpPath = NSTemporaryDirectory(); // 暫存目錄
// Documents 資料夾
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
// <程式根目錄>/Documents/foo.plist
NSString *fooPath = [documentsPath stringByAppendingPathComponent:@“foo.plist”];

2013年6月7日 星期五

跨執行緒存取UIKit會crash的解法

//把你要執行的程式包在 dispatch_async( dispatch_get_main_queue(), ^{......});裡面, 以主執行緒去執行。
dispatch_async( dispatch_get_main_queue(), ^{
                                                           [[NSNotificationCenter defaultCenter] postNotificationName:@"presentOfficialWebview" object:nil];        
                                                                });

小心int的除法

用除法時,型別不會自動轉換
千萬小心

300/600 等於 0

300.0/600.0 才會等於 0.5

2013年6月5日 星期三

實機測試時出現Could not change executable permissions on the application

因為iPhone上已經存在相同bundle ID的App,
將iPhone上原來的App刪除,或是改掉現在的bundle ID就可以成功。

2013年6月3日 星期一

在高通openGL中take a screenshot

- (BOOL)presentFramebuffer
{
    if (takePhoto)
    {
        [self glToUIImage];
        takePhoto = NO;
    }
 
....remaining code ...
}



- (UIImage*) glToUIImage

{
    GLint backingWidth, backingHeight;
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
    
    CGRect s = CGRectMake(0, 0, backingWidth, backingHeight);
    
    uint8_t *buffer = (uint8_t *) malloc(s.size.width * s.size.height * 4);
    glReadPixels(0, 0, s.size.width, s.size.height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
    CGDataProviderRef ref = CGDataProviderCreateWithData(NULL, buffer, s.size.width * s.size.height * 4, NULL);
    CGImageRef iref = CGImageCreate(s.size.width, s.size.height, 8, 32, s.size.width * 4, CGColorSpaceCreateDeviceRGB(),
                                    kCGBitmapByteOrderDefault, ref, NULL, true, kCGRenderingIntentDefault);
            
    size_t width = CGImageGetWidth(iref);
    size_t height = CGImageGetHeight(iref);
    size_t length = width * height * 4;
    uint32_t *pixels = (uint32_t *)malloc(length);
    
    CGContextRef cgcontext = CGBitmapContextCreate(pixels, width, height, 8, width * 4,
                                                 CGImageGetColorSpace(iref), kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big);
    
    CGAffineTransform transform = CGAffineTransformIdentity;
    transform = CGAffineTransformMakeTranslation(0.0f, height);
    transform = CGAffineTransformScale(transform, 1.0, -1.0);
    CGContextConcatCTM(cgcontext, transform);
    CGContextDrawImage(cgcontext, CGRectMake(0.0f, 0.0f, width, height), iref);
    CGImageRef outputRef = CGBitmapContextCreateImage(cgcontext);
    
    UIImage* outputImage = [UIImage imageWithCGImage:outputRef];
    UIImageWriteToSavedPhotosAlbum(outputImage, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
    
    CGDataProviderRelease(ref);
    CGImageRelease(iref);
    CGContextRelease(cgcontext);
    CGImageRelease(outputRef);
    
    free(pixels);
    free(buffer);
    
    NSLog(@"Screenshot size: %d, %d", (int)[outputImage size].width, (int)[outputImage size].height);
    
    return outputImage;
}


// callback for UIImageWriteToSavedPhotosAlbum
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
    
    if (error) {
        NSLog(@"Photo save error");
    }
    else {
        NSLog(@"Photo saved");
    }
}