2012-10-01 9 views
6

In meiner Anwendung habe ich eine UIViewController, dass ich eine Menge von UIAlertView verwendet, um Dinge an den Benutzer zu stellen.Erstellen Sie benutzerdefinierte dynamische Klassen in Objective-c

Weil ich die Antwort jedes UIAlertView muss ich mein Controller ein Delegierter von UIAlertViewDelegate gemacht haben, das funktioniert gut, aber nach 7 UIAlertView ‚s i`m versuchen, einen besseren Weg zu finden, die Delegierten zu verwenden.

in Java ich weiß, dass ich Inline-Klassen für einen einzigen Zweck zu schaffen, wie in dieser Frage: Java - inline class definition

Was ich will, ist wissen: Gibt es eine Möglichkeit, eine Klasse zu erstellen Delegierten dynamisch sein? So etwas zu erreichen

id<UIAlertViewDelegate> myCustomClass = @class { 
    my class code goes here 
} 

UIAlertView* alertView; 
alertView = [[UIAlertView alloc] initWithTitle:@"Title" 
             message:@"Message" 
             delegate:myCustomClass 
          cancelButtonTitle:@"No" 
          otherButtonTitles:@"OK", @"Sure", @"Maybe", nil] ];  
[alertView show]; 
+0

'@ CLASS' passieren zu nennen hat eine ganz andere Bedeutung in Obj-C als das, was du denkst. Es erklärt eine Art "Weiterleitungsklasse", FYI. –

+1

Der Punkt der Benutzung von '' class'' ist nur etwas Ähnliches zu zeigen, um mir zu erklären, was ich denke. nur das –

Antwort

14

Nein - In Objective-C gibt es keine Inline-Klassen. Nachdem Sie das gesagt haben, können Sie zur Laufzeit benutzerdefinierte Objekte mit objective-c erstellen, was ein wenig komplizierter ist, aber ich wäre bereit, etwas Code zu teilen, um das zu tun, was Sie sagen.

Hier ist ein Beispiel, dass:

NSObject + Subclass.h

#import <objc/runtime.h> 

typedef struct selBlockPair { SEL aSEL; id (^__unsafe_unretained aBlock)(id, ...); } selBlockPair; 
#define NIL_PAIR ((struct selBlockPair) { 0, 0 }) 
#define PAIR_LIST (struct selBlockPair []) 
#define BLOCK_CAST (id (^)(id, ...)) 

@interface NSObject (subclass) 

+(Class) newSubclassNamed:(NSString *) name 
      protocols:(Protocol **) protos 
       impls:(selBlockPair *) impls; 

@end 

NSObject + Subclass.m

@implementation NSObject (subclass) 

+(Class) newSubclassNamed:(NSString *)name 
      protocols:(Protocol **)protos 
       impls:(selBlockPair *)impls 
{ 
    if (name == nil) 
    { 
     // basically create a random name 
     name = [NSString stringWithFormat:@"%s_%i_%i", class_getName(self), arc4random(), arc4random()]; 
    } 

    // allocated a new class as a subclass of self (so I could use this on a NSArray if I wanted) 
    Class newClass = objc_allocateClassPair(self, [name UTF8String], 0); 

    // add all of the protocols untill we hit null 
    while (protos && *protos != NULL) 
    { 
     class_addProtocol(newClass, *protos); 
     protos++; 
    } 

    // add all the impls till we hit null 
    while (impls && impls->aSEL) 
    { 
     class_addMethod(newClass, impls->aSEL, imp_implementationWithBlock(impls->aBlock), "@@:*"); 
     impls++; 
    } 

    // register our class pair 
    objc_registerClassPair(newClass); 

    return newClass; 
} 

@end 

Verwendungsbeispiel:

int main() 
{ 
    @autoreleasepool { 
     __strong Class newClass = [NSString newSubclassNamed:@"MyCustomString" protocols:NULL impls: PAIR_LIST { 
      @selector(description), 
      BLOCK_CAST ^id (id self) { 
       return @"testing"; 
      }, 
      NIL_PAIR 
     }]; 

     NSString *someString = [newClass new]; 
     NSLog(@"%@", someString); 
    } 
} 

Ausgang:

 
2012-10-01 10:07:33.609 TestProj[54428:303] testing 
+0

Ihre Antwort beantwortete alle meine Fragen über Inline-Klassen und öffnete eine weitere Reihe von Fragen zu Ihrem Code. Danke für die Echtheit. Jetzt versuche ich diesen Code zu verstehen, den du gepostet hast. Nochmals vielen Dank –

+0

@NicosKaralis kein Problem, wenn Sie irgendwelche Probleme Verständnis haben, haben Sie keine Angst zu fragen! –

+0

Brilliant! Eine kurze Frage, gibt es eine einfache Möglichkeit, '[super description]' in der benutzerdefinierten impl zu nennen? – ccwasden

3

Diese Art von Java anonyme innere Klasse ist nicht etwas, das in Objective-C unterstützt wird. Wenn Sie den Delegierten individuell antworten möchten, ist es ein guter Weg, mit Blöcken zu experimentieren.

Leider hat Apple keine Blöcke in UIAlertViews hinzugefügt, aber Sie können sie selbst implementieren. Eine Menge Leute haben das online gemacht. Schau mal hier: http://blog.mugunthkumar.com/coding/ios-code-block-based-uialertview-and-uiactionsheet/ oder https://github.com/MugunthKumar/UIKitCategoryAdditions.

Die Grundidee ist, dass Sie eine Unterklasse (oder eine Kategorie bei Verwendung von zugeordneten Objekte) erstellen kann, wird das seine eigenen Delegierten sein und seine eigenen Delegierten sagen, einen Block, den Sie in

+0

Ihre Antwort hilft mir auch sehr, Panzer –