Форум программистов, компьютерный форум, киберфорум Python
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.93/29: Рейтинг темы: голосов - 29, средняя оценка - 4.93
420 / 357 / 47
Регистрация: 22.05.2013
Сообщений: 2,518

Аналог 1С

08.08.2014, 20:51. Показов 5759. Ответов 4
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Помогите новичку!

Надо написать не сложную программу для оффлайн хранения простых справочников и документов. И возможно простые отчеты по документам (в текст или html)... Без учета остатков, реестров, накоплений - просто факт записи (и табличной части)... На 1С(7.7) набросал бы подобное за час-полтора... Но хотелось бы сделать программу бесплатной (для скачивания с сайта).
Есть ли в яве инструменты для подобного? Фреймворки? Движки? Конструкторы?

Как базу в иделе бы использовать DBF или SQLite...

...подумал что должно быть. Учитывая сколько лет яве и что она используется в банковской и учетной сфере...
Понятно что логика будет на яве(а не 1С), но плодить документы/справочники с нуля, придумывать логику контроля зависимости полей не охота... Списки и формы документов... Ведь если бухгалтерия некого (иностранного) завода захочет еще одну таблицу справочника завести или документов с отдельным журналом, вряд-ли программисты будут копировать логику со старых документов, пререопределять десятки-сотни полей(включая стандартные), придумывать таблицы хранения, привязку к старым документам и справочникам... Привязывать к инструментам пересчета полей при сбое...

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

Насколько такую программу будет тяжело установить обычному пользователю? Самораспаковывающийся архив + "установите яву"? Инсталятор "все включено"?

1.5 года использую яву для андроида, надеялся что и перейти не тяжело будет. Да и при желании мультиплатформенной можно будет сделать...
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
08.08.2014, 20:51
Ответы с готовыми решениями:

Аналог Компрессора Данфосс FR-8.5A, Не могу найти аналог компрессора
Кто-нибудь подбирал аналог данного компрессора,он стоит на низкотемпиратурном ларе? Заранее спасибо!

Аналог Zilog 1883, Аналог Zilog 1883 Модуль EATON A1 D20
Подскажите плз есть ли аналог у Zilog 1883 cm20a (так написано на самой микросхеме)? Модулек EATON A1 D20. Или документацию какую на...

Аналог GET в js
<input type="hidden" name="qq" value = <?php echo $_GET?> /> Скрипту передается что типа такого script.php?q=1. Но в заголовке...

4
0 / 0 / 0
Регистрация: 07.08.2014
Сообщений: 4
08.08.2014, 22:02
Я когда-то сталкивался с похожей задачей.
В одном из подразделений было нужно нечто для документов, но с элементами ERP системы.
Перед этим приглядывался к LibreOffice и его макросам и был в курсе, что можно писать для него на Java. В общем, с Java+LibreOffice получился неплохой вариант, но довольно сложный.
После некоторых дополнительных поисков, я остановился на Python+LibreOffice. Решение такое же красивое и удобное, но при этом более простое.
Советую попробовать с базой SQLite (независимо Java или Python).
Что касается обычного пользователя: установка LibreOffice и копипаста скриптов (или установочный скрипт для всего этого).
Одинаково хорошо работает как под Windows так и под GNU\Linux. Если заинтересует, могу бросить на почту python-скрипт.
0
Почетный модератор
Эксперт по компьютерным сетямЭксперт Windows
 Аватар для magirus
28047 / 15783 / 983
Регистрация: 15.09.2009
Сообщений: 67,753
Записей в блоге: 78
08.08.2014, 22:28
Цитата Сообщение от vTin Посмотреть сообщение
могу бросить на почту python-скрипт.
можете разместить здесь, и тогда размеры благодарности (как минимум в моем лиТсе), не будут иметь размеров (в
пределах разумного)
0
420 / 357 / 47
Регистрация: 22.05.2013
Сообщений: 2,518
08.08.2014, 22:52  [ТС]
Цитата Сообщение от vTin Посмотреть сообщение
могу бросить на почту python-скрипт
Кидайте! tester64@rambler.ru
Попробую...

если честно, расчитывал на более простой вариант... Было время - на делфи написал некое подобие справочников-документов (на SQLite) - список с фильтрами, быстрый поиск, редактирование через диалоги... Отдельный файл для структуры всех справочников с рускоязычными полями. Редактирование через диалоги со встроенными процедурами проверок, заполнения полей при открытии, записи полей при закрытии, кнопка отказ от записи... Почти дописал... немного тормозило и были недоисправленные глюки... Вроде "Парус" (конкурент 1С) написан похожим образом на Делфи... Легко добавляют новые документы и справочники...

Сейчас пытаюсь нечто подобное написать под андроид. Там даже чуть проще... Можно формы наследовать от "образца" (в делфи сложнее было). Но тут АПИ от Гугла (гадкое и ни с кем не совместимое).

Надеялся что подобное уже есть под яву с окошками! Мультиплатформенное. Ведь люди годами над подобным работали... даже вроде (еще не пробовал, но много читал) придумали NoSQL базы с документо-ориентированостью. И не одиночки вроде меня, а целые корпорации... Неужели никто до сих пор не придумал опенсорс аналога 1С на основе явы - нужен учет в справочниках с возможностью править юзерами - берется фрейворк и за 3-4 часа "накидываются" формочки и формируется в конструкторе база... Ведь на яве все банки работают... Неужели они все свою зарплату в 1С считают?

Помню я подобное за месяц на FoxPro создавал... Потом за ночь на 1С переписал(при нулевом знании 1С - по учебнику)... около 20 справочников было со сложной структурой.

Сейчас за полчаса "накидал" общую схему связанных справочников в 1С... Получилось около 6-7 справочников даже без документов. Но выложить бесплатную версию на сайт не могу - нужен "запускатель от 1С", а он стоит денег. И не малых (на каждый комп).

Добавлено через 8 минут
p.s. подобное встроено в большинство веб-движков. На друпале поблема не создать справочник, а красиво его вывести табличками и что-бы картинки не тормозили... А создание справочников (там они как-то по другому называются) там давно встроено. Вместе с дизайнером элементов... И необычными обработками реакций на PHP, если автору не нравятся стандартные...
0
0 / 0 / 0
Регистрация: 07.08.2014
Сообщений: 4
09.08.2014, 17:14
можно конечно и здесь, хотя самолюбие требует для таких результатов статью в блоге

В наличии python скрипт для формирования нестандартного печатного документа штатного расписания и скрипт, который очень помог в разработке и упростил понимание python под LibreOffice (у LibreOffice свой собственный отдельный python, в последних версиях 3.3, и свои особенности запуска скриптов-макросов).
Проект выглядит так: в 1С храняться сведения (тут можно использовать SQLite), включаем шаблон LibreOffice, запускаем python-скрипт-макрос, PySide(Qt) диалог с параметрами, подтверждаем - получаем готовый отчет.
Ниже скрипт, который представляется как макрос в LibreOffice и формирует документ
Python Скопировано
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# -*- coding:utf-8 -*-
import sys
print(sys.path)
 
import os
import uno
from PySide import QtGui
from PySide import QtCore, QtUiTools
 
 
class ShtatScheduleFormater:
    ####### for   development ################
    @staticmethod
    def initXSC():
        if not 'XSCRIPTCONTEXT' in globals():
            from devDocInit import SScheduleXContext
            global XSCRIPTCONTEXT
            XSCRIPTCONTEXT = SScheduleXContext().XSCRIPTCONTEXT
    ##########################################
 
    V82 = None
 
    class ParametersDialog:
        def __init__(self, formater):
            self.app = QtGui.QApplication([''])
            file = QtCore.QFile(formater.localPath + formater.uiFilePath)
            file.open(QtCore.QFile.ReadOnly)
            self.widget = QtUiTools.QUiLoader().load(file)
            file.close()
            self.widget.DepComboBox.addItem('')
            self.widget.KategoryComboBox.addItem('')
            self.widget.FinancComboBox.addItem('')
            qDeps = 'SELECT DP.Наименование Name FROM Catalog.ПодразделенияОрганизаций DP WHERE DP.DeletionMark = false ORDER BY Name'
            depsQuery = formater.V82.NewObject("Query", qDeps)
            depsSels = depsQuery.Execute().Choose()
            while depsSels.next():
                self.widget.DepComboBox.addItem(depsSels.Name)
            qKats = 'SELECT KT.Наименование Name FROM Catalog.КатегорииДолжностейПерсонала KT WHERE KT.DeletionMark = false ORDER BY KT.Наименование'
            katsQuery = formater.V82.NewObject("Query", qKats)
            katsSels = katsQuery.Execute().Choose()
            while katsSels.next():
                self.widget.KategoryComboBox.addItem(katsSels.Name)
            qFins = 'SELECT FT.Наименование Name FROM Catalog.СтатьиФинансирования FT WHERE FT.DeletionMark = false ORDER BY FT.Наименование'
            finsQuery = formater.V82.NewObject("Query", qFins)
            finsSels = finsQuery.Execute().Choose()
            while finsSels.next():
                self.widget.FinancComboBox.addItem(finsSels.Name)
 
        def exec_(self):
            return self.widget.exec_()
 
    def getData(self):
        parmDialog = ShtatScheduleFormater.ParametersDialog(self)
        pDialWidget = parmDialog.widget
        if not pDialWidget.exec_():
            QtCore.QCoreApplication.exit()
            raise Exception('close dialog')
            sys.exit(0)
        PersonalYearFrame = self.doc.TextFrames.getByName('PersonalYearFrame')
        PersonalYearFrame.getText().insertString(PersonalYearFrame.getStart(),\
                           '%s \r\n %s'%(pDialWidget.KategoryComboBox.currentText(), pDialWidget.DepComboBox.currentText()), 0)
 
        FinanceTable = self.doc.TextTables.getByName('FinanceTable')
        FinanceTable.getCellByName('A1').String = pDialWidget.FinancComboBox.currentText()
 
        q = '''
            SELECT  ШР.ПодразделениеОрганизации.Наименование dep,
                    ШР.Должность.Наименование posit,
                    ШР.КоличествоСтавок cnt,
                    ШР.МесячнаяСтавка base,
                    ISNULL(НадбавкиПоШтату.Показатель, 0)/100 + 1 k,
                    "=<D{0}>*<E{0}>" sm,
                    "=<F{0}>*<C{0}>" ttlSm
              FROM РегистрСведений.ШтатноеРасписаниеОрганизаций.СрезПоследних КАК ШР
              LEFT OUTER JOIN (
                      SELECT  НадбавкиПоШтату.ПодразделениеОрганизации,
                              НадбавкиПоШтату.Должность,
                              СУММА(НадбавкиПоШтату.Показатель1) Показатель
                         FROM РегистрСведений.НадбавкиПоШтатномуРасписаниюОрганизаций.СрезПоследних КАК НадбавкиПоШтату
                        WHERE НадбавкиПоШтату.ВидНадбавки.Код = "00109"
                          GROUP BY
                              НадбавкиПоШтату.ПодразделениеОрганизации,
                              НадбавкиПоШтату.Должность
                      ) КАК НадбавкиПоШтату
                        ПО ШР.ПодразделениеОрганизации = НадбавкиПоШтату.ПодразделениеОрганизации
                            И НадбавкиПоШтату.Должность = ШР.Должность
                WHERE (ШР.ПодразделениеОрганизации.Наименование = "{1}" OR "{1}" = "")
                  AND (ШР.Должность.КатегорияПерсонала.Наименование = "{2}" OR "{2}" = "")
                  AND (ШР.СтатьяФинансированияФорма14.Наименование = "{3}" OR "{3}" = "")
                ORDER BY
                      ШР.ПодразделениеОрганизации.Наименование,
                      ШР.Должность.Наименование
            '''.format('{0}', pDialWidget.DepComboBox.currentText()
                            , pDialWidget.KategoryComboBox.currentText()
                            , pDialWidget.FinancComboBox.currentText() )
        query = self.V82.NewObject("Query", q)
        return query.Execute().Choose()
 
    def fetch(self):
        from com.sun.star.beans import PropertyValue
        mainTable = self.doc.TextTables.getByName('MainTable')
        sels = self.getData()
        controller = self.doc.getCurrentController()
        frame = self.doc.getCurrentController().Frame
        frame.activate()
        dispatcher = XSCRIPTCONTEXT.ctx.ServiceManager.createInstance('com.sun.star.frame.DispatchHelper')
 
        lastDep = None
        i = 1  # string number
        n_n = 0
        while sels.Next():
            if not sels.__getattr__('dep') == lastDep:
                if not lastDep is None:
                    mainTable.getRows().insertByIndex(i, 1)
                    i+=1
                    mainTable.getCellByName('%s%d'%(self.clmns['posit'],i)).String = 'ИТОГО'
                    mainTable.getCellByName('%s%d'%(self.clmns['ttlSm'],i)).Formula = \
                        '=sum(<{0}{1}:{0}{2}>)'.format(self.clmns['ttlSm'], i-n_n, i-1)
                    mainTable.getCellByName('%s%d'%(self.clmns['cnt'],i)).Formula = \
                        '=sum(<{0}{1}:{0}{2}>)'.format(self.clmns['cnt'], i-n_n, i-1)
                mainTable.getRows().insertByIndex(i, 1)
                i+=1
                lastDep = sels.__getattr__('dep')
                controller.select(mainTable.getCellRangeByName('%s%d:%s%d'%(self.fColumn,i,self.lColumn,i)))
                prop = (PropertyValue(),)
                dispatcher.executeDispatch(frame, ".uno:MergeCells", "", 0, ())
                prop[0].Name = 'Bold'
                prop[0].Value = True
                controller.select(mainTable.getCellByName('%s%d'%(self.fColumn,i)))
                dispatcher.executeDispatch(frame, ".uno:Bold", "", 0, prop)
                prop[0].Name = "CenterPara"
                prop[0].Value = True
                controller.select(mainTable.getCellByName('%s%d'%(self.fColumn,i)))
                dispatcher.executeDispatch(frame, ".uno:CenterPara", "", 0, prop)
                mainTable.getCellByName('%s%d'%(self.fColumn,i)).String = sels.__getattr__('dep')
                n_n = 0
            mainTable.getRows().insertByIndex(i, 1)
            i+=1;     n_n+=1
            for clm in self.clmns:
                if clm in ['sm','ttlSm']:
                    mainTable.getCellByName('%s%d'%(self.clmns[clm],i)).Formula = sels.__getattr__(clm).format(i)
                elif clm == 'num':
                    mainTable.getCellByName('%s%d'%(self.clmns[clm],i)).Value = n_n
                elif clm in ['cnt', 'base', 'k']:
                    mainTable.getCellByName('%s%d'%(self.clmns[clm],i)).Value = sels.__getattr__(clm)
                else:
                    mainTable.getCellByName('%s%d'%(self.clmns[clm],i)).String = sels.__getattr__(clm)
        i+=1
        mainTable.getCellByName('%s%d'%(self.clmns['posit'],i)).String = 'ИТОГО'
        mainTable.getCellByName('%s%d'%(self.clmns['ttlSm'],i)).Formula = \
            '=sum(<{0}{1}:{0}{2}>)'.format(self.clmns['ttlSm'], i-n_n, i-1)
        mainTable.getCellByName('%s%d'%(self.clmns['cnt'],i)).Formula = \
            '=sum(<{0}{1}:{0}{2}>)'.format(self.clmns['cnt'], i-n_n, i-1)
        del self.V82
 
    def __init__(self, *args):
        import win32com.client
        import pythoncom
        ShtatScheduleFormater.initXSC()
        pythoncom.CoInitialize()
        self.localPath       = 'C:\\Program Files (x86)\\LibreOffice 4\\share\\Scripts\\python\\shtatSchedule\\'
        self.uiFilePath      = 'ShtatSchedule.ui'
        self.V82_CONN_STRING = 'File="C:\\1cbackup\\BudgetHRM_copy";Ref=v8_db;'
        self.V82             = win32com.client.Dispatch("V82.COMConnector").Connect(self.V82_CONN_STRING)
        self.clmns           = {'num':'A', 'posit':'B', 'cnt':'C', 'base':'D', 'k':'E', 'sm':'F', 'ttlSm':'G'}
        self.fColumn         = 'A'
        self.lColumn         = 'G'
        self.doc             = XSCRIPTCONTEXT.getDocument()
        sys.path.append(self.localPath)
        try:
            self.fetch()
        except:
            del self.V82
 
