UIAlertView Delegate

This is the forum for miscellaneous technical/programming questions.

Moderator: 2ffat

UIAlertView Delegate

Postby jayden » Fri Sep 18, 2015 12:57 pm

Hi,

Im following Brian Long's video on accessing iOS API's but trying to implement it in C++. Managed to get my head around it until he implemented a Delegate for UIAlertView. This is what I have so far:
Code: Select all
#pragma region UIAlertView - Using Delegate
class TAlertViewDelegate : public TOCLocal, public UIAlertViewDelegate
{
   //Virtual in .hpp I believe means that its going to be defined somewhere else
   public:
      void __cdecl alertView(_di_UIAlertView alertView, int clickedButtonAtIndex);
      void __cdecl alertViewCancel(_di_UIAlertView alertView);
};
_di_UIAlertViewDelegate Delegate;
#pragma region Helper Function - Returns A ObjC Pointer To An NSString From A Unicode String
void * PNSSTR(const String str)
{
   return ((_di_ILocalObject)StrToNSStr(str))->GetObjectID();
}
#pragma end_region

void __cdecl TAlertViewDelegate::alertView(_di_UIAlertView alertView, int clickedButtonAtIndex)
{
   //Could Use Log::d again but will use NSlog
   Iosapi::Foundation::NSLog(PNSSTR("UIAlertView Button Pressed!"));
   switch(clickedButtonAtIndex)
   {
      case 0:
         Log::d("You Clicked Cancel");
         break;
      case 1:
         Log::d("You clicked Yes");
         break;
      case 2:
         Log::d("You clicked No");
         break;
      case 3:
         Log::d("You clicked Maybe");
         break;
   }
   alertView->setDelegate(nil);
   Delegate = nil;
}

void __cdecl TAlertViewDelegate::alertViewCancel(_di_UIAlertView alertView)
{
   Log::d("Alert View Was Cancelled");
   alertView->setDelegate(nil);
   Delegate = nil;
}
void __fastcall TForm1::ListBoxItem6Click(TObject *Sender)
{
   _di_UIAlertView alertView;
   Delegate = TAlertViewDelegate();  ----> COMPILER ERROR: See Below
   alertView = TUIAlertView::Alloc();
   __try
   {
      alertView = TUIAlertView::Wrap(alertView->initWithTitle(
         StrToNSStr("A Very Important Question"),             //Title
         StrToNSStr("Do you like me? :)"),               //Message
         ((_di_ILocalObject)Delegate)->GetObjectID(),    //Delegate
         StrToNSStr("Cancel"),                           //Cancel Button Caption
         nil                                             //Other Button Caption
      ));
      /*Add Some More Buttons....*/
      alertView->addButtonWithTitle(StrToNSStr("Absolutley!"));
      alertView->addButtonWithTitle(StrToNSStr("Nope."));
      alertView->addButtonWithTitle(StrToNSStr("Meh :|"));
      alertView->show();
   }
   __finally
   {
      alertView->release();
   }
}
#pragma end_region


However I am not sure if I have created the delegate correctly - but I am getting a compiler error saying "allocating an object of abstract class type 'TAlertViewDelegate'. Looking at the source the TOCLocal has a constructor so therefor as I am subclassing it do I call TAlertViewDelegate::TOCLocal()?

Any help would be appreciated!

FYI The UIAlertViewDelegate interface from iOSapi.UIKit.hpp
Code: Select all
__interface  INTERFACE_UUID("{A52A64A0-AA7E-422E-B7A4-8EFCF2C20A49}") UIAlertViewDelegate  : public Macapi::Objectivec::IObjectiveC
{
#ifndef __aarch64__
   virtual void __cdecl alertView(_di_UIAlertView alertView, int clickedButtonAtIndex) = 0 /* overload */;
#else /* __aarch64__ */
   virtual void __cdecl alertView(_di_UIAlertView alertView, long clickedButtonAtIndex) = 0 /* overload */;
#endif /* __aarch64__ */
   virtual void __cdecl alertViewCancel(_di_UIAlertView alertView) = 0 ;
   virtual void __cdecl didPresentAlertView(_di_UIAlertView alertView) = 0 ;
#ifndef __aarch64__
   virtual void __cdecl alertViewDidDismissWithButtonIndex(_di_UIAlertView alertView, int didDismissWithButtonIndex) = 0 ;
#else /* __aarch64__ */
   virtual void __cdecl alertViewDidDismissWithButtonIndex(_di_UIAlertView alertView, long didDismissWithButtonIndex) = 0 ;
#endif /* __aarch64__ */
};
jayden
Active Poster
Active Poster
 
Posts: 24
Joined: Fri Aug 21, 2015 3:41 pm

