TableView Scroll

  • TableView Scroll

    Hallo,
    ich habe so eine ähnliche Frage schonmal gestellt aber bin leider nicht wirklich auf eine gute Lösung gekommen.

    Ich lade parse aus einer XML Daten wie Produktnamen und Bilder usw.
    Durch die Bilder wird mein Scroll aber sehr ruckelig und das nervt natürlich total.
    Ich möchte das die Bilder nachgeladen werden und das ein ActivityIndicator in der Zeit angezeigt wird.

    Quellcode

    1. //Bild in der Zelle
    2. NSString * bildUrl = [[products objectAtIndex: storyIndex]objectForKey:@"internerLink"];
    3. bildUrl = [bildUrl stringByReplacingOccurrencesOfString:@"medium" withString:@"small"];
    4. bildUrl = [bildUrl stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
    5. UIImage* smallPic = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:bildUrl]]];
    6. UIImageView *tableImage = [[UIImageView alloc] initWithImage:smallPic];
    7. cell.accessoryView = tableImage;
    8. [tableImage release];
    Alles anzeigen


    ..so lade ich mir die Bilder in den accessoryView der Zelle.

    Wäre sehr nett wenn jemand der ein ähnliches Problem hatte mir das etwas genauer erklären kann, denn ich hänge an diesem Problem schon länger und schiebe es immer wieder vor mir her dabei sollte es eigentlich ja gar nicht sooo schwer sein :(

    Mit freundlichen Grüßen

    Moritz
  • RE: TableView Scroll

    Du solltest den ImageView nur einmal erzeugen und ansonsten die image-Property des des Views setzen. Dynamisches Nachladen von Bildern kannst Du über eine Kategorie machen:

    Quellcode

    1. @interface UIImageView(DelayedLoading)
    2. - (void)loadImageFromURL:(NSURL *)inURL indicatorStyle:(UIActivityIndicatorViewStyle)inStyle;
    3. @end
    und

    Quellcode

    1. @implementation UIImageView(DelayedLoading)
    2. - (void)loadImageFromURL:(NSURL *)inURL indicatorStyle:(UIActivityIndicatorViewStyle)inStyle {
    3. [self addIndicatorViewWithStyle:inStyle];
    4. [self performSelector:@selector(loadDelayedImage:) withObject:inURL afterDelay:0.1];
    5. }
    6. - (void)loadDelayedImage:(NSURL *)inURL {
    7. NSData *theData = [NSData dataWithContentsOfURL:inURL];
    8. self.image = [UIImage imageWithData:theData];
    9. }
    10. @end
    Alles anzeigen
    „Meine Komplikation hatte eine Komplikation.“
  • RE: TableView Scroll

    Das bringt doch genauso wenig.
    +dataWithContentsOfURL ist syncrhonous und blockt die UI, während es die Daten über das Netzwerk lädt.
    Du solltest NSURLConnection benutzen und ein Cache von Bildern verwenden.
  • @macmoonshine performSelector:withObject:AfterDelay: wird zwar in der Runloop delayed,lädt aber trotzdem synchronous auf dem main thread, also nichts mit async. Wenn, dann musst du performSelectorInBackground verwenden und ein NSAutoreleasePool benutzen.
  • so ich hab das nun fast ^^
    jedoch hab ich noch eine frage
    und zwar ich habe nun folgenden code als kategorie

    Quellcode

    1. @implementation UIImageView( DelayedLoading )
    2. - (void)loadImageFromURL:(NSURL *)inURL indicatorStyle:(UIActivityIndicatorViewStyle)inStyle {
    3. // [self addIndicatorViewWithStyle:inStyle];
    4. [self performSelector:@selector(loadDelayedImage:) withObject:inURL afterDelay:0.1];
    5. }
    6. - (void)loadDelayedImage:(NSURL *)inURL {
    7. NSLog (@"dataWithContentsOfURL %@",inURL);
    8. NSData *theData = [NSData dataWithContentsOfURL:inURL];
    9. self.image = [UIImage imageWithData:theData];
    10. }
    11. @end
    Alles anzeigen


    funktioniert auch soweit das er inURL ausgibt und mit alle links anzeigt und wenn ich im eigentlichen controller das ImageView auslogge zeigt er mir auch an das dort was drin ist...aber meine tabelle zeigt keine bilder an..daraufhin habe ich mein tableImage.image ausgeloggt und festgestellt das dort 0 drinsteht aber wieso? eigentlich sage ich doch in der kategorie self.image = [UIImage imageWithData:theData];

    zudem musste ich addIndicatorViewWithStyle auskommentieren, da es anscheinend nicht bekannt ist?

    mfg
    moritz
  • Ups, stimmt:

    Quellcode

    1. #define INDICATOR_TAG 112233
    2. - (void)addIndicatorViewWithStyle:(UIActivityIndicatorViewStyle)inStyle {
    3. CGSize theSize = self.frame.size;
    4. UIActivityIndicatorView *theIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:inStyle];
    5. CGRect theFrame = theIndicator.frame;
    6. theIndicator.tag = INDICATOR_TAG;
    7. theFrame.origin = CGPointMake((theSize.width - theFrame.size.width) / 2.0,
    8. (theSize.height - theFrame.size.height) / 2.0);
    9. theIndicator.frame = theFrame;
    10. [self addSubview:theIndicator];
    11. [theIndicator startAnimating];
    12. [theIndicator autorelease];
    13. }
    14. - (void)removeIndicator {
    15. id theIndicator = [self viewWithTag:INDICATOR_TAG];
    16. if([theIndicator isKindOfClass:[UIActivityIndicatorView class]]) {
    17. [theIndicator stopAnimating];
    18. [theIndicator removeFromSuperview];
    19. }
    20. }
    Alles anzeigen

    Du musst noch ein

    Quellcode

    1. [self removeIndicator];
    in die Methode setzen, wenn die Daten geladen wurden.

    Zum starten des Ladens musst Du für Deinen ImageView die Methode loadImageFromURL:indicatorStyle: sonst passiert nichts.
    „Meine Komplikation hatte eine Komplikation.“
  • ah cool danke sehr dann ist das ja schonmal gelöst :)

    hmm ich rufe die methode ja auf und zwar in dem controller der die bilder läd und anzeigt:

    Quellcode

    1. [tableImage loadImageFromURL:[NSURL URLWithString:bildUrl] indicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];


    ...die bildUrl übergibt er dann auch ganz brav an die kategorie jedoch kommt kein bild zurück und ich bekomme folgende warning: "UIImageView may not respond to loadImageFromURL:indicatorStyle" ..dabei müsste er die doch nun kennen
  • ach so ich dachte die kategorie ändert das sofort für jedes ImageView...gut die warning ist weg aber tableImage.image hat immer noch 0 bilder..man ich kann doch nciht so verdammt doof sein du hast mir das ja quasi schon fertig geschrieben und das sieht auch alles wunderbar aus
  • Original von moritz91
    ach so ich dachte die kategorie ändert das sofort für jedes ImageView...gut die warning ist weg aber tableImage.image hat immer noch 0 bilder..man ich kann doch nciht so verdammt doof sein du hast mir das ja quasi schon fertig geschrieben und das sieht auch alles wunderbar aus

    Das macht die Kategorie auch. Aber dein Code muss es auch wissen.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • jo den header habe ich nun auch in den entsprechenden controller importiert ;)
    ich poste mal meinen code etwas genauer:

    Kategorie:

    Quellcode

    1. #import <UIKit/UIKit.h>
    2. @interface UIImageView(DelayedLoading)
    3. - (void)loadImageFromURL:(NSURL *)inURL indicatorStyle:(UIActivityIndicatorViewStyle)inStyle;
    4. @end


    Quellcode

    1. #import "UIImageView+DelayedLoading.h"
    2. @implementation UIImageView( DelayedLoading )
    3. #define INDICATOR_TAG 112233
    4. - (void)addIndicatorViewWithStyle:(UIActivityIndicatorViewStyle)inStyle {
    5. CGSize theSize = self.frame.size;
    6. UIActivityIndicatorView *theIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:inStyle];
    7. CGRect theFrame = theIndicator.frame;
    8. theIndicator.tag = INDICATOR_TAG;
    9. theFrame.origin = CGPointMake((theSize.width - theFrame.size.width) / 2.0,
    10. (theSize.height - theFrame.size.height) / 2.0);
    11. theIndicator.frame = theFrame;
    12. [self addSubview:theIndicator];
    13. [theIndicator startAnimating];
    14. [theIndicator autorelease];
    15. }
    16. - (void)removeIndicator {
    17. id theIndicator = [self viewWithTag:INDICATOR_TAG];
    18. if([theIndicator isKindOfClass:[UIActivityIndicatorView class]]) {
    19. [theIndicator stopAnimating];
    20. [theIndicator removeFromSuperview];
    21. }
    22. }
    23. - (void)loadImageFromURL:(NSURL *)inURL indicatorStyle:(UIActivityIndicatorViewStyle)inStyle {
    24. // [self addIndicatorViewWithStyle:inStyle];
    25. [self performSelector:@selector(loadDelayedImage:) withObject:inURL afterDelay:0.1];
    26. }
    27. - (void)loadDelayedImage:(NSURL *)inURL {
    28. NSLog (@"dataWithContentsOfURL %@",inURL);
    29. NSData *theData = [NSData dataWithContentsOfURL:inURL];
    30. [self removeIndicator];
    31. self.image = [UIImage imageWithData:theData];
    32. }
    33. @end
    Alles anzeigen


    SearchResultController:

    Quellcode

    1. //Bild in der Zelle
    2. NSString * bildUrl = [[products objectAtIndex: storyIndex]objectForKey:@"internerLink"];
    3. bildUrl = [bildUrl stringByReplacingOccurrencesOfString:@"medium" withString:@"small"];
    4. bildUrl = [bildUrl stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
    5. UIImageView *tableImage = [[UIImageView alloc] init];
    6. [tableImage loadImageFromURL:[NSURL URLWithString:bildUrl] indicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
    7. NSLog (@"tableImage!!!: %@",tableImage);
    8. cell.accessoryView = tableImage;
    9. [tableImage release];
    Alles anzeigen


    wenn ich das tableImage auslogge dann sind da scheinbar auch die bilder drin aber nicht wenn ich tableImage.image auslogge...und ich bekomme kein bild im cell.accessoryView..

    mit freundlichen grüßen
    moritz