2015년 5월 11일 월요일

objc_setAssociatedObject , objc_getAssociatedObject


#import <objc/runtime.h>


예제1)

// set
    {
        objc_setAssociatedObject(self, @"ShouldDismissModalViewLater", modalViewController, OBJC_ASSOCIATION_ASSIGN);
    }
    
    // get and using
    {
        UIViewController *modalVC = objc_getAssociatedObject(self, @"ShouldDismissModalViewLater");
        [modalVC dismissViewControllerAnimated:YES completion:nil];
    }



예제2)

// set
    {
        NSArray *gotArray;
        objc_setAssociatedObject(self, @"MyGotArray", gotArray, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    // get and using
    {
        NSArray *array = objc_getAssociatedObject(self, @"MyGotArray");
        [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
            
        }];
    }


예제3)
Easier syntax
Alternatively you could use @selector(nameOfGetter) instead of creating a static pointer. Why? See http://stackoverflow.com/a/16020927/202451. Example:
- (NSArray *)laserUnicorns {
    return objc_getAssociatedObject(self, @selector(laserUnicorns));
}

- (void)setLaserUnicorns:(NSArray *)unicorns {
    objc_setAssociatedObject(self, @selector(laserUnicorns), unicorns, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 
}

async download images

NSURLSession를 이용한 방법)

xxx.h
NSURLSession *mealNewsUrlSession;

xxx.m

// initialization
mealNewsUrlSession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];


// use
NSURL *imageURL = [NSURL URLWithString:imagePath];
            NSURLRequest *request = [NSURLRequest requestWithURL:imageURL];
            NSURLSessionDataTask *task = [mealNewsUrlSession dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                if (error)
                {
                    NSLog(@"ERROR: %@", error);
                }
                else
                {
                    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
                    
                    if (httpResponse.statusCode == 200)
                    {
                        UIImage *image = [UIImage imageWithData:data];
                        [mealNewsImageCache setObject:image forKey:imagePath];
                        
                        dispatch_async(dispatch_get_main_queue(), ^{
                            [cell.mealPhoto setImage:image];
                            [cell setNeedsLayout];
                            //[cell.activityIndicator stopAnimating];
                        });
                    }
                    else
                    {
                        NSLog(@"Couldn't load image at URL: %@", imageURL);
                        NSLog(@"HTTP %ld", (long)httpResponse.statusCode);
                    }
                }
            }];

            [task resume];


dispatch를 이용한 방법)

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
        dispatch_async(queue, ^(void) {
            
            NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:profilePath]];
            UIImage* image = [[UIImage alloc] initWithData:imageData];
            if (image) {
                [mealNewsImageCache setObject:image forKey:profilePath];
                
                dispatch_async(dispatch_get_main_queue(), ^{
                    [self.profilePhoto setImage:image forState:UIControlStateNormal];
                });
            }

        });

3. 한번에 모두 다운로드 한후에 이용하는 방법)

xxx.h
NSOperationQueue *_asyncQueue;

xxx.m
// initialization
{
_asyncQueue = [[NSOperationQueue alloc] init];
or
_asyncQueue = [NSOperationQueue mainQueue]
or
_asyncQueue = [NSOperationQueue currentQueue]
}

{
// use
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        [NSURLConnection sendAsynchronousRequest:request queue:_asyncQueue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
            
            UIImage *image = [[UIImage alloc] initWithData:data];
            [Utility saveImageToFS:UIImageJPEGRepresentation(image, 1.0) withUrl:request.URL];
            
            dispatch_async(dispatch_get_main_queue(), ^{
                //update cell
            });
        }];
    }); //dispatch_async
}