def getShtatSchedule(*args):
    ShtatScheduleFormater(*args)
 
if __name__ == '__main__':
    getShtatSchedule()
Особенности:
* ShtatScheduleFormater - класс-менеджер для формирования отчета, но для запуска макроса обязательно нужен метод, подобный getShtatSchedule в корне модуля, иначе скрипт не запуститься
Python Скопировано
1
2
def getShtatSchedule(*args):
    ShtatScheduleFormater(*args)
* LibreOffice python не включает в PATH директорию запущенного скрипта, т.к. отчет небольшой, я добавил путь в явном виде
Python Скопировано
1
2
self.localPath       = 'C:\\Program Files (x86)\\LibreOffice 4\\share\\Scripts\\python\\shtatSchedule\\'
sys.path.append(self.localPath)
* fetch - метод сборки отчета (наименование запомнилось после ERP Axapta)
* getData - забирает данные из 1С
* ParametersDialog - класс qt-диалога с параметрами
* Очень важно для дебага и для интерактивной работы с python: метод initXSC
если вы запускаете отчет в режиме дебага, то переменной окружения XSCRIPTCONTEXT не существует, её нужно создавать или как-то выкручиваться без неё.
На этот случай был написан вот такой скрипт
Python Скопировано
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# -*- coding:utf-8 -*-
import os
import sys
import uno
import socket
 
