Friday, March 30, 2012

Autorelease, release, retain

在Objective-C中所有的物件都是指標,當我們建立一個物件時(由 alloc、new、copy 產生出來或是使用retain來取得從其他來源獲得的物件),我們不但配置了記憶體,同時也讓該物件的指標指向這個記憶體位址。 Objective-C使用reference counting的方式作為記憶體管理的機制,Reference Counting 的運作是基於 ownership。當程式要使用物件時,必須取得物件的 ownership,一個物件可以有很多 owner;而當程式不再使用物件時,則需要放棄 ownership。直到物件沒有任何 owner 時,物件就會自動被 dealloc。
物件第一次被建立時,只有一個owner的指標指向它的記憶體位址,所以它的reference count為1。若有新owner的指標指向該記憶體,它的reference count便會加1。相反的,如果我們不再需要這個指標,而將它release,該物件的reference count就會減1。當該物件的reference count變為零時,代表沒有指標指向它了,該物件的dealloc函式就會自動被呼叫,這時寫在dealloc裡的那些release指令就會一起被執行了,這塊記憶體就會被釋放掉。


在Objective-C建立物件有兩種方法,一種是手動配置記憶體並初始化該物件:


NSString *string = [[NSString alloc] init];
用這種方式宣告的物件,當我們不再需要使用時,必需手動呼叫release方法來釋放它。


另一種方法則是呼叫該類別的類別方法(Class method)直接建立該物件:


NSString *string = [NSString stringWithFormat:@"test string"];
這類方法所建立的物件我們不需要手動release它,當它被建立的同時,它也會被丟進一個叫做autorelease pool的「池子」裡。每當程式主要的loop執行完一次,就會檢查autorelease pool裡的物件是否還會被使用到,如果會就留著;如果不會就把它清掉。這種會把物件丟進autorelease pool的類別方法有個特點,就是他們的名稱開頭都會是該類別的字串。比如NSString,類別方法中開頭是stringXXX的,就會把建立的物件丟入autorelease pool。


要特別注意的是,autorelease跟release不同,release會馬上在執行後把retain count減1,而autorelease則是待會才會減1。另外,一但你把物件設定為autorelease之後,這個東西基本上就不算是你管的,你之後就不需要也不應該再去對它做release的動作了。


- (NSString *) getBookTitle {  
NSString *name = [[NSString alloc] initWithString:@"This is a book"];  
[name autorelease];  
return name; }


以上的code,因為name這個方法需要回傳值,如果第4行的[name autorelease]寫成了[name release],因為太早release掉name後,name就不會正確回傳了。不加上的話又會造成記憶體的泄漏(leaked)。所以這時候使用了autorelease就是正確的作法。上面的程式碼第2行常常會和autorelease合併簡寫為類似[[[NSString alloc] init] autorelease],或是把第3和4行合併簡寫為return [name autorelease]。



這裡提供幾個基本的原則,希望對還不熟悉記憶體管理的朋友們有些幫助:


  1. 如果是自已alloc或者retain的物件,最後一定要release掉。
  1. 用類別方法(Class method)建立的物件會被丟入autorelease pool,不需要手動釋放記憶體。



Reference:
http://bonjouryentinglai.wordpress.com/2010/02/10/objective-c-隨手筆記-ii-記憶體管理


http://marcelsite.heroku.com/posts/5-iPhone-s-alloc-init-new-retain-release-autorelease-copy-


http://log.bcse.tw/2011/05/ios-programming-tips-3.html

Monday, March 26, 2012

New app - PhotoUploads Lite (Free version)

New app "PhotoUploads Lite" is available in App Store.

This app lets you to upload the photos to Facebook, Flickr and Dropbox, and view the photos in the account.

http://itunes.apple.com/us/app/photouploads-lite/id511228591?mt=8

 

Sunday, March 25, 2012

To ping the server to determine if it is reachable

Here is the method to ping if the server is reachable.


- (BOOL)canPingServer {
    
    NSString *serverAddress = urlField.text;
    
    NSLog(@"ping domain: %@", serverAddress);
    
    Reachability* reachability = [[Reachability reachabilityWithHostName: serverAddress] retain];
    NetworkStatus netStatus = [reachability currentReachabilityStatus];
    
    if ((netStatus == ReachableViaWWAN) || (netStatus == ReachableViaWiFi)) 
            return YES;
    else 
            return NO;
    
}

