Geek@Paris
  • Update your GitHub fork repo from its original repo

    2011-04-27
    //the active directory in the prompt to the newly cloned "ProjectName" directory
    $ cd ProjectName
    //Assigns the original repo to a remote called "upstream"
    $ git remote add upstream git:/ /github.com/theOriginalAuthor/ProjectName.git
    //Fetches any new changes from the original repo
    $ git fetch upstream
    //Merges any changes fetched into your working files
    $ git merge upstream/master
    Author:admin | Categories:Dev | Tags:
  • Save any UIView to PNG files

    2011-03-22
    //Get the view from a specific window
    UIView *view = [[[[[UIApplication sharedApplication] windows] objectAtIndex:1] subviews] lastObject];
     
    //Will be used for naming png files
    NSInteger index = 0;
     
    //Check each subView
    for (UIView *subView in [view subviews]) {
    	//Find the UIView you need
    	if ([subView isKindOfClass:NSClassFromString(@"UIImageView")] || [subView isKindOfClass:NSClassFromString(@"UIThreePartButton")]) {
    		//Very important to support retina screen
    		if(UIGraphicsBeginImageContextWithOptions != NULL)
    			UIGraphicsBeginImageContextWithOptions(subView.frame.size, NO, 0.0);
    		else
    			UIGraphicsBeginImageContext(subView.frame.size);
     
    		//Get the image
    		[subView.layer renderInContext:UIGraphicsGetCurrentContext()];
    		UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    		UIGraphicsEndImageContext();
     
    		//Save the image
    		NSString *path=[NSHomeDirectory() stringByAppendingFormat:@"/%d.png",index];
    		if ([UIImagePNGRepresentation(image) writeToFile:path atomically:YES]) {
    			index += 1;
    			NSLog(@"Succeeded!");
    		}
    		else {
    			NSLog(@"Failed!");
    		}
    	}
    }
    Author:admin | Categories:Dev | Tags:
  • Key-Value Observing, Key-Value Coding, Key-Value Bindings

    2010-11-26

    1, KVO (Key-Value Observing Programming Guide)
    KVO is a mechanism to notify observers automatically when the observed object’s value is changed.
    Register an observation

    - (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context

    Example:

    [observedObject addObserver:observer forKeyPath:@"keyPath"];//Register the observation here.

    Remove a registered observation

    - (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath

    Example:

    [observedObject removeObserver:observer forKeyPath:@"keyPath"];//Remember to remove the registration to avoid crashing.

    Receiving value changed messages

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    //You will get messages here.
    }

    2, KVC (Key-Value Coding Programming Guide)
    KVC is a mechanism allows application to access an object’s properties by name (or key).
    Before KVC:

    - (id)tableView:(NSTableView *)tableview
          objectValueForTableColumn:(id)column
                                row:(int)row
    {
        ChildObject *child = [childrenArray objectAtIndex:row];
        if ( [[column identifier] isEqualToString:@"name"] ) {
            return [child name];
        }
        if ( [[column identifier] isEqualToString:@"age"] ) {
            return [child age];
        }
        if ( [[column identifier] isEqualToString:@"favoriteColor"] ) {
            // etc...
        }
        // etc...
    }

    After KVC:

    - (id)tableView:(NSTableView *)tableview
          objectValueForTableColumn:(id)column
                                row:(int)row
    {
        ChildObject *child = [childrenArray objectAtIndex:row];
        return [child valueForKey:[column identifier]];
    }

    Be careful, if the application can’t find the key, it will try to call valueForUndefinedKey:, and if the object doesn’t override this method, it will raise an exception called NSUndefinedKeyException.

    3, KVB (Cocoa Bindings Programming)
    “Cocoa bindings supports multiple ways of viewing your data, and automatically synchronizes views when models change.”

    - (void)bind:(NSString *)binding toObject:(id)observableController withKeyPath:(NSString *)keyPath options:(NSDictionary *)options

    example:

    [self.view bind:@"frame" toObject:anotherView withKeyPath:@"frame" options:nil];

    After that, self.view will always have the same frame as anotherView, no need to use NSNotification or any other complicated mechanism.

    Author:admin | Categories:Dev | Tags:
  • Stop editing NSTextField

    2010-10-13

    I only post some results here. Reference from http://www.cocoabuilder.com/archive/cocoa/230825-stop-edit-session-with-nstextfield.html?q=+Stop+edit+session+with+a+NSTextField#230825

    Failed solutions:
    1,

    [[[self view] window] endEditingFor:nil];

    Pressing return or pressing the tab key will not end the editing session
    2,

    [[[self view] window] makeFirstResponder:[self view]];

    Pressing return will allow the editing session to end, but pressing the tab key will not
    3,

    NSTextView *fieldEditor = [[aNotification userInfo] objectForKey:@"NSFieldEditor"];
    NSView *v = fieldEditor;
    while ( v && ( [v superview] != [aNotification object] ) )
    v = [v superview];
    [v removeFromSuperview];

    Pressing return or pressing the tab key will not end the editing session

    The editing session was started with:

    [textField selectText:nil];
    NSTextView    *currentEditor    = (NSTextView*)[textField currentEditor];
    NSPoint        windowLocation    = [theEvent locationInWindow];
    NSPoint        screenLocation    = [[self window] convertBaseToScreen:windowLocation];
    NSUInteger    characterIndex    = [currentEditor characterIndexForPoint:screenLocation];
    [currentEditor setSelectedRange:NSMakeRange( characterIndex + 1, 0 )];

    For me, I use [[[self view] window] makeFirstResponder:[self view]] to stop the text field by enter key.

    And use NSWindow’s setAutorecalculatesKeyViewLoop:YES to stop the text field by tab key.

    So both of them are solved.

    Author:admin | Categories:Dev | Tags:
  • 研究了一下CATiledLayer的levelsOfDetail和levelsOfDetailBias的含义

    2010-09-02

    levelsOfDetail是指,从UIScrollView的1倍zoomScale开始,能够支持细节刷新的缩小级数。每一级是上一级的1/2,所 以假设levelsOfDetail = n,levelsOfDetailBias不指定的话,CATiledLayer将会在UIScrollView的zoomScale为以下数字时重新 drawLayer
    2^-1 -> 2^-2 -> … -> 2^-n
    也就是
    1/2, 1/4, 1/8, 1/16, … , 1/2^n

    在levelsOfDetailBias不指定的情况下,zoomScale大于0.5后就不会再drawLayer,所以若继续放大UIScrollView的话,画面将越来越模糊。

    这个时候levelsOfDetailBias就有用了。
    levelsOfDetailBias = m表示,将原来的1/2,移到2^m倍的位置。
    假设levelsOfDetail = n,levelsOfDetailBias = m的话,会有如下队列:
    2^m * 2^-1 -> 2^m * 2^-2 -> … -> 2^m * 2^-n
    简化一下即
    2^(m – 1) -> 2^(m – 2) -> 2^(m – 3) ->… -> 2^(m – n)

    举例,levelsOfDetail = 3,levelsOfDetailBias = 3,则你的UIScrollView将会在以下zoomScale时drawLayer
    2^(3 – 1) -> 2^(3 – 2) -> 2^(3 – 3)
    即4 -> 2 -> 1

    特例是,levelsOfDetailBias > levelsOfDetail时,则每相差2倍就会drawLayer一下。

    可以简单理解成:
    levelsOfDetail表示一共有多少个drawLayer的位置
    levelsOfDetailBias表示比1大的位置里有多少个drawLayer的位置(包括1)

    以上若还没看懂的话,以下是图(点开看原始大小)
    图中灰色的格子表示跨界的格子,它们本来是同一个格子,被1这条线分割了。

    Author:admin | Categories:Dev | Tags:
  • A simple tutorial of UISearchDisplayController (iOS 3-7)

    2010-02-25

    After several years, thanks to StoryBoard and iOS 7, it becomes super easy to use Search Display Controller now.
    I attached a new sample project here, hope it could help everyone who needs it.

    SearchDisplayControllerDemo

    UISearchDisplayController iOS 7

    I find out that, the API for UISearchDisplayController in SDK 3.0b is different from 3.0. And there’s no sample code for UISearchDisplayController anywhere else until now. (Yes, there is one in Apple’s sample code web page, but it uses Interface Builder to realize it. And there is one from the source code of “three20”, but it’s based on SDK 3.0b. )

    So I wrote this sample based on “Table Search” sample code.It realizes UISearchDisplayController programmatically without Interface Builder. It supports landscape screen and search scopes, and integrate one UITabBarController with two UITableViewControllers.

    Here is the tutorial.

    @interface

    1. Declare an instance of UISearchDisplayController and set as property.
    2. Prepare two arrays to hold original data and filtered data.

    @implementation

    1. Set up viewDidLoadmethod
      1. Create an UISearchBar.
      2. Initialize the UISearchDisplayController based on the UISearchBar:
        1
        
        [[UISearchDisplayController alloc] initWithSearchBar:mySearchBar contentsController:self];
      3. Set the UISearchDisplayController instance:
        1
        2
        3
        
        [self setSearchDisplayController:searchDisplayController];
        [searchDisplayController setDelegate:self];
        [searchDisplayController setSearchResultsDataSource:self];
    2. Set up UISearchDisplayController delegate methods:
        1
        2
        3
        
        - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
        - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
        - (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller

        Be careful, we need to set the delegate for self.searchDisplayController.searchResultsTableView each time we begin to search. Because the instance of searchResultsTableView is allocated and released automatically.

    3. Set up UITableView data source and delegate methods, we distinguish filtered or not filtered table by
        1
        
        if (tableView == self.searchDisplayController.searchResultsTableView)
    4. Remember to return YES in shouldAutorotateToInterfaceOrientation to support landscape screen.


    Some details need to be cared:

    1. self.searchDisplayController.searchResultsTableView is created and release automatically, so its delegate should be setted each time it’s created.
    2. Every time we turn to a landscape UITableViewController, the UISearchBar in the tableHeaderView has only a width of 320 even we have already setted sizeToFit. It’s may be caused by UITabBarController, I don’t know. So I set the frame of tableHeaderView based on the screen orientation manually in the viewDidLoad method.

    Sample Code(.zip)
    Or get the project from GitHub : CBSearchDisplayControllerSample

    Author:admin | Categories:Dev | Tags: