Showing posts with label iOS Programming. Show all posts
Showing posts with label iOS Programming. Show all posts

Tuesday, December 4, 2012

iOS 6's Social Network integration

First thing I want to say: Really appreciate Apple for putting efforts to embed the social sharing functions into the iOS SDK 6.0. You know what, thousands of lines of code I used to do social sharing can be totally deleted now. Wow! It can be just less than 10 lines of code now.

To bring out the Sharing Panel above, we just need to write the code:

- (IBAction) shareButtonClicked:(id)sender{
    NSString *textToShare = @"Hello World!";
    UIImage *imageToShare = [UIImage imageNamed:@"ss.jpg"];
    NSArray *activityItems = @[textToShare, imageToShare];
    UIActivityViewController *activityVC =
    [[UIActivityViewController alloc] initWithActivityItems:activityItems
                                      applicationActivities:nil];
    [self presentViewController:activityVC animated:YES completion:nil];
}

UIActivityViewController is under UIKit, so we don't need to include any framework. What we did here was to supply the activitiyVC with a string and an image, and leave all the rest to UIActivityViewController.

Sometimes, we may not provide the sharing panel to user. If we just want to present user the facebook sharing, then we can simply user the following code:

- (IBAction)facebookShare:(id)sender{
    // need include social.framework
    SLComposeViewController *facebookPostVC=[SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
    // You can have other servicetypes for Weibo, Twitter.

    [facebookPostVC setInitialText:@"Hello World!"];
    [facebookPostVC addImage:[UIImage imageNamed:@"ss.jpg"]];
    [self presentViewController:facebookPostVC animated:YES completion:nil];

}

Very similarly, very simple codes...You will get something as following directly. As I comment in the code, we can do the same way for Twitter and Weibo. To use SLComposeViewController, we need to include Social.framework

Very simple right. I love this. However, we have to realize the drawbacks. Good things don't come out without cost... Doing this way, we have no more deep link to Facebook, no need to create App on developers.facebook. So people won't see the feed comes from your App.

Sunday, November 4, 2012

UITextField with Input from UIPickerView

Sometimes, we need an UITextField whose input is picking from an array of strings. People may popup an UIPickerView from an UIActionSheet/UIPopoverController, but it is easier to use UITextField's inputView to do this. Doing this way is more intuitive and more OOP. I would like to achieve something shown below.

To do this, I created a subclass of UITextField, called PickerTextField

In the header file, we can see it is a direct subclass from UITextField. I created some varibles: 1. sourceStringsArray to hold the array of strings to select from; 2. picker to be the inputView of the TextView. 3. pickedIndex to indicated the selected index.

pickedIndex is also declared as a property, used to be an API from other class to access it. You may wondering, how can we access the text from outside? Super easy. my_sub_class.text will give you the text, just like a normal UITextField.

The method:'{setDataSource: andPlaceHolder:}' is an important method for us to set the sourceStringsArray and the textfield's placeholder property.

First two methods are initialization, they won't be called at the same time. Please refer to the comment in the code. Also note '[super setDelegate:self];', which direct the UITextField's delegate to this subclass itself.

'{setDataSource: andPlaceHolder:}' as mentioned earlier, used to assign sourceStringsArray. It has to be called before using it. Besides, we also setup the picker here, and assign the UITextField's inputView to the picker.

 if (self.pickedIndex!=-1) {
        [self setText:[sourceStringsArray objectAtIndex:self.pickedIndex]];
    }
If you want pre-select certain element for the PickerTextField, you call assign a pickedIndex before calling the method.

The remaining code is quite straight forward. UIPickerView's delegate methods. We change the pickedIndex and the text when the picker's selection changes. The following class is only to serve as the mid-object to forward UITextFieldDelegate methods to the PickerTextField. We pre-select first element, if pickerIndex is not assigned with any value and remains -1. I tried to simply use'[super setDelegate:self]' in PickerTextField, but that will lead to infinite loop, end up have to create the PickerTextFieldHandler class to forward.

You can also download the code from git.

Thursday, May 31, 2012

Map of iOS SDK Frameworks

I recently saw a map of iOS SDK Frameworks, and was surprised by the author's mindful effort to create it. This map should have come from Apple's developer site or xCode, but it never happened.

I problems when develop an App with lastest iOS SDK but support old iOS (e.g. base SDK: iOS 5.1,  Deployment Target: iOS4.0). When I create functions whose API is only available for iOS 5.0+, that will be a problem if I dont have this map in mind.  With the map in mind, I will be aware that I need to do some API checking before using. 

Class cls = NSClassFromString (@"UIDocument");
if (cls) {
    // Create an instance of the class and use it.
} else {
    // Alternate code path to follow when the
    // class is not available.
}
As an iOS developer, this map also help me to evaluate my skills by checking whether I am familiar with all the listing frameworks.



 the map is created by 德鲁伊@cocoachina.com(Ref)

Sunday, August 14, 2011

Push Notification iOS Side Programming

Push Notification (also called Remote Notification) is a powerful free function provided by Apple. App can use it to push promotions or other tailor-made messages to App users.

iOS side code is simple, most of time within 200 lines. However, the logic part is a little bit difficult if you want to write an "intelligent" handler when push message comes, taking consideration of the following three scenarios:
  1. App is not running. 
  2. App is running at the background.
  3. App is running at the forefront.
Here, I am going to share some of the iOS side code for "Register for Push Notification" and "Handling of Push Notification".

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
[[UIApplication sharedApplicationregisterForRemoteNotificationTypes: UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert];
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;

        //////////Your App launch Setups
        //////////Your App launch Setups
        //////////Your App launch Setups
        [self.window makeKeyAndVisible];
//for receiving push notification when the App is not running.
if (launchOptions!=nil) {
if ([launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]!=nil) {
NSDictionary * userInfo=[launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
//this userInfo actually contains information about the received Push notification, so write some code about it and do handling about it here. 
}
}
    return YES;

}


-(void) application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
//send the token to your server here
//send the token to your server here
//send the token to your server here
}

Please take a look at the above code.
First line is to Register for Push Notification, and second line is to clear BadgeNumber if there is any.

Let's go to next function first,
-(void) application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken.





This function is called when the App receive the "token" from Apple, so you'd write some code to send this code to your server (Better hash it first). With this token, your server will be able to send Push Notification to the user with this "token".

Move back to function (didFinishLaunchingWithOptions), near there end the few lines of code is actually handler for scenario 1: App is not running. 

Handler for scenario 2 & 3 will be handled by the following function, basically it is the place you can capture the message (userInfo) for the Push Notification. In this example, I use an AlertView to display the Push message for scenario 3, which looks intuitive. Then, any further handling with be written within the AlertViewDelegate methods.

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSLog(@"Got Notification%@",userInfo);
if ( application.applicationState == UIApplicationStateActive ){
// app was already at the forefront: Scenario 3
if ([[userInfo objectForKey:@"aps"] objectForKey:@"alert"]) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil
message:[NSString stringWithFormat:@"%@",[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]]  delegate:self
  cancelButtonTitle:@"Cancel"
  otherButtonTitles:@"View", nil];
[alertView show];
[alertView release];
}
}
else// app was just brought from background to forefront: Scenario 2
{
//Write your code here to handle your Push Notification
}
}


