bgondim
bgondim
Bruno Bilescky
12 posts
iPhone and iPad programmer and designer. I have about 5 years of expertise in developing computer software. I work with mobile for almost an year now, and have done some apps in the appStore.
Don't wanna be here? Send us removal request.
bgondim · 14 years ago
Text
NSDateComponents and a better way to handle dates
Handling dates in objective-c can be quite difficult if you don't use the right tools.
And the best tools are for sure the NSDateComponents class. This class is available to both Mac and iOS development, and it makes handling dates much more simple.
Suppose that you need to get the month number of a date. If you don't know NSDateComponents, a way to do that is create a NSDateFormatter and set the format only for the month and get a string that you could convert to a number. Simple  like that. Actually this is far from simple, and far from optimal and far from good programming practices.
Using NSDateComponents things get much easier.
Just create a NSCalendar, like in this statement
NSCalendar* calendar = [NSCalendar currentCalendar];
and set which components you want to retrieve, these are the options:
NSEraCalendarUnit,
NSYearCalendarUnit,
NSMonthCalendarUnit,
NSDayCalendarUnit,
NSHourCalendarUnit,
NSMinuteCalendarUnit,
NSSecondCalendarUnit,
NSWeekCalendarUnit,
NSWeekdayCalendarUnit,
NSWeekdayOrdinalCalendarUnit,
You can specify which components you want using a statement like this one
NSUInteger flags = NSMonthCalendarUnit | NSDayCalendarUnit;
And later you just need to call
NSDateComponents* components = [calendar components:flags fromDate:someDate];
and you will have (in this case) the day and the month of the someDate variable.
To get these values just call the day and month methods from the components object, and you will get an NSInteger.
Also if you want to add some time to a date, like an hour, or a day, or 65 days,4 hours and 3 minutes, if you dont use NSDateComponents, you would end up using something like this:
[someDate addTimeInterval:60*60] //add an hour to someDate
To and an hour this is the simplest way, but and if you need to add 65 days,4 hours and 3 minutes? things would get a lot harder, wouldn't it? Using NSDateComponents this is done like a breeze :) You will need the calendar again, and then you instantiate a NSDateComponents, like this:
NSDateComponents *components = [[NSDateComponents alloc] init];
and you set the time you want to add, like in our example:
[components setDay:65]; [components setHour:4]; [components setMinutes:3];
and you call:
NSDate *futureDate = [calendar dateByAddingComponents:components toDate:[NSDate date] options:0];
You can also find the distance between two dates using the NSDateComponents. It is as simple as the other functions: You set the components you want to track, like this code:
NSUInteger flags = NSMonthCalendarUnit | NSDayCalendarUnit; NSDateComponents *components = [calendar components:flags fromDate:startDate toDate:endDate options:0]; NSInteger months = [components month]; NSInteger days = [components day];
You see, the NSDateComponents can make you life dealing with dates a lot simpler :)
0 notes
bgondim · 15 years ago
Text
Great Logging functions
I found this info in stackoverflow.com. The tip comes from Diederik Hoogenboom.
To better handle logging in your application you might want to use these macros:
#ifdef DEBUG
#   define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#   define DLog(...)
#endif
// ALog always displays output regardless of the DEBUG setting
#define ALog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
I put these macros in a LOG.h file and add it to the .pch file located in the Other Sources folder in xCode, with an
#import "LOG.h"
To enable the DLog function just add the -DDEBUG flag in the "Other C Flags" option in your project's configuration.
Just to remember you, the ALog will always print what you pass to it.
An example of a line from Dlog(@"Hello world"):
-[YourController yourMethod] [Line 100] Hello world
3 notes · View notes
bgondim · 15 years ago
Text
Using the camera in an iphone application
It's pretty simple to use the camera (front, rear and camera albums) in an iphone application. 
To get started just create an instance of UIImagePickerController with:
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
After you need to decide the source of the image you want to capture. There are these possible values:
UIImagePickerControllerSourceTypeCamera - this will get the image from the camera.
UIImagePickerControllerSourceTypePhotoLibrary - this will open the album list of the photos app.
UIImagePickerControllerSourceTypeSavedPhotosAlbum - this will open the camera roll
you can specify which one you want with: 
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
You can also specify if you want the user to be able to edit the image (with cropping) with the property:
picker.allowsImageEditing = YES;
After you need to set a delegate to the controller. This delegate must implement the UIImagePickerControllerDelegate protocol at least this method:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
this method will receive a dictionary containing some info about the chosen picture. The original image selected (without editing) will be under the key "UIImagePickerControllerOriginalImage", the edited image (if you allowed the user to edit) will be under the key "UIImagePickerControllerEditedImage". These properties are both instances of UIImage. You can even get the selected frame if the user edited the picture, with the property "UIImagePickerControllerCropRect". This will be an instance of CGRect.
Finally to present the view controller, just invoke in your view controller:
[self presentModalViewController:picker animated:YES];
One last thing that is worth mentioning is that you can verify if your device has a camera before allowing him to use it.
To test if the user has a camera device just use this method (that returns a boolean):
[UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear]
You can also query the user about the front camera with the parameter: UIImagePickerControllerCameraDeviceFront.
Knowing that a user does not even has a camera, may help you prevent a broken experience to the user.
Well, that's all folks, at least for now.
Hope you enjoyed this tutorial.
0 notes
bgondim · 15 years ago
Text
How to access (and edit) the controls of a UISearchBar
There are no accessors to the buttons and subviews of the UISearchBar public available by default, but we can access them thought the subviews method of the searchBar.
But why this is cool? Imagine you design a view and want a search bar on it. In order to go back from the search, or you need navigation bar with a back button, or you will need to create a back button for yourself in some place. But wait, the search bar can show a "cancel" button, can't it? So you foward to use the cancel button and you realize that it comes disable until the user write something in the textfield. And we don't want our users to need to type a letter in order to leave the search page. So with this trick, it's pretty simple to enable the cancel button, even when the user typed nothing.
Put this code in the viewDidLoad method, or any place you prefer.
for (UIView *possibleButton in searchBar.subviews) {
if ([possibleButton isKindOfClass:[UIButton class]]){
UIButton *cancelButton = (UIButton*)possibleButton;
cancelButton.enabled = YES;
break;
}
}
Now you are done. Your cancel button will be available to the user even if he didn't type any character.
Then yon can implement this method:
- (void)searchBarCancelButtonClicked:(UISearchBar *) searchBar {
[self dismissModalViewControllerAnimated:YES];
}
and dismiss the view controller or anything you want. You can even change the text of the button with the method setTitle:ForState: of the button.
[cancelButton setTitle:@"Back" forState:UIControlStateNormal];
1 note · View note
bgondim · 15 years ago
Video
youtube
This is the second prototype app, for the comic creator app.
I didn't updated the reader app so that's why it's not featured in this video. But you can tak a look in the previous videos :)
Also, i post some of the things I learned while creating this app.
0 notes
bgondim · 15 years ago
Video
youtube
full comics reader iPad suite prototype
It is avaliable now on youtube the video with the Mac application to create the comicbook.
As you can see this is still a prototype, and many things will change.
But even in this stage of prototyping the process to create comic books will be pretty simple, easy and fast.
I can imagine producing a full 22 pages comic in about 2~3 hours.
Stay tunned for updates in this application!
0 notes
bgondim · 15 years ago
Video
youtube
I’m developing a new comics reader, much alike the one from comixology (marvel and DC). Now I already have almost the same effect from the comixology reader, but I’m planning to add some extra features.
The first other feature is a much more adaptable and interactive magazine store. Custom backgrounds, user defined backgrounds, also background music and music control, video and news subscriptions. For now it is already working the custom background.
Also to create the comics there is already a prototype app that make it so much easy, fast and simple to create te comic.
Hope you enjoyed this video. I will upload the magazine creator video soon.
0 notes
bgondim · 15 years ago
Text
iOS - When we need multiple display types for our tables.
Most of the time we see in tutorials, code examples and even apple starter project our view controller being the delegate and the datasource of some tableview. Although I'm not saying this approach is wrong, it is not the best for every situation, and even in the worst cases we most of the time use this approach. As an example, if our viewcontroller has two tableviews, generally we see a lot of if code to control the logic for each tableview. Even, when we got only one tableview, but this table can be ordered, sorted, searched, and displayed in different formats, our code gets full of if codes. This can lead to a huge amount of bugs, work-arounds and finally to an confused and impossible code to maintain.
In those cases we can always use our good OOP (object orientation programming) knowledge.
Objective-C has a very good design pattern called "Delegate". In this pattern you delegate some functions to another class to execute. In IOS development we use delegates all the time. But the delegate of a tableview does not necessary need to be the viewcontroller container of the tableview. We can create other NSObject classes to be the delegate for a tableview.
"But what kind of benefits do i get doing that?" you must be thinking. Well, using this pattern you can create a different delegate for each state of your table.
In in the state1 your tableview does not have sections and your cells should only display text, you create a delegate for that.
And if in the state2 your tableview should have sections, and each row should display also a detail for each row, you don't need to create a lot of ifs. Just create another delegate, assign it as the new delegate for you tableview, and call the reloadData message of your tableview. Ad you are done.
Continue reading for an example
Here goes an example of two datasources delegators:
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section {
return 10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString* CELLIDENTIFIER = @"CellIdentifier";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:CELLIDENTIFIER];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CELLIDENTIFIER];
}
cell.textLabel.text = [NSString stringWithFormat:@"Line: %d",indexPath.row];
return cell;
}
and the other datasource delegator:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 3;
}
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section {
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString* CELLIDENTIFIER = @"DataSource2";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:CELLIDENTIFIER];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CELLIDENTIFIER];
}
cell.textLabel.text = [NSString stringWithFormat:@"Line: %d",indexPath.row];
cell.detailTextLabel.text = [NSString stringWithFormat:@"Section: %d",indexPath.section];
return cell;
}
Now I can change the behavior of my tableview, even if it had about 20 possible states. No messy code, and all display logic isolated.
You could also create a parent delegate and subclass this parent if you need.
Important: note that each cellForRowAtIndex method has it's own cellIdentifier. If you set the same cellIdentifier, you will get the same UITableViewCell.
Here you can download a sample project that illustrate this very well.
0 notes
bgondim · 15 years ago
Text
iOS - Adding a stretchable UIImage as background
Often i need to use some image as a background for many visual components, like views, scrollviews, buttons, other images... and most of time i ended using a large enough image to cover the front image.
So, if my view was 1000x700 i needed to load an 1000x700 image for the background. But this image will eat a lot of memory just to be there as a background. There should be a better way to do this. And there is a better way to do this.
All you have to do is create your UIImage like this
UIImage* backgroundImage = [[UIImage imageNamed:@"stretchableImage.png"] stretchableImageWithLeftCapWidth:44 topCapHeight:45];
this stretchableImageWithLeftCapWidth specify how many pixel in the left must be kept. The same goes to the topCapHeight, and in this case it specifies the number of pixels in the top.
So in the example, the sdk will keep the first 44 pixels, copy the 45th along all the way of the image, and in the end keep again the last 44 pixels. It will do the same for the height.
So you wont need to keep a large image in memory. And you can also use this technique to create dynamic buttons, views and anything that you may even not know how length it is.
Here you can find an image as example (but keep in mind that as a designer, i'm a good programmer ^_^" )
0 notes
bgondim · 15 years ago
Text
iOS - Accessing web services easily, now with blocks!!
The iPhone SDK 4 brought to us some very neat features. One of the most awesome and powerful are blocks.  
Blocks are like small procedures, that you can use as parameters to methods.
These structures exists already in many scripting languages, as ruby and python, and now we can also use its powers in ours iphone applications.
When we need to communicate with web services, we know how painful this task may be. Asynchronous operations, delegates, parsing json and xml responses. There are a lot of libraries that handle these tasks. I've commented already about a JSON parsing library here. But this library just parses JSON. It does not handle accessing the webservice, or error responses.
For that, i've found a great project hosted on github, called Seriously, that handles all of the tasks, and it uses blocks to simplify our code.
Here is an example:
NSString *url = @"http://api.twitter.com/1/users/show.json?screen_name=probablycorey;"
    [Seriously get:url handler:^(id body, NSHTTPURLResposne *response, NSError *error) {
        if (error) {
            NSLog(@"Error: %@", error);
        }
        else {
            NSLog(@"Look, JSON is parsed into a dictionary!");
            NSLog(@"%@", [body objectForKey:@"profile_background_image_url"]);
        }
    }];
It's kind of simple code. In the handler we pass our block (denominated by the ^), and the block takes three parameters:
the body, which is the response parsed, 
the response itself, in case we need to verificate something,
an error reference, in case something went wrong.
Inside the block we just do the stuff we need with the data, always remembering that updates to the view should be done in the main thread. So if you combine this library with the InternetViewController, your life will get a lot more easy and simple, and you will get more time to concentrate on what is more important: using the data you got from the service.
UPDATED: this library just works with iOS 4, because the Blocks API was just released in this sdk. So for iPad development this library is still not useful. 
0 notes
bgondim · 15 years ago
Text
iOS - Parsing JSON
Very often we need to access some kind of service available on the internet to gather some data to work with. Most of nowadays services prefer to send data using the JSON format (learn more about json here). It's simple and compared to XML, smaller.
In iOS there is no native way to work with json text, but there are some great library avaliable out there that make the job really easy. One of the best I know is the TouchJSON (a wiki about it is avaliable here). This library makes really simple the task to parse a JSON string.
Continue reading to learn how to use this library.
To install this framework, in your xCode, do the following:
open the "Other Sources" group, and then open the yourappname_Prefix.pch 
Add just below the "#import <UIKit/UIKit.h>" the - #import "JSON.h" - line. 
This will make the JSON parser available to all of your classes. 
This is all you need to install the framework, now to parse a json string just call the method JSONValue on the string you want to translate. Then you will get a NSDictionary or a NSArray object, depending on how your JSON is structured. 
You can download the last source for TouchJSON here (read the note below), or a version packed by me (I use this one in my projects) here
Note: in the git repository of Touch i haven't found the source for the TouchJSON framework. So for now, i suggest you download the package i created.
0 notes
bgondim · 15 years ago
Text
iOS - How to load your data correctly in the background
Almost all view controllers need to load some data from the internet and interact with them.
This kind of task may sound simple at first, but as you will find out, there are some kind of complications, like autoreleasing objects with no autorelease pool in place, how to get notified when your data has been loaded and how to handle this data. Also all the updates to the view should be done in the main thread, not the background thread, to avoid possibly app crash.
To solve all these problems I’ve created a subclass of UiViewController that controls all the steps required to load the data the right way, and updates the view the right way.
All you need to do is just add the QuartzCore framework to your project, import the files in the zip (you can download it here) into your project. In the viewcontroller that you need to load the remote data, you will need to import the InternetViewController and change the parent class of the class from UiViewController to InternetViewController. After that in the implementation file, you will need to implement basically two methods:
-(void) loadContentFromInternet
Here you put the logic that will load the remote data that you need. You may also treat this data in this method if you want.
-(void) didLoadContentFromInternet
In the second method you will put the code that updates the view with your data, as all updates to the view should be done in the main thread.
There are also other methods you may implement, such as:
-(void)willLoadContentFromInternet
In this method you can update your view before start to load the content.
-(UiView)newLoadingView
This method creates a small view in the right corner of the view while the data is loading, but you can re-implement this method to change the look of this view to whatever you want.
This class wil call all the methods in the right thread, and also will ensure there is an AutoRelease pool avaliable, so your variables wont leak that easy.
You can download the code here
0 notes