Re: UIAlertView Delegate

Postby rlebeau » Fri Sep 18, 2015 11:22 pm

jayden wrote:
Code: Select all
class TAlertViewDelegate : public TOCLocal, public UIAlertViewDelegate
{
   //Virtual in .hpp I believe means that its going to be defined somewhere else
   public:
      void __cdecl alertView(_di_UIAlertView alertView, int clickedButtonAtIndex);
      void __cdecl alertViewCancel(_di_UIAlertView alertView);
};



They are not just virtual, they are "pure" virtual (they all have "= 0" on their declarations), aka they are "abstract" methods. Which means you MUST override them. UIAlertViewDelegate defines 4 abstract methods (2 of which are wrapped in #ifdef's to account for iOS64), but your class is only overriding 2 of them. You need to overriding all 4 of them, or else your class will be abstract and cannot be instantiated directly (which is exactly what the compiler is complaining about):

Code: Select all
class TAlertViewDelegate : public TOCLocal, public UIAlertViewDelegate
{
public:
    #ifndef __aarch64__
    virtual void __cdecl alertView(_di_UIAlertView alertView, int clickedButtonAtIndex);
    #else
    virtual void __cdecl alertView(_di_UIAlertView alertView, long clickedButtonAtIndex);
    #endif

    virtual void __cdecl alertViewCancel(_di_UIAlertView alertView);
    virtual void __cdecl didPresentAlertView(_di_UIAlertView alertView);

    #ifndef __aarch64__
    virtual void __cdecl alertViewDidDismissWithButtonIndex(_di_UIAlertView alertView, int didDismissWithButtonIndex);
    #else
    virtual void __cdecl alertViewDidDismissWithButtonIndex(_di_UIAlertView alertView, long didDismissWithButtonIndex);
    #endif
};

#ifndef __aarch64__
void __cdecl TAlertViewDelegate::alertView(_di_UIAlertView alertView, int clickedButtonAtIndex)
#else
void __cdecl TAlertViewDelegate::alertView(_di_UIAlertView alertView, long clickedButtonAtIndex)
#endif
{
    //...
}

void __cdecl TAlertViewDelegate::alertViewCancel(_di_UIAlertView alertView)
{
    //...
}

void __cdecl TAlertViewDelegate::didPresentAlertView(_di_UIAlertView alertView)
{
    //...
}

#ifndef __aarch64__
void __cdecl TAlertViewDelegate::alertViewDidDismissWithButtonIndex(_di_UIAlertView alertView, int didDismissWithButtonIndex)
#else
void __cdecl ::alertViewDidDismissWithButtonIndex(_di_UIAlertView alertView, long didDismissWithButtonIndex)
#endif
{
    //...
}


Alternatively, use a custom #define to clean up the #ifdef's:

Code: Select all
#ifndef __aarch64__
#define aarch_int_t int
#else
#define aarch_int_t long
#endif

class TAlertViewDelegate : public TOCLocal, public UIAlertViewDelegate
{
public:
    virtual void __cdecl alertView(_di_UIAlertView alertView, aarch_int_t clickedButtonAtIndex);
    virtual void __cdecl alertViewCancel(_di_UIAlertView alertView);
    virtual void __cdecl didPresentAlertView(_di_UIAlertView alertView);
    virtual void __cdecl alertViewDidDismissWithButtonIndex(_di_UIAlertView alertView, aarch_int_t didDismissWithButtonIndex);
};

void __cdecl TAlertViewDelegate::alertView(_di_UIAlertView alertView, aarch_int_t clickedButtonAtIndex)
{
    //...
}

void __cdecl TAlertViewDelegate::alertViewCancel(_di_UIAlertView alertView)
{
    //...
}

void __cdecl TAlertViewDelegate::didPresentAlertView(_di_UIAlertView alertView)
{
    //...
}

void __cdecl TAlertViewDelegate::alertViewDidDismissWithButtonIndex(_di_UIAlertView alertView, aarch_int_t didDismissWithButtonIndex)
{
    //...
}


jayden wrote:
Code: Select all
alertView->setDelegate(nil);
Delegate = nil;



FYI, you need to use NULL or nullptr in C++. nil is a Delphi keyword.

jayden wrote:
Code: Select all
Delegate = TAlertViewDelegate();  ----> COMPILER ERROR: See Below



Even if that could compile, it would not work. You need to allocate the class on the heap instead of the stack:

Code: Select all
Delegate = (UIAlertViewDelegate*) new TAlertViewDelegate();
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1533
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: UIAlertView Delegate

Postby jayden » Sat Sep 19, 2015 3:48 am

Hi Remy,

Thanks a ton, I understand why they all need to be implemented makes perfect sense. I am however still getting a compiler issue (same as before) as it is telling me that:
Code: Select all
[bcciosarm Error] Unit1.cpp(208): allocating an object of abstract class type 'TAlertViewDelegate'
  sysmac.h(329): unimplemented pure virtual method 'Release' in 'TAlertViewDelegate'
  sysmac.h(327): unimplemented pure virtual method 'QueryInterface' in 'TAlertViewDelegate'
  sysmac.h(328): unimplemented pure virtual method 'AddRef' in 'TAlertViewDelegate'


Surely for these methods I would want to leave the implementation to that defined in TOCLocal for updating the reference counts?
Thanks,
Jayden
jayden
Active Poster
Active Poster
 
Posts: 24
Joined: Fri Aug 21, 2015 3:41 pm

Re: UIAlertView Delegate

Postby rlebeau » Sat Sep 19, 2015 12:28 pm

jayden wrote:Thanks a ton, I understand why they all need to be implemented makes perfect sense. I am however still getting a compiler issue (same as before) as it is telling me that:
Code: Select all
[bcciosarm Error] Unit1.cpp(208): allocating an object of abstract class type 'TAlertViewDelegate'
  sysmac.h(329): unimplemented pure virtual method 'Release' in 'TAlertViewDelegate'
  sysmac.h(327): unimplemented pure virtual method 'QueryInterface' in 'TAlertViewDelegate'
  sysmac.h(328): unimplemented pure virtual method 'AddRef' in 'TAlertViewDelegate'



Those are IUnknown methods. Delphi interfaces derive from IInterface instead, which is Delphi's equivalent to IUnknown. They are similar but have subtle differences. Delphi's TInterfacedObject base class implements IInterface, not IUnknown.

jayden wrote:Surely for these methods I would want to leave the implementation to that defined in TOCLocal for updating the reference counts?


Yes, but you have to implement the IUnknown methods in your class and have them call TOCLocal's IInterface methods. There is a section on this issue in the Embarcadero DocWiki:

IUnknown and IInterface

Creating classes that support IUnknown
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1533
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: UIAlertView Delegate

Postby jayden » Sun Sep 20, 2015 5:37 pm

Great, thanks I will give this a shot tomorrow!
jayden
Active Poster
Active Poster
 
Posts: 24
Joined: Fri Aug 21, 2015 3:41 pm

Re: UIAlertView Delegate

Postby jayden » Mon Sep 21, 2015 9:05 am

Hi Remy,

Gave this a try, looking at the link you gave me I implemented INTFOBJECT_IMPL_IUNKOWN(TOCLocal); after my class declaration and the program then compiled.

However on when clicking the item that constructs the UIAlertView with a delegate I got an exception:
First chance exception at $00188DF5. Exception class EObjectiveC with message 'RTTI for type UIAlertViewDelegate was not found. Perhaps missing {$M+}?'. Process Project5 (1145233)

I then tried changing my class declaration to:
Code: Select all
class __declspec(TAlertViewDelegate) TAlertViewDelegate : public TOCLocal, public UIAlertViewDelegate
{
 //....
}

However this yielded a result no different - I got the exact same exception as before.
and
Code: Select all
class __declspec(delphirtti) TAlertViewDelegate  : public TOLocal, public UIAlertViewDelegate
{
 //...
}

This caused a different exception - it came up on runtime slightly different to the one before:
Project Project5 raised exception class EObjectiveC with message 'RTTI for type NSObject was not found. Perhaps missing {$M+}?'.

I have had a look at the documentation here, but any help to figure out what this is and how to access the delegate would be greatly appreciated. I must confess at this point I have little idea how or what the Delphi RTTI is - all that I know is from what is available from the wiki that I can understand :oops:

Thanks!
jayden
Active Poster
Active Poster
 
Posts: 24
Joined: Fri Aug 21, 2015 3:41 pm

Re: UIAlertView Delegate

Postby rlebeau » Wed Sep 23, 2015 12:36 am

jayden wrote:However on when clicking the item that constructs the UIAlertView with a delegate I got an exception:
First chance exception at $00188DF5. Exception class EObjectiveC with message 'RTTI for type UIAlertViewDelegate was not found. Perhaps missing {$M+}?'. Process Project5 (1145233)


Sorry, I can't help with that error. You will likely have to contact Embarcadero directly for help.

jayden wrote:I then tried changing my class declaration to:
Code: Select all
class __declspec(TAlertViewDelegate) TAlertViewDelegate : public TOCLocal, public UIAlertViewDelegate



TAlertViewDelegate is not a valid parameter value for __declspec(). You might try using __declspec(delphiclass), though.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1533
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA


Return to Technical

Who is online

Users browsing this forum: No registered users and 12 guests

cron