Hope this helps some people. It is not very in detail, but the structure is there. Thank you.







Tuesday, August 2, 2011

How to add UITextField to UIAlertView from XIB

Today, I am going to share how to add UITextFields to UIAlertView from XIB. 
UITextFields can be added through coding, but I prefer draw it in a small view from XIB because it is more convenient and visualizable. In the following example, I will add 3 UITextFields and 4 UILabels in the small view.

1. Create a view_controller and add the customized small view(named AlertXIB in the picture, while named "changePasswordView" in the code) parallel to the main view of the view_controller. Add certain number of UILabels and/or UITextfields in the small view. As shown in the picture:






























2. Add the view into the view_controller' main view on a button click.

-(IBAction)buttonClicked:(UIButton*) button {
//If I don't add this _fakeTextField, my own textfields won't be able to detect inputs from keyboard, another good thing is that the alertview will be automatically moved up a bit.
UITextField * _fakeTextField=[[UITextField alloc] initWithFrame:CGRectMake(12, 3, 200, 30)];
_fakeTextField.backgroundColor=[UIColor clearColor];
_fakeTextField.userInteractionEnabled=NO;

UIAlertView *_myAlertView = [[UIAlertView alloc] initWithTitle:nil message:@"\n\n\n\n\n" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK",nil];
changePasswordView.frame=CGRectMake(12, 3, changePasswordView.frame.size.width, changePasswordView.frame.size.height);
newPassword.text=@"";
oldPassword.text=@"";
confirmPassword.text=@"";
[_myAlertView addSubview:_fakeTextField];
[_fakeTextField release];
[_myAlertView addSubview:changePasswordView];
[_myAlertView show];
[_myAlertView release];
}

A few things to explain here:
1). The message of the UIAlertView, I use several newline characters, because the message will be determine the size of the UIAlertView.

2). A "_fakeTextField" is also added, reason is what i explained in the comment. You can play around with it. For all the UITextfields "newPassword, oldPassword, confirmPassword", you can configure their UITextFieldDelegate via XIB or code. 

3). delegate of the UIAlertView is set to self (the view_controller), so you can handle further processing when user clicks button on the UIAlertView.

#pragma mark -
#pragma mark UIAlertViewDelegate

-(void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex==0) {
NSLog(@"button at index 0, cancel and doing nothing");
} else {
//Change password code here
NSLog(@"button at index 1");
}
}



3. So when the button click method (buttonClicked:) is called, the view will look like this. The UILabel text in the UIAlertView is in black color is just for demo, while you can change it to any color or size you want.