【问题标题】:Odd animations with swipe to delete action in UITableView在 UITableView 中滑动删除动作的奇怪动画
【发布时间】:2019-01-30 23:06:18
【问题描述】:

我的 UITableView 遇到问题。 删除滑动手势的动画无法正常工作。 问题是,在新模板项目“MasterDetailed”中效果很好。但不在我目前工作的项目中。

我之前遇到过另一个问题,即在第一次完成动画后动画无法正常工作。我通过在我的代码中替换它来修复它。

/// New code
- (void)gl_setObject:(id)obj forKeyedSubscript:(id<NSCopying>)key {
    if (!key || !obj) {
        return;
    }
    [self gl_setObject:obj forKeyedSubscript:key];
}

/// Old code
- (void)gl_setObject:(id)obj forKeyedSubscript:(id<NSCopying>)key {
    if (!key) {
        return;
    }
    if (!obj) {
        obj = [NSNull null];
    }
    [self gl_setObject:obj forKeyedSubscript:key];
}

这是当前 TableView 的代码,它在 Xcode 基础项目中工作,但不在我的项目中。

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface TempViewController: UIViewController

@end

NS_ASSUME_NONNULL_END
#import "TempViewController.h"
#import "TempTableViewCell.h"

@interface TempViewController () <UITableViewDelegate, UITableViewDataSource>

@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property NSMutableArray *objects;

@end

@implementation TempViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // TableView
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    self.tableView.rowHeight = 80;
    [self.tableView registerNib:[UINib nibWithNibName:@"TempTableViewCell" bundle:nil] forCellReuseIdentifier:@"TempTableViewCell"];

    // Add button to add element when deleting too much
    UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(insertNewObject:)];
    self.navigationItem.rightBarButtonItem = addButton;

    // Add some data to make the bug work
    for (int i = 0; i < 100; i++) {
        [self insertNewObject:0];
    }
}

- (void)insertNewObject:(id)sender {
    if (!self.objects) {
        self.objects = [[NSMutableArray alloc] init];
    }
    [self.objects insertObject:[NSDate date] atIndex:0];
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
    [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}

#pragma mark - Table View

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.objects.count;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    TempTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"TempTableViewCell" forIndexPath:indexPath];
    NSDate *object = self.objects[indexPath.row];
    cell.tempLabel.text = [object description];
    return cell;
}


- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return NO if you do not want the specified item to be editable.
    return YES;
}


- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        [self.objects removeObjectAtIndex:indexPath.row];
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    } else if (editingStyle == UITableViewCellEditingStyleInsert) {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
    }
}

@end

所以,我想知道你们是否知道在哪里看?或者之前已经遇到过这个问题?

感谢您未来的帮助!! 建设愉快!

