Swift协议,关联类型作为参数类型

时间:2017-12-26 12:36:40

标签: ios swift swift-protocols associated-types

所以我在这里有这个协议

def __init__(self, master = None):          #initialising the frame setup for windows

    Frame.__init__(self, master)
    self.master = master
    self.init_window()

def init_window(self):
    global lb,a,n
    self.master.title("Alarm")
    self.pack(fill=BOTH, expand =1)

    newButton = Button(self, text="New Alarm", command=self.new_window)     #create buttons and link to commands
    newButton.place(x=50, y=50)
    deleteButton = Button(self, text="Delete Alarm", command = self.alarmDelete)
    deleteButton.place(x=250, y=50)



    n=0                                         #loop through to find out how many rows are in the database
    for row in c.execute('SELECT Start Destination FROM stocks '):
        n = n + 1


    i=0
    remove=")"
    removed="("
    removing=","
    remover="'"
    a = [[0] * 14 for i in range(n)]             #load database into multidimensional array
    for row in c.execute('SELECT Start Destination FROM stocks '):
        a[i][0]= row
        temp=""
        for j in str(a[i][0]):              #remove unwanted characters from vars
            if j==remove or j == removed or j == removing :
                null=""
            else:
                temp=temp + str(j)
        a[i][0]=temp
        i = i + 1

    i=0
    for row in c.execute('SELECT End Destination FROM stocks '):
        a[i][1]= row
        temp=""
        for j in str(a[i][1]):
            if j==remove or j == removed or j == removing :
                null=""
            else:
                temp=temp + str(j)
        a[i][1]=temp
        i = i + 1

    i=0
    for row in c.execute('SELECT hArrival FROM stocks '):
        a[i][2]= row
        temp=""
        for j in str(a[i][2]):
            if j==remove or j == removed or j == removing or j==remover  :
                null=""
            else:
                temp=temp + str(j)
        a[i][2]=temp
        i = i + 1

    i=0
    for row in c.execute('SELECT mArrival FROM stocks '):
        a[i][3]= row
        temp=""
        for j in str(a[i][3]):
            if j==remove or j == removed or j == removing or j == remover:
                null=""
            else:
                temp=temp + str(j)
        a[i][3]=temp
        i = i + 1

    i=0
    for row in c.execute('SELECT Preperation Time FROM stocks '):
        a[i][4]= row
        temp=""
        for j in str(a[i][4]):
            if j==remove or j == removed or j == removing :
                null=""
            else:
                temp=temp + str(j)
        a[i][4]=temp
        i = i + 1

    i=0
    for row in c.execute('SELECT Day Date FROM stocks '):
        a[i][5]= row
        temp=""
        for j in str(a[i][5]):
            if j==remove or j == removed or j == removing :
                null=""
            else:
                temp=temp + str(j)
        a[i][5]=temp
        i = i + 1

    i=0
    for row in c.execute('SELECT Month Date FROM stocks '):
        a[i][6]= row
        temp=""
        for j in str(a[i][6]):
            if j==remove or j == removed or j == removing :
                null=""
            else:
                temp=temp + str(j)
        a[i][6]=temp
        i = i + 1

    i=0
    for row in c.execute('SELECT Year Date FROM stocks '):
        a[i][7]= row
        temp=""
        for j in str(a[i][7]):
            if j==remove or j == removed or j == removing :
                null=""
            else:
                temp=temp + str(j)
        a[i][7]=temp
        i = i + 1

    i=0
    for row in c.execute('SELECT AlarmName FROM stocks '):
        a[i][10]= row
        temp=""
        for j in str(a[i][10]):
            if j==remove or j == removed or j == removing or j ==remover :
                null=""
            else:
                temp=temp + str(j)
        a[i][10]=temp
        i = i + 1


    i=0
    for i in range(n):#convert times and dates to timestamp and datestamps
        a[i][8] = int(a[i][2])*3600 + int(a[i][3])*60
        a[i][9] = str(a[i][6]) + "/" + str(a[i][5]) + "/" + str(a[i][7])
        i=i+1

    i=0
    for i in range(n): #set all boolean value to true for later validation in calc
        a[i][12] = "00:00"
        a[i][12] = datetime.strptime(a[i][12], '%H:%M').time()
        i=i+1

    for i in range(n): #set all boolean value to true for later validation in calc
        a[i][13] = 0
        i=i+1

    i=0
    lb=Listbox(root)    #create listbox and insert values
    lb.pack()
    for i in range(n):
       for item in [str(a[i][10])]:
            lb.insert(END, item)
            i=i+1




    lb.bind('<Double-Button-1>', Window.alarmInfo) #if list item is double clicked call alarmInfo
    Window.alarmCalc(self) #call calculations


