2016-06-16 10 views
3

До сих пор (Swift 2.2) Я с радостью воспользовался кодом от this answer - это немного, это элегантно, это сработало, как сон.Swift 3: Сортировка (ранее сортировка по месту) массив по дескрипторам сортировки

extension MutableCollectionType where Index : RandomAccessIndexType, Generator.Element : AnyObject { 
    /// Sort `self` in-place using criteria stored in a NSSortDescriptors array 
    public mutating func sortInPlace(sortDescriptors theSortDescs: [NSSortDescriptor]) { 
     sortInPlace { 
      for sortDesc in theSortDescs { 
       switch sortDesc.compareObject($0, toObject: $1) { 
       case .OrderedAscending: return true 
       case .OrderedDescending: return false 
       case .OrderedSame: continue 
       } 
      } 
      return false 
     } 
    } 
} 

extension SequenceType where Generator.Element : AnyObject { 
    /// Return an `Array` containing the sorted elements of `source` 
    /// using criteria stored in a NSSortDescriptors array. 
    @warn_unused_result 
    public func sort(sortDescriptors theSortDescs: [NSSortDescriptor]) -> [Self.Generator.Element] { 
     return sort { 
      for sortDesc in theSortDescs { 
       switch sortDesc.compareObject($0, toObject: $1) { 
       case .OrderedAscending: return true 
       case .OrderedDescending: return false 
       case .OrderedSame: continue 
       } 
      } 
      return false 
     } 
    } 
} 

Swift 3 все изменения.

Используя инструмент миграции кода и Proposal SE- 0006 - sort() => sorted(), sortInPlace() => sort() - я получил, насколько

extension MutableCollection where Index : Strideable, Iterator.Element : AnyObject { 
    /// Sort `self` in-place using criteria stored in a NSSortDescriptors array 
    public mutating func sort(sortDescriptors theSortDescs: [SortDescriptor]) { 
     sort { 
      for sortDesc in theSortDescs { 
       switch sortDesc.compare($0, to: $1) { 
       case .orderedAscending: return true 
       case .orderedDescending: return false 
       case .orderedSame: continue 
       } 
      } 
      return false 
     } 
    } 
} 

extension Sequence where Iterator.Element : AnyObject { 
    /// Return an `Array` containing the sorted elements of `source` 
    /// using criteria stored in a NSSortDescriptors array. 

    public func sorted(sortDescriptors theSortDescs: [SortDescriptor]) -> [Self.Iterator.Element] { 
     return sorted { 
      for sortDesc in theSortDescs { 
       switch sortDesc.compare($0, to: $1) { 
       case .orderedAscending: return true 
       case .orderedDescending: return false 
       case .orderedSame: continue 
       } 
      } 
      return false 
     } 
    } 
} 

«рассортированные» функция компилируется [и работает] без проблем. Для 'sort' я получаю сообщение об ошибке в строке, которая говорит «sort»: «Невозможно преобразовать значение типа» (_, _) -> _ 'в ожидаемый тип аргумента «[SortDescriptor]», который полностью меня озадачил: I не понимаю, где компилятор пытается конвертировать что-либо, поскольку я передаю массив SortDescriptors, который должен быть массивом SortDescriptors.

Обычно этот тип ошибок означает, что вы обрабатываете дополнительные опции, в которых вы должны иметь определенные значения, но поскольку это аргумент функции - и, похоже, он работает без заминки в func sorted - все, что я могу прочитать, это что «что-то не так». На данный момент я понятия не имею, ЧТО что-то есть, и поскольку мы находимся на ранних стадиях бета-тестирования, документации вообще нет.

В качестве обходного пути, я удалил вид функции (ранее сортировки на месте) из моего кода и заменить его танец

пусть sortedArray = oldArray (отсортированный [...] oldArray = sortedArray

, но я был бы очень признателен, если бы я мог получить свою функциональность сортировки в месте назад

+0

Почему не просто что-то (например, как NSArray) .sortedArray (используя: sortDescriptors) '? Нет ничего плохого в подключении к типам Foundation, где они предоставляют необходимую функциональность. – rickster

+0

a) Я предпочитаю избегать мостов, особенно потому, что есть шанс, что в какой-то момент будет удален бесплатный мост. (Мы уже видим эту тенденцию). Кроме того, б) У меня есть метод, который будет работать, поэтому это не актуально; но я хотел бы понять, что здесь происходит - мне что-то не хватает, и я не вижу его сам. –

+0

Можете ли вы привести пример использования этих методов в Swift 2.2? –

ответ

1

Сравнить доступные в Swift 2.2 методы:.

enter image description here

с методами в Swift 3:

enter image description here

Обратите внимание, что Swift 3 не имеет sort метод, который принимает isOrderedBefore закрытия.

Именно поэтому ваша функция не будет компилироваться.

Это похоже на ошибку, поэтому я сообщил об этом как ошибку 26857748 на странице bugreport.apple.com.

+0

Где вы нашли эти методы? В Xcode 8 я получаю только получение варианта isOrderedBefore при завершении кода. (сортировать и сортировать на игровых площадках, как iOS, так и MacOS, сортируются только в проекте MacOS). Сортированный (sortDescriptors :) вариант доступен для NSArray в проекте MacOS, но не в файле детской площадки. –

+0

Вышеупомянутое из файла игровой площадки iOS в Xcode 8. –

+0

Apple говорит, что метод теперь 'sort (by:)', но я не могу найти этот метод в MutableCollection. Кажется, существует только на EmptyCollection и CollectionOfOne . –

0

пусть sortedArray = users.sorted {$ 0.name < $ 1.name}

+0

это не работает с быстрым 3. –

+0

OP хочет сортировать на месте, а не создавать новый массив. –

0

Использование RandomAccessCollection протокол

extension MutableCollection where Self : RandomAccessCollection { 
    /// Sort `self` in-place using criteria stored in a NSSortDescriptors array 
    public mutating func sort(sortDescriptors theSortDescs: [NSSortDescriptor]) { 
     sort { by: 
      for sortDesc in theSortDescs { 
       switch sortDesc.compare($0, to: $1) { 
       case .orderedAscending: return true 
       case .orderedDescending: return false 
       case .orderedSame: continue 
       } 
      } 
      return false 
     } 
    } 
} 
0

В Swift 3,0

let sortedCapitalArray = yourArray.sorted {($0 as AnyObject).localizedCaseInsensitiveCompare(($1 as AnyObject)as! String) == ComparisonResult.orderedAscending}