+ (void) saveImageToFS:(NSData *)data withUrl:(NSURL *)url {
    NSString *dir = [[url absoluteString] stringByDeletingLastPathComponent];
    NSString *filename = [url.absoluteString lastPathComponent];
    
    //
    NSString *path = [NSString stringWithFormat:@"%@/%@",[Utility getMangaRootPath],dir];
    if(![[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil])
        NSLog(@"fail to create directory ");
    
    
    NSString *fullpath = [path stringByAppendingFormat:@"/%@",filename];
    if(![data writeToFile:fullpath atomically:YES])
        NSLog(@"fail to write file");
}

+ (NSString *)getMangaRootPath {
    NSString *path = [NSString stringWithFormat:@"%@/%@",
                      [self getCachesPath],
                      kMangaEditionDirectory];
    // create directory
    [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
    return path;
}

+ (NSString*)getCachesPath {
    NSString *documentPath = nil;
    
    NSSearchPathDirectory directory;
    directory = NSCachesDirectory;
    
    NSArray* directories = NSSearchPathForDirectoriesInDomains(directory, NSUserDomainMask, YES);
if(directories != nil && [directories count] > 0)
        documentPath = [directories objectAtIndex:0];
    return documentPath;
}

2015년 4월 5일 일요일

2015년 2월 13일 금요일

facebook 이미지들 가로 스크롤과 비슷한 기능 구현...



페이스북에서 여러 이미지들이 가로로 스크롤되면서 보여지는 UI를 구현하기 위해서는  UICollectionViewFlowLayout를 상속받아서 구현해야 한다.

구현 시나리오.
1. 우선 interface builder에서 collectionview의 paging 기능을 disable. 이때 collectionview의 frame의 가로 사이즈는 window의 가로 사이즈와 같게 설정.

2. UICollectionViewFlowLayout를 상속받아서 targetContentOffsetForProposedContentOffset 을 구현.
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)contentOffset
                                 withScrollingVelocity:(CGPoint)velocity
{
    NSArray* layoutAttributesArray = [self layoutAttributesForElementsInRect:self.collectionView.bounds];
   
    if(layoutAttributesArray.count == 0)
        return contentOffset;
   
    UICollectionViewLayoutAttributes* candidate = layoutAttributesArray.firstObject;
   
    for (UICollectionViewLayoutAttributes* layoutAttributes in layoutAttributesArray)
    {
        if (layoutAttributes.representedElementCategory != UICollectionElementCategoryCell)
            continue;
       
       
        if((velocity.x > 0.0 && layoutAttributes.center.x > candidate.center.x) ||
           (velocity.x <= 0.0 && layoutAttributes.center.x < candidate.center.x))
            candidate = layoutAttributes;
    }
   
    return CGPointMake(candidate.center.x - self.collectionView.bounds.size.width * 0.5f, contentOffset.y);

}

3. viewcontroller의 적절한 위치에서 layout을 설정
UICollectionViewFlowLayout *flowLayout = [[ArbitaryCollectionViewFlowLayout alloc] init];
[cell.collectionView setCollectionViewLayout:flowLayout animated:YES];


reference : http://stackoverflow.com/questions/15919457/uicollectionview-paging-like-safari-tabs-or-app-store-search

문장에서 검색어와 일치하는 모든 단어 볼드처리 하기

{
    UIFont *boldFont = [UIFont boldSystemFontOfSize:10];
    UILabel *sentenceLabel = [[UILabel alloc] init];
    sentenceLabel.text = @"If you still feel the need to clean your ear, anything you can easily see or touch with the pad of your finger is fair game. But if you want to snake into your ear with a narrow tool, just remember this advice from Chandrasekhar: Nothing smaller than your elbow.";
    NSString *sentence = sentenceLabel.text;
    NSString *keyword = @"your";
    [sentence enumerateSubstringsInRange:NSMakeRange(0, [sentence length])
                                   options:NSStringEnumerationByWords
                                usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
                                    if ([substring isEqualToString:keyword]){
                                        NSLog(@"%@", substring);
                                        [attributedText addAttribute:NSFontAttributeName value:boldFont range:substringRange];
                                    }
                                }];
        [sentenceLabel setAttributedText:attributedText];
    }

2014년 11월 20일 목요일

keyboard 에서 enter 키 누르면 키보드 숨기기


UITextField 의 경우

#pragma mark - UITextFieldDelegate
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if ([string isEqualToString:@"\n"]) {
        [self.view endEditing:YES];
    }
    return YES;
}



UITextView 의 경우


#pragma mark - UITextViewDelegate

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
    if ([text isEqualToString:@"\n"]) {
        [self.view endEditing:YES];
    }
    return YES;

}

2014년 11월 3일 월요일

최상위 View Controller 가져오기



+ (UIViewController*)topMostViewController {
    UIViewController *topMostViewController = nil;
    
    UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
    if ([rootViewController isKindOfClass:[UINavigationController class]]) {
        UINavigationController* navigationController = (UINavigationController*)rootViewController;
        topMostViewController = navigationController.visibleViewController;
    } else if (rootViewController.presentedViewController) {
        topMostViewController = rootViewController.presentedViewController;
    } else if ([rootViewController isKindOfClass:[UITabBarController class]]) {
        UITabBarController* tabBarController = (UITabBarController*)rootViewController;
        topMostViewController = tabBarController.selectedViewController;
    } else
        topMostViewController = rootViewController;
    
    return topMostViewController;

}