class XCont:
    def __init__(self, ctx, doc, inv):
        self.ctx = ctx;        self.doc = doc;        self.inv = inv
    def getDocument(self):        return self.doc
 
class SScheduleXContext( ):
    def __init__(self):
        ctx = uno.getComponentContext()
        resolver = ctx.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", ctx)
        smgr = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ServiceManager")
        desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", ctx)
        doc = desktop.loadComponentFromURL('file:///c:/Program Files (x86)/LibreOffice 4/share/Scripts/python/shtatSchedule/ShtatSchedule.ott',"_blank", 0, () )
        self.XSCRIPTCONTEXT = XCont(ctx,doc,0)
Запускается LibreOffice на подключение в режиме дебага
Bash Скопировано
1
soffice "-accept=socket,host=localhost,port=2002;urp;StarOffice.NamingService"
Далее в интерпретаторе запускается скрипт с вашим макросом, в данном случае вызывается метод getShtatSchedule()

Были и другие реализации похожих задач. Что касается стороны GNU - с неми проблем было меньше всего, сложнее как всегда с тайным и загадочным 1С.
В Вашем случае можно воспользоваться SQLite+Python+LibreOffice+Qt. Для ORM можно использовать sqlalchemy. Что касается такой фишки как Grid - тут немного сложнее, но как вариант делать так: список выводиться в сам LibreOffice Calc, а новые элементы, редактирование и удаление по дополнительным кнопкам на панельке. Повезёт, если найдёте готовый вариант визуального редактирования строк таблиц.
Важное замечание, как любителю Java: если будете использовать Python в первую очередь начните с интерактивного режима/дебага. Написали, пол проекта запустили, что-то выполнилось, следующие команды пишите "не отходя от кассы" - прямо внутри работающего приложения, пусть выполняет - вы сразу посмотрите на результат. Такой подход очень помогает при работе с LibreOffice, да и вообще с любыми задачами на python.
Ну и наконец GNU\Emacs Юзаю и Всем рекомендую Очень удобный редактор (+Evil mode)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
09.08.2014, 17:14
Помогаю со студенческими работами здесь

