Когда я должен использовать Odbc, OleDb, SQLClient? Каковы компромиссы

Поскольку UISegmentedControl отправляет действие только в том случае, если выбран невыбранный сегмент, необходимо выполнить подкласс UISegmentedControl, чтобы внести незначительные изменения в его обработку касания. Я использую этот класс:

@implementation MBSegmentedControl

// this sends a value changed event even if we reselect the currently selected segment
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSInteger current = self.selectedSegmentIndex;
    [super touchesBegan:touches withEvent:event];
    if (current == self.selectedSegmentIndex) {
        [self sendActionsForControlEvents:UIControlEventValueChanged];
    }
}

@end

Теперь вы получите UIControlEventValueChanged событий, даже если сегмент уже выбран. Просто сохраните текущий индекс в переменной и сравните его в действии. Если два индекса совпадают, вы должны отменить выбор затронутого сегмента.

// _selectedSegmentIndex is an instance variable of the view controller

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    _selectedSegmentIndex = self.segment.selectedSegmentIndex;
}

- (IBAction)segmentChanged:(UISegmentedControl *)sender {
    if (sender.selectedSegmentIndex == _selectedSegmentIndex) {
        NSLog(@"Segment %d deselected", sender.selectedSegmentIndex);
        sender.selectedSegmentIndex =  UISegmentedControlNoSegment;
        _selectedSegmentIndex = UISegmentedControlNoSegment;
    }
    else {
        NSLog(@"Segment %d selected", sender.selectedSegmentIndex);
        _selectedSegmentIndex = sender.selectedSegmentIndex;
    }
}

iOS 7 изменила способ обработки касаний для UISegmentedControl. SelectedSegmentIndex теперь изменяется во время touchesEnded:.

Таким образом, обновленный подкласс должен выглядеть следующим образом:

@implementation MBSegmentedControl

+ (BOOL)isIOS7 {
    static BOOL isIOS7 = NO;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSInteger deviceSystemMajorVersion = [[[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:@"."] objectAtIndex:0] integerValue];
        if (deviceSystemMajorVersion >= 7) {
            isIOS7 = YES;
        }
        else {
            isIOS7 = NO;
        }
    });
    return isIOS7;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSInteger previousSelectedSegmentIndex = self.selectedSegmentIndex;
    [super touchesBegan:touches withEvent:event];
    if (![[self class] isIOS7]) {
        // before iOS7 the segment is selected in touchesBegan
        if (previousSelectedSegmentIndex == self.selectedSegmentIndex) {
            // if the selectedSegmentIndex before the selection process is equal to the selectedSegmentIndex
            // after the selection process the superclass won't send a UIControlEventValueChanged event.
            // So we have to do this ourselves.
            [self sendActionsForControlEvents:UIControlEventValueChanged];
        }
    }
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    NSInteger previousSelectedSegmentIndex = self.selectedSegmentIndex;
    [super touchesEnded:touches withEvent:event];
    if ([[self class] isIOS7]) {
        // on iOS7 the segment is selected in touchesEnded
        if (previousSelectedSegmentIndex == self.selectedSegmentIndex) {
            [self sendActionsForControlEvents:UIControlEventValueChanged];
        }
    }
}

@end

Версия Swift 2.2 исправила проблему, замеченную Гжегожем.

class ReselectableSegmentedControl: UISegmentedControl {
    @IBInspectable var allowReselection: Bool = true

    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
        let previousSelectedSegmentIndex = self.selectedSegmentIndex
        super.touchesEnded(touches, withEvent: event)
        if allowReselection && previousSelectedSegmentIndex == self.selectedSegmentIndex {
            if let touch = touches.first {
                let touchLocation = touch.locationInView(self)
                if CGRectContainsPoint(bounds, touchLocation) {
                    self.sendActionsForControlEvents(.ValueChanged)
                }
            }
        }
    }
}

Swift 3.0 изменяет исправление для этого, чтобы выглядеть следующим образом:

class MyDeselectableSegmentedControl: UISegmentedControl {
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        let previousIndex = selectedSegmentIndex

        super.touchesEnded(touches, with: event)

        if previousIndex == selectedSegmentIndex {
            let touchLocation = touches.first!.location(in: self)

            if bounds.contains(touchLocation) {
                sendActions(for: .valueChanged)
            }
        }
    }
}
8
задан CrazyTim 27 February 2015 в 03:19
поделиться

5 ответов

Я бы просто использовал SqlClient и переписал / заново сгенерировал DAL, если он изменился.

Если вы не собираетесь внедрять и тестировать на нескольких платформах прямо сейчас, я ' Я не уверен, что дополнительные усилия сейчас имеют большое значение или меньше, чем усилия по переделке DAL, и тот факт, что у вас вообще есть DAL, означает, что у вас есть все в одном месте для последующих изменений в любом случае.

1
ответ дан 5 December 2019 в 19:02
поделиться

Вы хотите использовать драйвер SQL Server. Я понимаю, что вы пытаетесь сделать, но для поддержки нескольких баз данных вы можете добавить еще один уровень абстракции. Вы можете сделать это разными способами. Но вы помещаете код, специфичный для базы данных, на край иерархии классов. Следовательно, каждый класс может получить преимущества специфической функциональности базы данных, но вызывающие стороны более высокого уровня не знают или не заботятся о том, какая база данных используется ниже. Что касается ORM, я предпочитаю LLBLGen , но это только мое предпочтение.

Кроме того, просто для пояснения, LINQ не является специфическим для SQL Server. Это LINQ-to-SQL. LINQ - это технология запросов, которую можно использовать в LINQ-to-SQL, LINQ-to-Entities, LINQ-to-objects, и даже LLBLGen поддерживает LINQ.

2
ответ дан 5 December 2019 в 19:02
поделиться

Если у вас есть подозрения, что вы будете менять базы данных (или поддерживать несколько бэкэндов), то ORM - это то, что вам нужно. В противном случае вам все равно придется реорганизовать / переписать большую часть вашего DAL, чтобы поддержать изменение. Если у вас маленькое приложение, оно не будет плохим, но что-нибудь существенное, и вам будет больно.

1
ответ дан 5 December 2019 в 19:02
поделиться

Я слышал, что там сказано, что если это не ключевая функция, вам не следует слишком беспокоиться о сохранении независимости платформы. Тем не менее,

SQLClient предоставит вам собственный доступ и должен быть более производительным (он не должен делать никаких абстракций / переводов).

Единственное, что вам нужно изменить, чтобы заставить OLEDB работать по сравнению с ODBC, - это ваш строка подключения. OLEDB имеет немного больше интеллекта на стороне клиента, поэтому он обеспечивает лучшую производительность.

0
ответ дан 5 December 2019 в 19:02
поделиться

Вы обнаружите, что при использовании SQL Server SqlClient намного быстрее и проще в разработке, чем OleDB и ODBC - если только не очень вероятно, что вам понадобится поддержка нескольких платформ, вы обнаружите, что преимущества перевешивают риски, связанные с переписыванием вашего DAL.

Кроме того, использование OleDB / ODBC - это только один способ сохранить независимость от платформы - вы можете найти более эффективным иметь несколько реализаций вашего DAL, каждая из которых использует собственный клиентский к используемой платформе.

1
ответ дан 5 December 2019 в 19:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: