我已基于此tutorial设计了搜索组件。
在表格视图中只有一个部分的情况下,它很好用,所以我不必担心嵌套的东西。
这是我的代码:
import UIKit
protocol Searchable {
var query: String { get }
var isSelected: Bool { get set }
}
class BaseSearchDataSource<V, T: Searchable>: NSObject, UITableViewDataSource where V: BaseTableViewCell<T> {
private var models: [T]
private let configureCell: CellConfiguration
typealias CellConfiguration = (V, T) -> V
private var searchResults: [T] = []
private var isSearchActive: Bool = false
init(models: [T], configureCell: @escaping CellConfiguration) {
self.models = models
self.configureCell = configureCell
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return isSearchActive ? searchResults.count : models.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: V = tableView.dequeueReusableCell(forIndexPath: indexPath)
let model = getModelAt(indexPath)
return configureCell(cell, model)
}
func getModelAt(_ indexPath: IndexPath) -> T {
return isSearchActive ? searchResults[indexPath.item] : models[indexPath.item]
}
func search(query: String) {
isSearchActive = !query.isEmpty
searchResults = models.filter {
let queryToFind = $0.query.range(of: query, options: NSString.CompareOptions.caseInsensitive)
return (queryToFind != nil)
}
}
}
我有一个符合指定协议的此类实现:
class MuscleSelectableItem: Searchable {
var query: String {
return name
}
var isSelected: Bool
let name: String
let muscle: MusclEntity
init (isSelected: Bool, name: String, muscle: MusclEntity) {
self.isSelected = isSelected
self.name = name
self.muscle = muscle
}
}
因此,现在当我使用父级BaseSearchDataSource的子类时,我可以简单地指定一个要加载到表视图中的类,并使该类可搜索。所以现在我的var models: [T]
将模型表示为[MuscleSelectableItem]
我了解到我需要使用一些带有嵌套项的section对象:
class TableViewSection {
var items: [MuscleSelectableItem]
}
但是上面代码的问题是我为[MuscleSelectableItem]
指定了具体类型items
。
如何用[T]
声明TableViewSection
和items
,直到我们在子类中告诉编译器我们要为items
使用哪种类型(例如搜索)之前,如何声明items
适用于城市,肌肉或书籍或其他任何实体,因此IDEAL
MODEL small
STACK 100h
DATASEG
filename db 'lv1maze.bmp',0
filename2 db 'Dotmaze.bmp',0
filehandle dw ?
Header db 54 dup (0)
Palette db 256*4 dup (0)
ScrLine db 320 dup (0)
ErrorMsg db 'Error', 13, 10,'$'
color db 12
CODESEG
proc OpenFile
; Open file
mov ah, 3Dh
xor al, al
mov dx, offset filename
int 21h
jc openerror
mov [filehandle], ax
ret
openerror:
mov dx, offset ErrorMsg
mov ah, 9h
int 21h
ret
endp OpenFile
; dot pic
proc Opendot
;dot pic
mov ah, 3Dh
xor al, al
mov dx, offset filename2
int 21h
jc openerror
mov [filehandle], ax
ret
endp Opendot
proc ReadHeader
; Read BMP file header, 54 bytes
mov ah,3fh
mov bx, [filehandle]
mov cx,54
mov dx,offset Header
int 21h
ret
endp ReadHeader
proc ReadPalette
; Read BMP file color palette, 256 colors * 4 bytes (400h)
mov ah,3fh
mov cx,400h
mov dx,offset Palette
int 21h
ret
endp ReadPalette
proc CopyPal
; Copy the colors palette to the video memory
; The number of the first color should be sent to port 3C8h
; The palette is sent to port 3C9h
mov si,offset Palette
mov cx,256
mov dx,3C8h
mov al,0
; Copy starting color to port 3C8h
out dx,al
; Copy palette itself to port 3C9h
inc dx
PalLoop:
; Note: Colors in a BMP file are saved as BGR values rather than RGB.
mov al,[si+2] ; Get red value.
shr al,2 ; Max. is 255, but video palette maximal
; value is 63. Therefore dividing by 4.
out dx,al ; Send it.
mov al,[si+1] ; Get green value.
shr al,2
out dx,al ; Send it.
mov al,[si] ; Get blue value.
shr al,2
out dx,al ; Send it.
add si,4 ; Point to next color.
; (There is a null chr. after every color.)
loop PalLoop
ret
endp CopyPal
proc CopyBitmap
; BMP graphics are saved upside-down.
; Read the graphic line by line (200 lines in VGA format),
; displaying the lines from bottom to top.
mov ax, 0A000h
mov es, ax
mov cx,200
PrintBMPLoop:
push cx
; di = cx*320, point to the correct screen line
mov di,cx
shl cx,6
shl di,8
add di,cx
; Read one line
mov ah,3fh
mov cx,320
mov dx,offset ScrLine
int 21h
; Copy one line into video memory
cld ; Clear direction flag, for movsb
mov cx,320
mov si,offset ScrLine
rep movsb ; Copy line to the screen
;rep movsb is same as the following code:
;mov es:di, ds:si
;inc si
;inc di
;dec cx
;loop until cx=0
pop cx
loop PrintBMPLoop
ret
endp CopyBitmap
start:
mov ax,@data
mov ds,ax
; Graphics mode
mov ax,13h
int 10h
call OpenFile
call ReadHeader
call ReadPalette
call CopyPal
call CopyBitmap
; Initializes the mouse
mov ax,0h
int 33h
; showing the mouse
mov ax,1h
int 33h
; Loop until mouse click
MouseLP:
mov ax,3h
int 33h
cmp bx, 01h ; check left mouse click
jne MouseLP
; Print dot near mouse location
shr cx,1 ; adjust cx to range 0-319, to fit screen
sub dx, 1 ; move one pixel, so the pixel will not be hidden by mouse
mov bh,0h
mov al,[color]
mov ah,0Ch
int 10h
; Press any key to continue
mov ah,00h
int 16h
; Text mode
mov ax,3h
int 10h
exit:
mov ax,4C00h
int 21h
END start
可以是其中的任何一个
我也不希望我的协议包含搜索和选择功能,如何正确地将其分开?
答案 0 :(得分:0)
您也可以在包装中使用泛型。在上述情况下,它看起来像这样:
class TableViewSection<T> {
var items = [T]()
}
您还可以构建一个TableDataSource类,该类具有一组表视图节,这将打开诸如基于indexPath下标的机会,然后使其符合收集协议,从而获得过滤器,计数等功能。
我也不希望我的协议包含搜索和选择功能,如何正确地将其分开?
Swift允许使用类型别名来组成较小协议的协议。上面可以这样划分:
protocol Searchable {
var query: String { get }
}
protocol Selectable {
var isSelected: Bool { get set }
}
typealias SearchAndSelectable = Searchable & Selectable
SearchAndSelectable类型的变量上将同时具有'query'和'isSelected'值,这对于可以利用这两种协议类型的通用约束或函数很方便。