jueves, 28 de abril de 2016

iOS: Resizing UITextView / UILabel

I implemented it with UILabel

1) First I set a max number of lines (Programatically by setting "numberOfLines" or in IB setting the "Lines" attribute)
2) Create a "READ MORE" button and set "readMoreClicked" as its action when touched up inside
3)

long numberOfLines = [self _numberOfLinesInNotes];
            
            if (numberOfLines <= <max_lines_you_want> ) {
                self. textLabel.numberOfLines = numberOfLines;
                self.readMoreButton.hidden = YES;
                
            } else {
                self.textLabel.numberOfLines = <max_lines_you_want>;
                self.readMoreButton.hidden = NO;

            }

4) 

#pragma mark - IBActions
- (IBAction)readMoreClicked:(id)sender
{
    if ([self.readMoreButton.titleLabel.text isEqualToString:@"READ MORE"]) {
        [self.readMoreButton setTitle:@"READ LESS" forState:UIControlStateNormal];
        self.noteLabel.numberOfLines = 0;
        
    } else {
        [self.readMoreButton setTitle:@"READ MORE" forState:UIControlStateNormal];
        self.noteLabel.numberOfLines = <max_lines_you_want>;
    }
}

iOS: Simple image loading method

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        NSURL *url = [NSURL URLWithString:<image_url>];
        NSData *data = [NSData dataWithContentsOfURL:url];
        UIImage *img = [[UIImage alloc] initWithData:data];
        
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.imageView setImage:img];
        });

    });

miércoles, 27 de abril de 2016

Android: Basic dependencies

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.android.support:design:23.0.0'
    compile 'com.android.support:support-v4:23.0.0'
    compile 'com.android.support:recyclerview-v7:23.1.1'
}

Android: Using Volley

Android docs

0) Download Volley
2) File > New > Import module (Volley)
1)  En el build.gradle de la app
dependencies {
    compile project(":volley")
    compile 'com.google.code.gson:gson:2.6.2'
    ...
}

4) Server class
public class Server {

    private RequestQueue mRequestQueue;
    private Context context;

    private static class Holder {
        static final Server INSTANCE = new Server();
    }

    public static Server getInstance() {
        return Holder.INSTANCE;
    }

    private Server() {

    }

    public void initialize(Context context) {
        this.context = context;

        // Instantiate the cache
        Cache cache = new DiskBasedCache(context.getCacheDir(), 1024 * 1024); // 1MB cap

        // Set up the network to use HttpURLConnection as the HTTP client.
        Network network = new BasicNetwork(new HurlStack());

        // Instantiate the RequestQueue with the cache and network.
        mRequestQueue = new RequestQueue(cache, network);

        // Start the queue
        mRequestQueue.start();
    }

    public void getHoroscope(Response.Listener responseListener, Response.ErrorListener errorListener) {

        String url = "https://volley-test.herokuapp.com/volley";

        JsonObjectRequest jsObjRequest = new JsonObjectRequest
                (Request.Method.GET, url, null, new Response.Listener() {

                    @Override
                    public void onResponse(JSONObject response) {
                        Log.d("Server", "Response: " + response.toString());
                    }
                }, new Response.ErrorListener() {

                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Log.d("Server", "Error: " + error.toString());
                    }
                });

        mRequestQueue.add(jsObjRequest);
    }
}
5) GsonRequest class
public class GsonRequest extends Request {
    private final Gson gson = new Gson();
    private final Class clazz;
    private final Map headers;
    private final Response.Listener listener;

    /**
     * Make a GET request and return a parsed object from JSON.
     *
     * @param url URL of the request to make
     * @param clazz Relevant class object, for Gson's reflection
     * @param headers Map of request headers
     */
    public GsonRequest(String url, Class clazz, Map headers,
                       Response.Listener listener, Response.ErrorListener errorListener) {
        super(Method.GET, url, errorListener);
        this.clazz = clazz;
        this.headers = headers;
        this.listener = listener;
    }

    @Override
    public Map getHeaders() throws AuthFailureError {
        return headers != null ? headers : super.getHeaders();
    }

    @Override
    protected void deliverResponse(T response) {
        listener.onResponse(response);
    }