Saturday, March 24, 2012

Dismiss UIAlertView without clicking the button

If need to dismiss the UIAlertView without clicking the button, we could use the below method.



-(void) showAlert {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Connecting to server" message:@"Please wait ..." delegate:self cancelButtonTitle:nil otherButtonTitles: nil];
[alert show];
}

-(void) anotherMethod {
yourCode...add the below method
[alert dismissWithClickedButtonIndex:0 animated:TRUE];
[alert release];
}



Saturday, March 17, 2012

NSMutableDictionary - write and read

Write value for key:
[progressDict setObject:@"Uploading ..." forKey:@"status"];
[progressDict setObject:[NSNumber numberWithInt:i] forKey:@"progress"];

Read value for key:
NSLog(@"key is status, value is %@",[dict objectForKey:@"status"]);
NSLog(@"key is progress, value is %@",[dict objectForKey:@"progress"] );

Saturday, March 3, 2012

Grab the image Data from web or mainBundle

-(void) grabImagefromURL
{
    NSURL *url = [NSURL URLWithString:@"http://cultofmac.cultofmaccom.netdna-cdn.com/wp-content/uploads/2010/01/apple-vs-google_2.jpg"];
    imageData = [NSData dataWithContentsOfURL:url];
    UIImage *image  = [[UIImage alloc] initWithData:imageData];
    myImageView.image = image;
    [image release];
    
}

- (void) grabImagefromFile
{

    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"lion" ofType:@"jpg"]; 

    UIImage *image = [UIImage imageWithContentsOfFile:filePath];
    UIImageView *imageView = [[UIImageView alloc] initWithImage:img];
    [self.view addSubview:imageView];

Set multi-lines in the label

Set the lines = 0 in the label tab, then the text can be shown as the multi-line in the UILabel. Actually it can be done in code too.

Mac - Screen capture


Command +Shift+3 
It captures entire screen and saves it in the desktop.

Command +Shift+4 
Use the mouse to select a specific area of the screen for capture saves it in the desktop, press ESC to dismiss.



Cmd+Ctrl+Shift 3
It captures the screenshot and keep it in clipboard


Cmd+Ctrl+Shift 4
It captures the selected screenshot and keep it in clipboard

Dismiss the keyboard when pressing the "Return" key

1. Except to use the IB to change the "Return" to be "Done" for the keyboard, it can be done in code as below.


 [myTextField setReturnKeyType:UIReturnKeyDone];

2. Dimiss the keyboard after pressing "Return" button for textfield, link this method to the "Did End on Exit" Event in the textfield. Remember to add UITextViewDelegate in .h file.

// dismisses the keyboard when a user selects the return key
- (IBAction)textFieldShouldReturn:(id)sender
{
    [sender resignFirstResponder];

    
}

3. If you want to dismiss the keyboard in the myTextView, please find the below code.

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    
    if([text isEqualToString:@"\n"]) {
        [myTextView resignFirstResponder];
        return NO;
    }
    
    return YES;
}
Besides it, you need to add UITextViewDelegate at .h file, also link delegate to file owner in reference outlet.

Custom navigation bar and toolbar

The below code can custom the font type on the navigation bar, make both navigation bar and toolbar to be translucent style, set up the left button to be "Back" in the next view.


// set navigation bar to be translucent style
    self.navigationController.navigationBar.barStyle = UIBarStyleBlackTranslucent;
    
// set custom font and size in the navigation bar
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 120, 40)];
    label.font = [UIFont fontWithName:@"Marker Felt" size: 22.0];
    label.BackgroundColor = [UIColor clearColor];
    label.textColor = [UIColor whiteColor];
    label.text = self.title;
    [self.navigationController.navigationBar.topItem setTitleView:label];
    [label release];
    
// set the left button to be "Back"
    UIBarButtonItem *backBtn = [[UIBarButtonItem alloc] initWithTitle:@"Back" style:UIBarButtonItemStyleDone target:nil action:nil];
    self.navigationItem.backBarButtonItem = backBtn;
    [backBtn release];

// set toolbar to be translucent style
    myToolbar.barStyle = UIBarStyleDefault;
    myToolbar.tintColor = [UIColor colorWithWhite:0.0 alpha:0.5];
    myToolbar.translucent = YES;