iOS Showcase
FREE DOWNLOAD
Click image for more screenshots.Introduction
With this showcase demo, we wanted to demonstrate the power of both TMS iCL and TMS FMX Cloud Pack products for creating iOS applications. We refer to the power in terms of achieving a 100% true native iOS look and feel, using RAD methodology for developing the application, almost codeless access to a wide range of cloud services, access the iOS device hardware and finally getting the most performance out of the application. In this demo, we show how to use the native tab bar, toolbar, tableview, imagepicker and more. We show how to get access to files in the root and documents folder of the iOS application and how to consume multiple cloud services such as Facebook, Twitter, Google Drive, Instagram and best of all, with only a few lines of code.
Loading images / thumbnails
When deploying the demo, a set of images will be loaded from the root directory and for each image a thumbnail is shown in the list. When clicking on the item in the list, the corresponding full size image is displayed and ready to be uploaded to the authenticated services. Additionally, an image can be taken with the camera after clicking the camera icon button in the toolbar. The images are added to a TMSFMXNativeUITableView. The TMSFMXNativeUITableView has a section and section items collection. These are collections that can be used at designtime and runtime and expose Delphi properties such as a Text, Description, BitmapFile and BitmapSize property. The BitmapFile and BitmapSize properties are used to generate a thumbnail from the image that is added to the list. The TMSFMXNativeUITableView automatically takes care of this. The code below demonstrates how to load files from the root and documents directory and how to add them to the TMSFMXNativeUITableView component.
//Returns the Documents directory the iOS application
function GetDocumentsDirectory: String;
var
paths: NSArray;
begin
Result := '';
paths := TNSArray.Wrap(NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, True));
if paths.count > 0 then
Result := UTF8ToString(TNSString.Wrap(paths.objectAtIndex(0)).UTF8String);
end;
//Returns the Root directory the iOS application function GetRootDirectory: String; begin Result := ExtractFilePath(Paramstr(0)); end;
//Initializes the list of images from the Root and Documents directory
procedure TForm1.InitImageList;
var
doc: String;
app: String;
begin
TMSFMXNativeUITableView1.BeginUpdate;
doc := GetDocumentsDirectory;
AddImagesFromFolder(doc, ['.JPG','.JPEG','.PNG']);
app := GetRootDirectory;
AddImagesFromFolder(app, ['.JPG']);
TMSFMXNativeUITableView1.Sections[0].Items.Sort(True, smDescending);
TMSFMXNativeUITableView1.EndUpdate;
SelectItem(0);
end;
//Adds images from a specified folder based on an array of file extensions.
procedure TForm1.AddImagesFromFolder(AFolder: String; AFileExtensions: array of string);
var
arr: NSArray;
I: Integer;
fn, ext: String;
it: TTMSFMXNativeUITableViewItem;
begin
arr := TNSFileManager.Wrap(TNSFileManager.OCClass.defaultManager).contentsOfDirectoryAtPath(NSStr(AFolder), nil);
for I := 0 to arr.count - 1 do
begin
fn := AFolder + '/' + UTF8ToString(TNSString.Wrap(arr.objectAtIndex(i)).UTF8String);
ext := ExtractFileExt(fn);
if MatchStr(ext.ToUpper, AFileExtensions) then
begin
it := TMSFMXNativeUITableView1.Sections[0].Items.Add;
it.BitmapFile := fn;
it.BitmapSize := 32;
it.Text := ExtractFileName(it.BitmapFile);
end;
end;
end;
Authentication with multiple services
In order to access the different cloud services, it is needed to signup with these services first and register the application. Via this registration procedure, you obtain your unique application key and secret that is used to initialize the various TMS Cloud Pack components.In case the cloud service component could get access to the cloud service (i.e. by means of getting an access token) the token is persisted in a file so it can be reused without going through a new authentication/authorization phase. In the demo app, an INI file in the documents folder is used for persisting. The previously obtained tokens are loaded with the call TCloudService.LoadTokens. The next step is to test the validity of the token and this is done with the call TCloudService.TestTokens. A visual indicator on the screen indicates this validity of the token. When the token is not valid, following code is used to start a new authentication/authorization:
Click image for more screenshots.//Initialize the application key and secret for each service procedure TForm1.InitAppKeys; begin TMSFMXCloudFaceBook1.App.Key := FacebookAppkey; TMSFMXCloudFaceBook1.App.Secret := FacebookAppSecret; TMSFMXCloudFaceBook1.PersistTokens.Key := GetDocumentsDirectory + '/facebook.ini'; TMSFMXCloudFaceBook1.PersistTokens.Section := 'tokens'; TMSFMXCloudFaceBook1.LoadTokens; TMSFMXCloudFaceBook1.Tag := integer(csFacebook); TMSFMXCloudTwitter1.App.Key := TwitterAppkey; TMSFMXCloudTwitter1.App.Secret := TwitterAppSecret; TMSFMXCloudTwitter1.PersistTokens.Key := GetDocumentsDirectory + '/twitter.ini'; TMSFMXCloudTwitter1.PersistTokens.Section := 'tokens'; TMSFMXCloudTwitter1.LoadTokens; TMSFMXCloudTwitter1.Tag := integer(csTwitter); TMSFMXCloudDropBox1.App.Key := DropBoxAppkey; TMSFMXCloudDropBox1.App.Secret := DropBoxAppSecret; TMSFMXCloudDropBox1.PersistTokens.Key := GetDocumentsDirectory + '/dropbox.ini'; TMSFMXCloudDropBox1.PersistTokens.Section := 'tokens'; TMSFMXCloudDropBox1.LoadTokens; TMSFMXCloudDropBox1.Tag := integer(csDropBox); TMSFMXCloudGDrive1.App.Key := GoogleAppKey; TMSFMXCloudGDrive1.App.Secret := GoogleAppSecret; TMSFMXCloudGDrive1.PersistTokens.Key := GetDocumentsDirectory + '/gdrive.ini'; TMSFMXCloudGDrive1.PersistTokens.Section := 'tokens'; TMSFMXCloudGDrive1.LoadTokens; TMSFMXCloudGDrive1.Tag := integer(csGDrive); TMSFMXCloudFlickr1.App.Key := FlickrAppKey; TMSFMXCloudFlickr1.App.Secret := FlickrAppSecret; TMSFMXCloudFlickr1.PersistTokens.Key := GetDocumentsDirectory + '/flickr.ini'; TMSFMXCloudFlickr1.PersistTokens.Section := 'tokens'; TMSFMXCloudFlickr1.LoadTokens; TMSFMXCloudFlickr1.Tag := integer(csFlickr); end;
//Initializes the status by showing an Ok or Error image next to each service.
procedure TForm937.InitStatus(cs: TCloudServices);
begin
if csFacebook in cs then
begin
svcOKFacebook.Visible := TMSFMXCloudFaceBook1.TestTokens;
svcErrFacebook.Visible := not svcOKFacebook.Visible;
end;
if csTwitter in cs then
begin
svcOKTwitter.Visible := TMSFMXCloudTwitter1.TestTokens;
svcErrTwitter.Visible := not svcOKTwitter.Visible;
end;
if csDropBox in cs then
begin
svcOKDropBox.Visible := TMSFMXCloudDropBox1.TestTokens;
svcErrDropBox.Visible := not svcOKDropBox.Visible;
end;
if csGDrive in cs then
begin
svcOKGDrive.Visible := TMSFMXCloudGDrive1.TestTokens;
svcErrGDrive.Visible := not svcOKGDrive.Visible;
end;
if csFlickr in cs then
begin
svcOKFlickr.Visible := TMSFMXCloudFlickr1.TestTokens;
svcErrFlickr.Visible := not svcOKFlickr.Visible;
end;
end;
//Connects to a specific service
procedure TForm1.ConnectService(cs: TCloudService; ServiceName: string);
var
cb: TTMSFMXCloudBase;
vw: TTMSFMXNativeUIImageView;
begin
case cs of
csFacebook: cb := TMSFMXCloudFaceBook1;
csTwitter: cb := TMSFMXCloudTwitter1;
csDropBox: cb := TMSFMXCloudDropBox1;
csFlickr: cb := TMSFMXCloudFlickr1;
csGDrive: cb := TMSFMXCloudGDrive1;
end;
case cs of
csFacebook: vw := svcOKFacebook;
csTwitter: vw := svcOKTwitter;
csDropBox: vw := svcOKDropBox;
csFlickr: vw := svcOKFlickr;
csGDrive: vw := svcOKGDrive;
end;
if vw.Visible then
begin
if MessageDlg(ServiceName +' already authorized, do you want to unauthorize ?', TMsgDlgType.mtInformation,
[TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], 0) = mrYes then
begin
cb.ClearTokens;
InitStatus([cs]);
end;
Exit;
end
else
cb.DoAuth;
end;
Changing appearance
Each component in the TMS iCL set has a default appearance, which is the native appearance that comes with the iOS SDK. The appearance might be different depending on the SDK and kind of device. The iOS showcase demonstrates how to change the appearance of your application with a few lines of code. The application appearance can be changed to have an Ocean look through a popup after clicking the Style button in the toolbar. The TMSFMXNativeUITableView component has an OnGetItemAppearance event that is called for each item. The Ocean style applies banding in the TMSFMXNativeUITableView and the code to accomplish this is demonstrated below:
//The TMSFMXNativeUITableView customizes its appearance through the OnGetItemAppearance event.
procedure TForm1.TMSFMXNativeUITableView1GetItemAppearance(Sender: TObject;
ASection, ARow: Integer;
var AAppearance: TTMSFMXNativeUITableViewItemAppearance);
begin
if FStyle = 1 then
begin
if Odd(ARow) then
AAppearance.BackGroundColor := $FFEFFFFE;
AAppearance.SelectedBackGroundColor := $FF2AC6BD;
end;
end;