    @Override
    protected Response parseNetworkResponse(NetworkResponse response) {
        try {
            String json = new String(
                    response.data,
                    HttpHeaderParser.parseCharset(response.headers));
            return Response.success(
                    gson.fromJson(json, clazz),
                    HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JsonSyntaxException e) {
            return Response.error(new ParseError(e));
        }
    }
}
6) Performing a GsonRequest
c

lunes, 25 de abril de 2016

iOS: UINavigationBar customization (color changes)

In IB under Attributes inspector, select your Navigation bar.

1) To change the bar color change the "Bar Tint" color under "Navigation Bar"*
2) To change the text color change "Title Color" under "Navigation Bar"

*If you want a solid color you will have to uncheck "Translucent"

iOS: Change status bar text color to white

Subclass UINavigationController and add the following code:

-(UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent;
}

Any view not push in the navigation controller needs to override that method as well.

iOS: Remove navigation bar back message


self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:self.navigationItem.backBarButtonItem.style target:nil action:nil];*

This code needs to be in the ViewController that pushed the ViewController in which you want to hide the back text.

*If using a TabBarController this code will go there, no in the contained view controller.

martes, 19 de abril de 2016

iOS: UITableView remove empty rows

Objective C

[self.tableView setTableFooterView: [[UIView alloc] initWithFrame: CGRectZero]];

Swift


tableView.tableFooterView = UIView(frame: CGRect.zero)

lunes, 18 de abril de 2016

Instagram: Safari cannot open the page because the address is invalid instagram

Go to your instagram app and click on the "Edit" button. Go to "Security" tab and see if "Disable implicit OAuth" is enabled, if it is, disable it. If it is not enable it, save, disable it and save :)

jueves, 14 de abril de 2016

iOS: UIPageViewController with input validation

1) Create a base view controller for the view controllers to be displayed in the page view controller
@interface PageContentViewController : UIViewController


@property(nonatomic, assign) NSUInteger pageIndex;
@property(nonatomic, retain) User* user;

- (BOOL)canGoToNext:(NSError**)error;

@end

@implementation PageContentViewController

...

- (BOOL)canGoToNext:(NSError**)error
{
    return YES; // Override in subclasses
}
2) Create a view controller to hold the page view controller
@interface CreateAccountViewController : UIViewController <UIPageViewControllerDataSource, UIPageViewControllerDelegate>

@property (strong, nonatomic) UIPageViewController *pageViewController;

@property (weak, nonatomic) IBOutlet UIPageControl *pageControl;

@end

@implementation CreateAccountViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.pageControl.numberOfPages = number_of_pages;

    // Create page view controller

    self.pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"PageViewController"];
    self.pageViewController.dataSource = self;
    self.pageViewController.delegate = self;

    UIViewController *startingViewController = [self viewControllerAtIndex:0];
    NSArray *viewControllers = @[startingViewController];
    [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];

    CGSize containerSize = self.pageViewControllerContainer.frame.size;
    self.pageViewController.view.frame = CGRectMake(0, 0, containerSize.width, containerSize.height);

    [self addChildViewController:_pageViewController];

    [self.pageViewControllerContainer addSubview:_pageViewController.view];
    [self.pageViewControllerContainer bringSubviewToFront:self.pageControl];

    [self.pageViewController didMoveToParentViewController:self];

}

#pragma mark - UIPageViewControllerDataSource

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
    NSUInteger index = ((PageContentViewController*) viewController).pageIndex;

    if ((index == 0) || (index == NSNotFound)) {
        return nil;
    }

    index--;

    return [self viewControllerAtIndex:index];
}

- (UIViewController*)_viewControllerAtIndex:(NSUInteger)index
{
    NSArray* viewControllers = self.pageViewController.viewControllers;

    NSError* error;

    if (viewControllers && viewControllers.count > 0 && ![viewControllers[0] canGoToNext:&error]) {

        if (error) {
            [self showErrorDialogWithMessage:[error localizedDescription]];
            return nil;
        }
    }

    return [self viewControllerAtIndex:index];
}