Аналог L
Аналог L&quot;строка&quot; для переменных есть? Или как использовать для переменной?

Аналог Like
всем привет, подскажите, как мне искать в документе необходимые слова в поле Код (Delphi): search = &quot;Form=&quot;KR&quot; &amp;...

Аналог на С++
есть на шарпе следующий код public Bitmap ImageFromScreen() { Bitmap bmp = new...

Аналог WHERE . IN (.)
Здравствуйте. Есть массив со значениями типа &quot;xkd 251-1&quot; Нужно обновить те поля таблицы, которые совпадают со значениями массива. Если...

Аналог БД
Доброго дня. Есть тьма Excel-евских файлов. Информацию из них нужно помещать в некое хранилище и потом из этого хранилища получать...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
sshd restrictions, ssh access limitations
jigi33 26.03.2025
sshd restrictions | ssh access limitations рестрикции доступа на сервер sshd статья: https:/ / www. golinuxcloud. com/ restrict-allow-ssh-certain-users-groups-rhel
Компиляция C++ с Clang API
NullReferenced 24.03.2025
Компиляторы обычно воспринимаются как черные ящики, которые превращают исходный код в исполняемые файлы. Мы запускаем компилятор командой в терминале, и вуаля — получаем бинарник. Но что если нужно. . .
Многопоточное программировани­е в C#: Класс Thread
UnmanagedCoder 24.03.2025
Когда запускается приложение на компьютере, операционная система создаёт для него процесс - виртуальное адресное пространство. В C# этот процесс изначально получает один поток выполнения — главный. . .
SwiftUI Data Flow: Передача данных между представлениями
mobDevWorks 23.03.2025
При первом знакомстве со SwiftUI кажется, что фреймворк предлагает избыточное количество механизмов для передачи данных: @State, @Binding, @StateObject, @ObservedObject, @EnvironmentObject и другие. . . .
Моки в Java: Сравниваем Mockito, EasyMock, JMockit
Javaican 23.03.2025
Как протестировать класс, который зависит от других сложных компонентов, таких как базы данных, веб-сервисы или другие классы, с которыми и так непросто работать в тестовом окружении? Для этого и. . .
Архитектурные паттерны микросервисов: ТОП-10 шаблонов
ArchitectMsa 22.03.2025
Популярность микросервисной архитектуры объясняется множеством важных преимуществ. К примеру, она позволяет командам разработчиков работать независимо друг от друга, используя различные технологии и. . .
Оптимизация рендеринга в Unity: Сортировка миллиона спрайтов
GameUnited 22.03.2025
Помните, когда наличие сотни спрайтов в игре приводило к существенному падению производительности? Время таких ограничений уходит в прошлое. Сегодня геймдев сталкивается с задачами совершенно иного. . .
Образование и практика
Igor3D 21.03.2025
Добрый день А вот каково качество/ эффективность ВУЗовского образования? Аналитическая геометрия изучается в первом семестре и считается довольно легким курсом, что вполне справедливо. Ну хорошо,. . .
Lazarus. Таблица с объединением ячеек.
Massaraksh7 21.03.2025
Понадобилась представление на экране таблицы с объединёнными ячейками. И не одной, а штук триста, и все разные. На Delphi я использовал для этих целей TStringGrid, и то, кривовато получалось. А в. . .
Async/await в Swift: Асинхронное программировани­е в iOS
mobDevWorks 20.03.2025
Асинхронное программирование долго было одной из самых сложных задач для разработчиков iOS. В течение многих лет мы сражались с замыканиями, диспетчеризацией очередей и обратными вызовами, чтобы. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru
Выделить код Копировать код Сохранить код Нормальный размер Увеличенный размер