def alarmInfo(self):            #finds out which listbox item was selcted and prints info about it
    global lb,a,n
    listName = lb.get(ACTIVE)
    i=-1

    for i in range(n):
        if listName == a[i][10]:
            break
        else:
            i=i+1

    window = Toplevel(root)
    window.geometry("200x150")
    Label(window, text="Start Destination:").grid(row=0, sticky=W)
    Label(window, text=a[i][0]).grid(row=0,column=1, sticky=W)
    Label(window, text="End Destination:").grid(row=1, sticky=W)
    Label(window, text=a[i][1]).grid(row=1,column=1, sticky=W)
    Label(window, text="Arrival Time:").grid(row=2, sticky=W)
    Label(window, text=a[i][2] + ":" + a[i][3]).grid(row=2,column=1, sticky=W)
    Label(window, text="Preperation Time:").grid(row=3, sticky=W)
    Label(window, text=a[i][5]).grid(row=3,column=1, sticky=W)
    Label(window, text="Date").grid(row = 4,column=0, sticky=W)
    Label(window, text=a[i][9]).grid(row=4,column=1, sticky=W)
    Label(window, text="Alarm Name:").grid(row=5, sticky=W)#
    Label(window, text=a[i][10]).grid(row=5,column=1, sticky=W)

def alarmDelete(self):
    global a,n,lb
    listName = lb.get(ACTIVE)
    i=-1

    for i in range(n):
        if listName == a[i][10]:
            break
        else:
            i=i+1

    for row in c.execute('SELECT AlarmName FROM stocks '): #deletes selected item from database
        temp = row
        if listName in temp:
            c.execute('DELETE FROM stocks WHERE AlarmName=?', (listName,))
            conn.commit()
            break      


def new_window(self):           #create new window, and initialise layout
    global eSd,eEd,eAth,eAtm,ePt,eDd,eDm,eDy,eAn

    window = Toplevel(root)
    window.geometry("550x300")

    Label(window, text="Start Destination").grid(row=0, sticky=W)
    Label(window, text="End Destination").grid(row=1, sticky=W)
    Label(window, text="Arrival Time").grid(row=2, sticky=W)
    Label(window, text=":").grid(row=2, column=2, sticky=W)
    Label(window, text="Preperation Time").grid(row=3, sticky=W)
    Label(window, text="Alarm Name").grid(row=5, sticky=W)#

    eSd = Entry(window, width=5)
    eEd = Entry(window,width=5)
    eAth = Spinbox(window, from_=0, to=23)
    eAtm = Spinbox (window, from_=0, to=59)
    eDd = Spinbox (window, from_=1, to=31)
    eDm = Spinbox (window, from_=1, to=12)
    eDy = Spinbox (window, from_=2017, to=2019)
    ePt = Entry(window,width=5)
    eAn = Entry(window, width=20)

    eSd.grid(row=0, column=1, sticky=W)
    eEd.grid(row=1, column=1, sticky=W)
    eAth.grid(row=2, column=1, sticky=W)
    eAtm.grid(row=2,column=3, sticky=W)
    ePt.grid(row=3, column=1, sticky=W)
    eAn.grid(row=5, column=1, sticky=W)#

    Label(window, text="Date").grid(row = 4,column=0, sticky=W)
    eDd.grid(row = 4,column=3, sticky=W)
    Label(window, text="/").grid(row = 4,column=2, sticky=W)
    eDm.grid(row = 4,column=1, sticky=W)
    Label(window, text="/").grid(row = 4,column=4, sticky=W)
    eDy.grid(row = 4,column=5, sticky=W)#

    createButton = Button(window, text ="Create", command = self.create) #link to def create()
    createButton.place(x =50,y=150)


def create(self):
    global eSd,eEd,eAth,eAtm,ePt,eDd,eDm,eDy,eAn
    global sd,ed,ath,atm,pt,Dd,Dm,Dy,an
    val1 = False
    val2 = False
    val3 = True
    error=""

    sd = eSd.get()
    ed = eEd.get()
    ath = eAth.get()
    atm = eAtm.get()
    pt = ePt.get()
    Dd = eDd.get()
    Dm = eDm.get()
    Dy = eDy.get()
    an = eAn.get()#

    with open('zipcode.csv') as csvfile: #check through csv file to validate zipfiles
        reader = csv.reader(csvfile)
        for row in reader:
            for col in row:
                if col == sd:
                    val1= True
                if col ==ed:
                    val2 = True



    if len(pt) < 5:             #validate pt
        try:
            val3 = int(pt)
        except ValueError:
            val3 = False
    else:
        val3 = False


    if val1 == False and val2 == False and val3 == False:       #Compare boolean values to generate correct error message
        error = "Invalid Prep Time and Zipcodes"
    elif val1 == False and val3 == False :
        error = "Invalid Prep Time and Start Zipcode"
    elif val1 == False and val2 == False :
        error = "Invalid Zipcodes"
    elif val2==False and val3==False:
        error= "Invalid Prep Time and End Zipcode"
    elif val1 == False:
        error="Invalid Start Zipcode"
    elif val2==False:
        error="Invalid End Zipcode"
    elif val3==False:
        error = "Invalid Prep Time"


    if val1 == False or val2 == False or val3 == False:         #call different function depending on errors
        Window.valEr(self,error)
    else:
        Window.addList(self)



def valEr(self, error):             #displays error message
    window = Toplevel(root)
    window.geometry("100x100")
    Label(window, text=error).place(x=40, y=40)

def addList(self):
    global sd,ed,ath,atm,pt,Dd,Dm,Dy,an#
    if len(ath)< 2:                 #add preceeding 0's to single values to make calculations easier
        ath = "0" + ath
    if len(atm) < 2:
        atm = "0" + atm
    if len(Dm) < 2:
        Dm = "0" + Dm
    if len(Dd) <2:
        Dd = "0" + Dd
    pt = int(pt) * 60

    writeTo = (sd,ed,ath,atm,pt,Dd,Dm,Dy,an) #create tuple to make writing to database easier

    c.execute("INSERT INTO stocks VALUES(?,?,?,?,?,?,?,?,?)", writeTo) #insert data into database
    conn.commit()
                                          #################################################################################      

def alarmCalc(self):
    global a,n
    x=1000000000000000000000000
    i=0
    nowDate = date.today()
    temp =""
    temp2 = ""
    nowDate = str(nowDate.month) + "/" + str(nowDate.day) + "/" + str(nowDate.year) #get todays date
    for i in range(n):
        if nowDate == a[i][9]:
            Link= 'https://www.mapquestapi.com/directions/v2/route?key=YCGaovp1Y6fRO5f1RVWv2c1Qs9F4qF1N&from='+str(a[i][0])+'%2C+NY&to='+str(a[i][1])+'%2C+NY&outFormat=json&routeType=fastest&avoidTimedConditions=true&narrativeType=none'
            response = requests.get(Link)
            data = json.loads(response.text)
            rawtravelTime =int( data["route"]["time"])   #request and retrieve correct time
            #print(rawtravelTime)
            a[i][11]= int(a[i][8]) - int(a[i][4]) - rawtravelTime #calculate time in seconds
            #print(a[i][11])
            m, s = divmod(a[i][11], 60) # convert seconds to time using quotients
            h, m = divmod(m, 60)
            a[i][11]= str("%d:%02d:%02d" % (h, m, s))
            a[i][11] = a[i][11][:-3] #validation of time string
            if len(a[i][11]) < 5:
                a[i][11] = "0" + a[i][11]
            a[i][11] = datetime.strptime(a[i][11], '%H:%M').time() #turn into datetime object
            #print(a[i][11])
            nowTime = datetime.now().strftime('%H:%M') #get current time
            nowTime = datetime.strptime(nowTime, '%H:%M').time()
            #print(nowTime)
            if a[i][11] < nowTime or a[i][11] == nowTime or x < (10*3600) : #if alarm time = or exceeds current time call alarmTrig
                Window.alarmTrig(self)
            else:
                #print("NO")
                a[i][12] = datetime.combine(date.min, a[i][11]) - datetime.combine(date.min, nowTime)
                temp = str(a[i][12])
                print(temp)
                if len(temp) > 7: # gets time left in seconds
                    temp2 = temp[4:6]
                    temp = temp[:2]
                    a[i][13] = (int(temp) *3600) + (int(temp2) *60)
                    print(a[i][13])

                else:
                    temp2 = temp[2:4]
                    temp = temp[:1]
                    a[i][13] = (int(temp) *3600) + (int(temp2) *60)
                    print(a[i][13])
           # i=i+1
        else:
           # i=i+1
            print("not date")

    for i in range(n):   #finds smallest time
        if int(a[i][13]) < int(x):
            x=int(a[i][13])
            print(x)


    time.sleep(x/2) #make it wait half the time before recalc
    Window.alarmCalc



def alarmTrig(self):
    print("TRIG")
    winsound.PlaySound("*", winsound.SND_ALIAS)
    #Delete alarm

我有一个像这样实现public protocol UseCase { associatedtype ResponseType associatedtype Parameters func build(params: Parameters) -> Single<ResponseType> } public extension UseCase { func execute(params: Parameters) -> Single<ResponseType> { return build(params: params) .subscribeOn(ConcurrentDispatchQueueScheduler(qos: DispatchQoS.background)) .observeOn(MainScheduler.instance) } } 协议的结构

UseCase

我希望在另一个课程中使用此public struct CreateNewAccount: UseCase { private let repository: AuthRepository public init(repository: AuthRepository) { self.repository = repository } public func build(params: Params) -> Single<User> { return repository.register(params: params) } public struct Params: RequestParams { ... } } ,但我不想直接使用CreateNewAccount而我希望将其作为CreateNewAccount传递,因为因为它是一个协议它可以很容易地模拟测试。 但是当我做这样的事情时

UseCase

这给了我一个像这样的错误

class RegisterViewModel: ViewModel {

    private let createNewAccount: UseCase // Error on this line

    init(createNewAccount: UseCase) { // Error on this line
        self.createNewAccount = createNewAccount
    }
}

那么,是否有一些我可以从我的代码中更改以使这种情况有效的东西?提前谢谢。

1 个答案:

答案 0 :(得分:1)

您不能将具有关联类型的协议用作字段。

您必须仅将它们用作类的实现。在大多数情况下,这些类应该是通用的。

例如,允许使用此代码:

require'
/Users/xxx/xxx/Rakefile:4:in

等等,

<top (required)>' /Users/xxx/.rbenv/versions/2.3.1/bin/bundle:23:in

或用其他协议以某种方式包装它。