- (UIViewController *)viewControllerAtIndex:(NSUInteger)index
{
    if (index >= number_of_pages) {
        return nil;
    }   

    switch (index) {
        // return appropriate view controller
    }
}

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
    NSUInteger index = ((PageContentViewController*) viewController).pageIndex;   

    if (index == NSNotFound) {
        return nil;
    } 

    index++;   

    if (index == 4) {
        return nil;
    }  

    return [self viewControllerAtIndex:index];
}

#pragma mark - UIPageViewControllerDelegate

- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray<UIViewController *> *)pendingViewControllers NS_AVAILABLE_IOS(6_0)
{
    PageContentViewController* vc = (PageContentViewController*)pendingViewControllers[0];

    self.pageControl.currentPage = [vc pageIndex];
}

- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray<UIViewController *> *)previousViewControllers transitionCompleted:(BOOL)completed
{
    self.pageViewController.view.userInteractionEnabled = NO;  

    NSError* error;   

    if (![((PageContentViewController*)previousViewControllers[0]) canGoToNext:&error]) {
        [self performSelector:@selector(_goToPrevious:) withObject:error afterDelay:1];    

    } else {
        self.pageViewController.view.userInteractionEnabled = YES;
    }
}

- (void)_goToPrevious:(NSError*)error
{
    [self showErrorDialogWithMessage:[error localizedDescription]];

    [self previousPage:nil];
}

#pragma mark - IBActions

- (IBAction)nextPage:(id)sender
{
    NSInteger index = self.pageControl.currentPage;

    PageContentViewController* currentVC = (PageContentViewController*)[self viewControllerAtIndex:index];   

    NSError* error;

    if (index == 3 || ![currentVC canGoToNext:&error]) {       

        if (error) {
            [self showErrorDialogWithMessage:[error localizedDescription]];
        }       

        return;

    }
    PageContentViewController* nextVC = (PageContentViewController*)[self viewControllerAtIndex:index+1];

    self.pageControl.currentPage = index+1;  

    [self.pageViewController setViewControllers:@[nextVC] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];

}

- (IBAction)previousPage:(id)sender
{
    NSInteger index = self.pageControl.currentPage;    

    if (index == 0) {
        return;
    }   

    PageContentViewController* previousVC = (PageContentViewController*)[self viewControllerAtIndex:index-1];   

    self.pageControl.currentPage = index-1;   

    __block CreateAccountViewController *blocksafeSelf = self;    

    dispatch_async(dispatch_get_main_queue(), ^{

        [self.pageViewController setViewControllers:@[previousVC] direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:^(BOOL finished){

            blocksafeSelf.pageViewController.view.userInteractionEnabled = YES;
        }];
    });
}

@end

miércoles, 13 de abril de 2016

iOS: UITableView background color not working


If setting the UITableView background to a certain color doesn’t seem to work check that in Attributes Inspector the background color is set in the “View” section and not in the “Table View” section

lunes, 11 de abril de 2016

iOS: Date from string and string to date

String to date

- (NSDate*)_dateFromString:(NSString*)string
{
    [NSDateFormatter setDefaultFormatterBehavior:NSDateFormatterBehavior10_4];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZ"];
    
    return [formatter dateFromString:string];

}

Date to string

- (NSString*)string
{
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"MM-dd-yyyy"];
    
    //Optionally for time zone conversions
    [formatter setTimeZone:[NSTimeZone timeZoneWithName:@"..."]];
    
    return [formatter stringFromDate:self];

}

iOS: enum

typedef enum  {
    Male,
    Female

} Gender;

miércoles, 6 de abril de 2016

iOS: Dictionary from / to json

NSError * error;
NSData * jsonData = [NSJSONSerialization dataWithJSONObject:response options:0 error:&err];
NSString * myString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

NSError * error;

    NSDictionary * response = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:[myString dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&error];

iOS: Adding and using fonts

1) Add your custom font into your project , i.e. drag the font file into xCode project.
2) Edit Info.plist: Add a new entry with the key "Fonts provided by application".
3) For each of your files, add the FILE NAME including extention to this array
4) Open the font in Font Book(double click on your font in finder) to see what the real FONT NAME is.
5) yourLabel.font = [UIFont fontWithName:@"FONT NAME" size:SIZE];

lunes, 4 de abril de 2016