2016-03-22 5 views
0

Я пытаюсь воспроизвести эту картину в Swiftмакрокоманды с возвращаемым значением

#define mustBeKindOfClassFailedReturn(object, objectClass, ret) \ 
if(![object isKindOfClass:objectClass]) { \ 
NSLog(([NSString stringWithFormat:@"%@ must be kind of %@ class, current class is %@", object, NSStringFromClass(objectClass), NSStringFromClass([object class])])) \ 
return ret; } 

используется как это

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView 
        layout:(UICollectionViewLayout*)collectionViewLayout 
    insetForSectionAtIndex:(NSInteger)section { 

mustNotBeNilFailedReturn(self.adapter, UIEdgeInsetsZero) 
mustBeKindOfClassFailedReturn(self.adapter, [WBCollectionViewSectionAdapter class], UIEdgeInsetsZero) 

Кто-нибудь знает хорошее решение этой проблемы?

Редактировать

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

/** 
* mustOverride 
*/ 
#define mustOverride \ 
{ NSLog(@"You must override this function") } 

#define mustOverrideFailedReturn(ret) \ 
{ mustOverride \ 
return ret; } 

EDIT 2

Я закончил с решением, является ли это оптимальным?

func needOverride(function: String = __FUNCTION__, file: String = __FILE__, line: Int = __LINE__) -> Bool { 

    REVLogManager.SharedInstance.logErrorMessage("You must override this function", function: function, file: file, line: line, exception: nil, error: nil) 

    return false 

} 

func doesObject(function: String = __FUNCTION__, file: String = __FILE__, line: Int = __LINE__, matchingObject: AnyObject!, matchesClass matchingClass: AnyClass) -> Bool { 

    guard matchingObject.isKindOfClass(matchingClass) else { 

     let message = "\(matchingObject) must be kind of \(matchingClass) class, current class is \(matchingObject.dynamicType)" 
     REVLogManager.SharedInstance.logErrorMessage(message, function: function, file: file, line: line, exception: nil, error: nil) 

     return false 

    } 

    return true 

} 

Я вызываю метод как этот

public func actualScrollOffsetDistanceWithScrollView(scrollView: UIScrollView!) -> Float { 

    guard needOverride() else { return 0.0 } 
    return 0.0 

} 

И

guard doesObject(matchingObject: self, matchesClass: REVListSectionAdapter.classForCoder()) else { return } 
+0

Что такое «ret» Предполагалось быть? – PeejWeej

+0

Это может быть что угодно: Float, Int, AnyObject, Bool, UIEdgeInsets и даже nil – Pwyll28

ответ

0

Мой ответ по той же схеме, используя устаревшую в Swift. Вы можете использовать classForCoder, но я предпочитаю dynamicType для проверки типа.

func mustBeKindOfClassFailedReturn(object: AnyObject, objectClass: AnyClass, returnVal: Any?) { 
    if !object.isKindOfClass(objectClass) { 
     print("\(object) must be kind of \(objectClass) class, current class is \(object.dynamicType)") 
     return returnVal 
    } 
    return nil // or UIEdgeInsetsZero, or whatever 
} 

Вы также можете получить аналогичные результаты с !(object is objectClass), но все становится сложнее при сравнении определенных типов чисел. См Swift type inference and type checking issue

Вы также можете заменить AnyObject и Any с NSObject, если вы знаете, что вы имеете дело с типами Objective-C. Из вашего комментария кажется, что ret может быть типом значения, поэтому я делаю его Any.

+0

Но, даже если мой объект является правильным классом, я верну «returnVal», который не подходит мне – Pwyll28

+0

@ Pwyll28 ah Я неправильно прочитал ваш макрос, отредактировал мой ответ, чтобы вернуть нуль, если класс не совпадает. – JAL

+0

Является ли это чем-то другим, кроме повторной записи «если пусть» или «охранять?»? – PeejWeej

0

У Swift есть лучшее решение для такого рода проблем, the guard statement. В этом случае просто поместите это в свой метод.

guard let adapter = self.adapter as? WBCollectionViewSectionAdapter else { 
/* return value if the adapter is not setup properly. */ 
    return .Zero 
} 
/* continue with valid and correctly classed adapter */ 

Если вы ищете способ, чтобы справиться с этим для суб классов, вы можете рассмотреть generics. Это позволит вам подразумевать безопасность типов без необходимости переписывать логику в ваших подклассах.

+0

Я отредактировал свой вопрос в ответе на ваш комментарий – Pwyll28

+0

Отредактировал мой ответ :) – PeejWeej

+0

переиздал мой вопрос – Pwyll28

0

У Swift нет макросов такого типа.

С точки зрения достижения вашей цели. Образец, за которым вы следуете, будет наиболее корректно обрабатываться с помощью операторов guard. Функция, содержащая инструкцию охраны, должна выйти из закрывающей области (или ловушки) и может сделать это с возвратом.

Просьба проверить документацию Swift для получения информации о контрольном потоке и управлении ранним выходом

Смежные вопросы