Friday, October 23, 2015

Socialize through iOS Apps


Hi all,

Almost every app these days wants to socialize through Twitter, Facebook etc. and share there experience or contents of the apps.

With every changing iOS the process of Integration keeps on changing.
From Basic Authentication to Graph API to SLComposeViewController

Since iOS 8.0 we are using SLComposeViewController as Twitter and Facebook accounts are by default added with OS & you just need to setup the account.

So let's start...

1) Start by creating a single view based sample app


2) Name project as



3) Project navigator will look like this after adding Social .framework



4) Add following components in your storyboard file. 
A text field that takes input from user and buttons to share via Facebook and Twitter 




5) Now lets dig in some code by importing the social framework


6) Add text field and connect IBOutlet



7) Sending tweet on button click



How it works : 
 a) First of all we check the availability of twitter account on the device/simulator
 b) Create object of SLComposeViewController for service type Twitter
 c) Text to be shared : setInitialText method
 d) URL to be shared : addURL
 e) Image to be shared : addImage
 f) After setting required values we present the view controller


8) Sharing on facebook on button click




How it works :
 a) First of all we check the availability of facebook account on the device/simulator
 b) Create object of SLComposeViewController for service type Facebook
 c) Text to be shared : setInitialText method
 d) Image to be shared : addImage
 e) After setting required values we present the view controller

Now try this and see the result 
:)


Thursday, September 24, 2015

Jenkins on Mac...


Hi Guys,

Now a days Continuous Integration [CI] has become an eternal part of software development.
This allows user to :
a) Integrate and share their code in a repository
b) Make error checks in builds
c) Automatic generation of builds [includes packaging and signing]
d) Generating artifacts

To enjoy the prospects of CI we are going to use a tool named JENKINS.
Jenkins is a server based system which provide CI services

SCM tools with which Jenkins can be integrated with are:
Git, Mercurial, SVN, CVS etc..


Lets first start with configuring Jenkins on MAC machine.
You can use OSX installer with nice GUI or go ahead with Homebrew

I will prefer to go ahead with Homebrew so here we go

1) Open Terminal and go ahead with below mentioned commands

********** HOMEBREW SETUP **********



swati:~ admin$ 
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/universal-darwin14/rbconfig.rb:213: warning: Insecure world writable dir /usr in PATH, mode 040777

==> This script will install:
/usr/local/bin/brew
/usr/local/Library/...
/usr/local/share/man/man1/brew.1

Press RETURN to continue or any other key to abort
==> /usr/bin/sudo /bin/mkdir /Library/Caches/Homebrew

WARNING: Improper use of the sudo command could lead to data loss
or the deletion of important system files. Please double-check your
typing when using sudo. Type "man sudo" for more information.

To proceed, enter your password, or type Ctrl-C to abort.

Password:
==> /usr/bin/sudo /bin/chmod g+rwx /Library/Caches/Homebrew

==> Downloading and installing Homebrew...
remote: Counting objects: 3744, done.
remote: Compressing objects: 100% (3579/3579), done.
remote: Total 3744 (delta 40), reused 567 (delta 28), pack-reused 0
Receiving objects: 100% (3744/3744), 3.14 MiB | 240.00 KiB/s, done.
Resolving deltas: 100% (40/40), done.
From https://github.com/Homebrew/homebrew
 * [new branch]      master     -> origin/master
HEAD is now at 98c28ae gst-plugins-bad: can optionally use srtp

==> Installation successful!

==> Next steps
Run `brew help` to get started

********** JENKINS DOWNLOAD **********


swati:~ admin$ brew install jenkins

After installing Jenkins Homebrew provides you some useful tips as well

==> Downloading https://homebrew.bintray.com/bottles/jenkins-1.629.yosemite.bottle.tar.gz
######################################################################## 100.0%

==> Pouring jenkins-1.629.yosemite.bottle.tar.gz
==> Caveats
Note: When using launchctl the port will be 8080.

To have launchd start jenkins at login:
  ln -sfv /usr/local/opt/jenkins/*.plist ~/Library/LaunchAgents

Then to load jenkins now:
  launchctl load ~/Library/LaunchAgents/homebrew.mxcl.jenkins.plist

Or, if you don't want/need launchctl, you can just run:
  jenkins

==> Summary
🍺  /usr/local/Cellar/jenkins/1.629: 6 files, 61M

********** UPDATE JAVA **********


swati:~ admin$ jenkins @ dev > sudo touch /Library/LaunchDaemons/org.jenkins-ci.plist

Jenkins requires Java7 or later, but you are running 1.6.0_65-b14-466.1-11M4716 from /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
java.lang.UnsupportedClassVersionError: 50.0
at Main.main(Main.java:90)

Remember to update your Java to latest to enjoy best features

********** LAUNCH DAEMONS **********


swati:~ admin$ sudo launchctl load -w /Library/LaunchDaemons/org.jenkins-ci.plist
Password:
/Library/LaunchDaemons/org.jenkins-ci.plist: Path had bad ownership/permissions

swati:~ admin$ sudo chmod 600 /Library/LaunchDaemons/org.jenkins-ci.plist
swati:~ admin$ sudo chown root /Library/LaunchDaemons/org.jenkins-ci.plist
swati:~ admin$ sudo launchctl load /Library/LaunchDaemons/org.jenkins-ci.plist

********** org.jenkins.plist **********


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>Label</key>
        <string>Jenkins</string>
        <key>ProgramArguments</key>
        <array>
            <string>/usr/bin/java</string>
            <string>-jar</string>
            <string>/usr/local/Cellar/jenkins/1.414/lib/jenkins.war</string>
        </array>
        <key>OnDemand</key>
        <false/>
        <key>RunAtLoad</key>
        <true/>
        <key>UserName</key>
        <string>jenkins</string>
    </dict>
</plist>

If user has a different name remember to add that in plist else it will run via System root


After all this you can reboot your MAC or type below mentioned command in browser
http://localhost:8080

yippieeee.... see how it looks



Now you are ready to go ahead...
Create your jobs , download plugins, integrate SCM, automate builds & Enjoy..

Hope you enjoyed the first step.
Next step will be posted soon
:)













Thursday, September 17, 2015

Pull To Refresh Tutorial


Hi all,

I have heard and seen this feature many a times while browsing through apps.
Liked it very much.

So i decided why not to try out this feature and share my experience with you all.
Hope somebody finds help with this.

Lets start....


1) Create a Project "Single View Application"



2) Set a product name : PullToRefresh


3)  Open the storyboard file and add UITableView to the provided view

Connect TableView Outlets, Delegates and Datasources


4) Under UITableView add UITableViewCell. 

This is a Static cell with Identifier as "CellIdentifier" and with only "Title" property.


5) Now comes the Controller part

5.1) Open ViewController.h and add properties for


@interface ViewController : UIViewController<UITableViewDelegate, UITableViewDataSource>
{
    
}

@property(nonatomic, strong)IBOutlet UITableView   *dataTable;
@property(nonatomic, strong)NSArray                        *fruitsArray;
@property(nonatomic, strong)UIRefreshControl          *refreshControl;

@end


5.2) Open ViewController.m and make dough from ingredients :P


- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.fruitsArray = [[NSArray alloc] initWithObjects:
                                 @"Apple", @"Orange", @"Mango" , @"Grapes", @"Banana", nil];
    
    self.refreshControl = [[UIRefreshControl alloc] init];

    [self.refreshControl addTarget:self
                                           action:@selector(refreshControlValueChanged) 
                         forControlEvents:UIControlEventValueChanged];

    self.refreshControl.tintColor = [UIColor redColor];

    [self.dataTable addSubview:self.refreshControl];
}



- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;

}



- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.fruitsArray.count;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell;
    
    cell = [tableView dequeueReusableCellWithIdentifier:@"CellIdentifier" 
                                                                   forIndexPath:indexPath];
    
    cell.textLabel.text          = self.fruitsArray[indexPath.row];
    cell.textLabel.textColor = [UIColor blueColor];

    return cell;

}



- (void)refreshControlValueChanged
{
    self.fruitsArray = [self.fruitsArray sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
    
    [self performSelector:@selector(updateTable)
                     withObject:nil
                      afterDelay:1];
}



- (void)updateTable
{
    [self.dataTable reloadData];
    
    [self.refreshControl endRefreshing];
}


6) Now run your App and see a list of fruits that are not sorted.



7) Drag your table & see the spinning wheel


8) Now see the refreshed data...



Happy Coding....
Enjoy :)




Thursday, May 8, 2014

Ant on Mac



Hey,

For the first time i tried working with Ant on Mac, so thought of sharing some stuff..

1) Firstly ant is available by default with Mac.
2) Now lets know the current version

admin$ ant -version
Apache Ant(TM) version 1.8.1 compiled on April 29 2014

3) Wanna update to latest

Download link : http://ant.apache.org/bindownload.cgi

4) Create a local directory in usr if not exists

admin$ sudo mkdir -p /usr/local

5) Copy the downloaded folder to the newly created usr/local folder

admin$ sudo cp -rf apache-ant-1.9.4 /usr/local/apache-ant

6) Set global variable PATH

admin$ export PATH=/usr/local/apache-ant/bin:"$PATH"

7) Echo global variable PATH

admin$ echo 'export PATH=/usr/local/apache-ant/bin:"$PATH"' >> ~/.profile

8) Now lets know the updated version

admin$ ant -version

Apache Ant(TM) version 1.9.4 compiled on April 29 2014


Enjoy :)

NSPredicates : A handy tool


Hi all,

Searching and sorting is an utmost important part of any iOS app, i believe so...

Lets try to use a simpler way provided by Apple named NSPredicates that make development easier..
:) :)

We have numerous situations where NSPredicates play an important role, very few are here..

Ohhh...list may increase
:)

1) Filter an array of objects

Basic
  •     I have an array : arrCustomObjects 
  •     It contains objects of type : CustomObject
  •     Properties of CustomObject : iDname
  •     Data :
    • [@"32"   , @"Maria"] 
    • [@"51"   , @"John"] 
    • [@"100" , @"Stuart"] 
    • [@"500" , @"Barbie"]

What to do
  •  Search object from arrCustomObjects where id = @"32" 

How To do
  
 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"iD == %@", @"32"];
 NSMutableArray *filtered = (NSMutableArray*)[arrCustomObjects 
                                       filteredArrayUsingPredicate:predicate];

  if(filtered.count>0)
     CustomObject *customObject  = [filtered objectAtIndex:0];


====================================================================


2) Filter in form of Sets

    What to do
    • Filter array that contains only my favorite female friends

    How To do

     NSArray *girlsArray = [NSArray arrayWithObjects:@"Barbie",@"Maria"];
     NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name IN %@", girlsArray];
     NSMutableArray *filtered = (NSMutableArray*)[arrCustomObjects 
                                           filteredArrayUsingPredicate:predicate];

      if(filtered.count>0)
        CustomObject *customObject  = [filtered objectAtIndex:0];


    ====================================================================


    3) Filter using Regular Expressions

    What To do
    • Email ID validation using regex

    How To do

     NSString *emailRegex =
        @"^(?i)(?:(?:https?|ftp):\\/\\/)?(?:\\S+(?::\\S*)?@)?(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:\\/[^\\s]*)?$";

        NSPredicate *regextest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",  emailRegex];
        
        if ([regextest evaluateWithObject: url] == YES
            NSLog(@"URL is valid!");
        else 
            NSLog(@"URL is not valid!");



    Enjoy the ease :) :)
        

        

    Sunday, March 2, 2014

    REST API and JSON


    Hi all,

    Almost every mobile app uses REST API where user needs to handle web requests.
    The request could be GET or POST
    The data to be carried could be JSON or XML or nay other.

    So today we will be working on GET and POST requests using JSON.

    Hope you find it useful and easy too. 
    :)

    Lets begin...

    ***********************How things work******************************

    LoginViewController 
    •  Implements the Webservice Protocol.
    •  Calls method of webserviceManager to execute login webrequest
    •  Handles response

    WebServiceManager
    • Creates JSON request dict / object.
    • Makes GET / POST request.
    • Creates NSURL Connections.
    • Receives the Response.
    • Using delegate makes a callback to the calling class that implemented the protocol method.
    ***************************************************************************

    1) Create WebServiceManager.h
    •     @property (weak, nonatomic) id                               delegate;
    •     @property (strong, nonatomic) NSMutableData       *responseData;
    •     @property (strong, nonatomic) NSURLConnection *remoteConnection;
    •     @property (nonatomic) NSInteger                             statusCode;
    •    @property (strong, nonatomic) NSMutableData        *connectionData;
    •    @property (nonatomic) WebServiceTransactionType   transactionType;
    •    Create ENUMS
    2) Create protocol in WebServiceManager.h.
        This protocol will be implemented by the class that implements it
         typedef NS_ENUM (NSInteger, WebServiceTransactionType)
        {
            WebServiceTransactionTypeUserLogin,
            WebServiceTransactionTypeUserLogout,
        };

        typedef NS_ENUM (NSInteger, NetworkOperationStatusCode)
       {
            NetworkOperationStatusCodeUnkown,
            NetworkOperationStatusCodeInProgress,
            NetworkOperationStatusCodeSuccess,
           NetworkOperationStatusCodeError
       };

         #pragma mark - Delegate Protocol

        @protocol WebServiceTransactionResponseDelegate <NSObject>

        @required

         - (void)assitant : (WebServicesManager *)assistant
               transaction : (WebServiceTransactionType)type
                       status : (NetworkOperationStatusCode)statusCode
             remoteData : (id)remoteData;

    @end

    3) WebServiceManager.m 

    a) Execute login with POST request  & credentials in JSON format.
        Call this method from any class

    - (void)authenticateLoginforUserName : (NSString*)userName
                                                  password : (NSString*)password
                                         transactiontype : (WebServiceTransactionType)transaction_type
                                                   delegate : (id)del
    {
        self.delegate = del;  
        
        NSDictionary *requestDict = [[NSDictionary allocinitWithObjectsAndKeys:
                                     userName  ,@"userName",
                                     password   ,@"password",
                                     nil];
        
        NSString *url = [NSString stringWithFormat:@"%@%@",BASE_URL,LOGIN_REQUEST];

        [self createURLRequest : url 
                            requestDict : requestDict 
                     transactionType : transaction_type 
                                 delegate : del];
    }

    b) Creating a generic method that handles GET / POST request

    - (void)createURLRequest : (NSString*)url
                            requestDict : (NSDictionary*)requestDict
                    transactionType : (WebServiceTransactionType)transaction_type
                                delegate : (id)del
    {
        if (self.remoteConnection)
            [self.remoteConnection cancel];
        
        self.delegate = del;
        self.transactionType = transaction_type;
        
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:
                                                                                            [NSURL URLWithString : url]];

        [request setValue @"application/json" forHTTPHeaderField @"Content-Type"];
        
        if(requestDict != nil)
        {
            [request setHTTPMethod:@"POST"];

            NSData *jsonData = [NSJSONSerialization dataWithJSONObject : requestDict 
                                                                                                              options 0 
                                                                                                                  error nil];
            [request setHTTPBody : jsonData];
        }
        else
            [request setHTTPMethod @"GET"];
        

        [request setTimeoutInterval 10];
        
        self.remoteConnection = [NSURLConnection connectionWithRequest : request
                                                                                                          delegate self];
        self.statusCode = -1;
        [self.remoteConnection start];
    }


    c) NSURLConnection Delegate methods


    - (void)connection : (NSURLConnection *)connection 
                                            didFailWithError : (NSError *)error
    {
            if([self.delegate respondsToSelector:@selector(assitant : transaction : status : remoteData : )])
            {
                [self.delegate assitant self
                                transaction self.transactionType
                                        status NetworkOperationStatusCodeError
                              remoteData nil];
            }
          
        if (connection == self.remoteConnection)
            self.remoteConnection = nil;
    }


    - (void)connection : (NSURLConnection *)connection 
                                        didReceiveResponse : (NSURLResponse *)response
    {
        self.statusCode = [(NSHTTPURLResponse*) response statusCode];
        
        if (self.statusCode > 200) return;
        
        self.connectionData = nil;
    }

    - (void)connection : (NSURLConnection *)connection 
                                         didReceiveData : (NSData *)data
    {
        if (self.statusCode > 200 || data == nil) return;
        
        if (self.connectionData ==  nil)
            self.connectionData = [NSMutableData dataWithData:data];
        else
            [self.connectionData appendData : data];
    }


    - (void)connectionDidFinishLoading : (NSURLConnection *)connection
    {
        id temp;

        if (self.statusCode > 200)
        {
            temp = nil;
            
            if([self.delegate respondsToSelector @selector(assitant : transaction : status : remoteData : )])
            {
                [self.delegate assitant self
                                transaction self.transactionType
                                        status NetworkOperationStatusCodeError
                              remoteData nil];
            }
        }
        else
        {
            if (connection == self.remoteConnection)
                self.remoteConnection = nil;
            
            if(self.statusCode == 200)
            {
                if([self.delegate respondsToSelector:@selector(assitant : transaction : status : remoteData :)])
                {
                   NSDictionary *parsedData = [Utils convertJSONDataToDictionary self.connectionData];
                    
                  // Check JSON Parsing in another blog of mine :  JSON Parsing Tutorial

                    [self.delegate assitant self
                                    transaction self.transactionType
                                            status NetworkOperationStatusCodeSuccess
                                  remoteData : parsedData];
                }
            }
        }
    }

    4) Implementing the protocol in LoginViewController.h

     @interface LoginViewController : UIViewController              
                                                             <WebServiceTransactionResponseDelegate>

        @end

    5) Calling WebServiceManager from LoginViewController.m

        WebServicesManager *webManager = [[WebServicesManager alloc] init];

        [webManager authenticateLoginforUserName : @"Swati"
                                                                  password : @"password"
                                                         transactiontype WebServiceTransactionTypeUserLogin
                                                                    delegate self];

    6) Handling response in LoginViewController.m

    -  (void) assitant : (WebServicesManager *)assistant
            transaction : (WebServiceTransactionType)type
                    status : (NetworkOperationStatusCode)statusCode
          remoteData : (id)remoteData
    {
        switch (type)
        {
            case WebServiceTransactionTypeUserLogin:
            {            
                if(statusCode == NetworkOperationStatusCodeError)
                {
                    // FAILURE                
                    return;
                }
              else
              {
                      // SUCCESS
               }
            }
                break;
            default:
                break;
        }
    }

    tada........

    now try out yourself.....