【问题讨论】:

    标签: objective-c uitableview tableview uiswipegesturerecognizer uiswipeactionsconfiguration


    【解决方案1】:

    嗯,

    我更深入地研究了我们的混合方法。 我完全删除了这段代码。我们使用它来避免在字典中插入 nil 值。没有它,错误就消失了。我不知道为什么,但如果有一天我找到了答案,我会更新这篇文章。 希望它可以为某些人节省一些时间!

    #import "NSDictionary+NilSafe.h"
    #import <objc/runtime.h>
    
    @implementation NSObject (Swizzling)
    
    + (BOOL)gl_swizzleMethod:(SEL)origSel withMethod:(SEL)altSel {
        Method origMethod = class_getInstanceMethod(self, origSel);
        Method altMethod = class_getInstanceMethod(self, altSel);
        if (!origMethod || !altMethod) {
            return NO;
        }
        class_addMethod(self,
                        origSel,
                        class_getMethodImplementation(self, origSel),
                        method_getTypeEncoding(origMethod));
        class_addMethod(self,
                        altSel,
                        class_getMethodImplementation(self, altSel),
                        method_getTypeEncoding(altMethod));
        method_exchangeImplementations(class_getInstanceMethod(self, origSel),
                                       class_getInstanceMethod(self, altSel));
        return YES;
    }
    
    + (BOOL)gl_swizzleClassMethod:(SEL)origSel withMethod:(SEL)altSel {
        return [object_getClass((id)self) gl_swizzleMethod:origSel withMethod:altSel];
    }
    
    @end
    
    @implementation NSDictionary (NilSafe)
    
    + (void)load {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            [self gl_swizzleMethod:@selector(initWithObjects:forKeys:count:) withMethod:@selector(gl_initWithObjects:forKeys:count:)];
            [self gl_swizzleClassMethod:@selector(dictionaryWithObjects:forKeys:count:) withMethod:@selector(gl_dictionaryWithObjects:forKeys:count:)];
        });
    }
    
    + (instancetype)gl_dictionaryWithObjects:(const id [])objects forKeys:(const id<NSCopying> [])keys count:(NSUInteger)cnt {
        id safeObjects[cnt];
        id safeKeys[cnt];
        NSUInteger j = 0;
        for (NSUInteger i = 0; i < cnt; i++) {
            id key = keys[i];
            id obj = objects[i];
            if (!key) {
                continue;
            }
            if (!obj) {
                obj = [NSNull null];
            }
            safeKeys[j] = key;
            safeObjects[j] = obj;
            j++;
        }
        return [self gl_dictionaryWithObjects:safeObjects forKeys:safeKeys count:j];
    }
    
    - (instancetype)gl_initWithObjects:(const id [])objects forKeys:(const id<NSCopying> [])keys count:(NSUInteger)cnt {
        id safeObjects[cnt];
        id safeKeys[cnt];
        NSUInteger j = 0;
        for (NSUInteger i = 0; i < cnt; i++) {
            id key = keys[i];
            id obj = objects[i];
            if (!key) {
                continue;
            }
            if (!obj) {
                obj = [NSNull null];
            }
            safeKeys[j] = key;
            safeObjects[j] = obj;
            j++;
        }
        return [self gl_initWithObjects:safeObjects forKeys:safeKeys count:j];
    }
    
    @end
    
    @implementation NSMutableDictionary (NilSafe)
    
    + (void)load {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            Class class = NSClassFromString(@"__NSDictionaryM");
            [class gl_swizzleMethod:@selector(setObject:forKey:) withMethod:@selector(gl_setObject:forKey:)];
            [class gl_swizzleMethod:@selector(setObject:forKeyedSubscript:) withMethod:@selector(gl_setObject:forKeyedSubscript:)];
        });
    }
    
    - (void)gl_setObject:(id)anObject forKey:(id<NSCopying>)aKey {
        if (!aKey) {
            return;
        }
        if (!anObject) {
            anObject = [NSNull null];
        }
        [self gl_setObject:anObject forKey:aKey];
    }
    
    - (void)gl_setObject:(id)obj forKeyedSubscript:(id<NSCopying>)key {
        if (!key) {
            return;
        }
        if (!obj) {
            obj = [NSNull null];
        }
        [self gl_setObject:obj forKeyedSubscript:key];
    }
    
    @end
    
    @implementation NSNull (NilSafe)
    
    
    + (void)load {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            [self gl_swizzleMethod:@selector(methodSignatureForSelector:) withMethod:@selector(gl_methodSignatureForSelector:)];
            [self gl_swizzleMethod:@selector(forwardInvocation:) withMethod:@selector(gl_forwardInvocation:)];
        });
    }
    
    - (NSMethodSignature *)gl_methodSignatureForSelector:(SEL)aSelector {
        NSMethodSignature *sig = [self gl_methodSignatureForSelector:aSelector];
        if (sig) {
            return sig;
        }
        return [NSMethodSignature signatureWithObjCTypes:@encode(void)];
    }
    
    - (void)gl_forwardInvocation:(NSInvocation *)anInvocation {
        NSUInteger returnLength = [[anInvocation methodSignature] methodReturnLength];
        if (!returnLength) {
            // nothing to do
            return;
        }
    
        // set return value to all zero bits
        char buffer[returnLength];
        memset(buffer, 0, returnLength);
    
        [anInvocation setReturnValue:buffer];
    }
    
    @end
    

    编辑 1:好吧,最后,问题是对 obj 的 nil 检查

    if (!key || !obj) {
        return;
    }
    /// Replaced by
    if (!key) {
        return;
    }
    
    

    我保留了其余的代码,如果插入尝试在 NSDictionary 中插入 nil 值,它会产生崩溃。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多