Форум программистов, компьютерный форум, киберфорум
Наши страницы
Swift
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/3: Рейтинг темы: голосов - 3, средняя оценка - 5.00
ExFau$t
638 / 538 / 122
Регистрация: 08.05.2012
Сообщений: 2,701
1

Progress dialog

15.08.2017, 16:45. Просмотров 587. Ответов 5
Метки нет (Все метки)

Добрый день.
Загружаю адресный справочник через Alamofire и потом его в CoreData засовываю, всё нормально, в процессе отображается модальное окошко с бесконечным прогрессом. Нужно сделать прогресс, типо загружается один район, прогресс доходит до конца, обнуляется, затем другой район и т.д. Все вьюхи сделал и описал, сами по себе работают, но вот в процессе загрузки/сохранения никак не могу заставить прогресс изменяться. Он принимает начальное значение и очень очень редко, когда внезапно обновится, а так стоит на месте. В логе прогресс бегает, как надо. Пробовал вынести операции в разные потоки, взял парочку примеров с github, но без успеха. Как это вообще делается правильно?
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.08.2017, 16:45
Ответы с готовыми решениями:

Progress Button, как вызвать метод, а после закончить Progress?
Есть кнопка с прогрессом, по ее клику вызывается это: private void...

Progress bar
как сделать так, чтобы при нажатии кнопки(загружающая в memo текст) она...

Gauge1.Progress
как при определенном количестве нажатий на кнопку постепенно увеличивать...

Progress Bar
Вот. Нашел способ как сделать прогресс бар. Думаю будет интересно. ...

progress bar
Написала код для простенького web браузера вот код brouser.h #ifndef...

5
Митя800
66 / 66 / 19
Регистрация: 13.07.2015
Сообщений: 219
15.08.2017, 22:48 2
По описанию сложно сразу понять что происходит не так. У Вас каким образом происходит запрос к серверу?
Через один вызов метода из Alamofire или сразу вызываете несколько?
Здесь стоит учесть, что все вызовы методов Alamofire не будут выполняться по очереди. Может быть найдете ответ тут https://stackoverflow.com/a/34939274
А лучше уточните свой вопрос тем как у вас происходит запрос и подкрепите тему частями исходного кода.
0
ExFau$t
638 / 538 / 122
Регистрация: 08.05.2012
Сообщений: 2,701
16.08.2017, 12:47  [ТС] 3
Митя800, Если коротко, то так: идёт запрос по региону, получили в нём список районов, потом запрос по всем этим районам для получения улиц, потом также улицы, затем сам адрес, три этапа вложенности запросов. Да, они идут асинхронно, меня интересует не порядок, а кол-во выполненной работы, о котором я сужу, зная размер массива. В целом по работе с сетью нет проблем, она отрабатывает на порядок быстрее записи в БД, которая по пока неизвестным причинам происходит очень долго, это наверное вопрос в новую тему.
В перерывах можно же как-то обновить прогресс в UI.
Теперь немного кода, чтобы прояснить немного (копировал через iCloud, и форматирование ушло):
Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
​
Alamofire.request(url+token).responseJSON{ response in
if (response.error == nil){
let jsonData: Data = response.data!
do{
if let jsonResult = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String:AnyObject] {
if (jsonResult["Status"] as! Int==0){
let liquidLocations = jsonResult["Regions"] as? [[String: Any]]
for i in stride(from: 0, to: (liquidLocations?.count)!, by: 1){
let RegionName: String = (liquidLocations![i]["RegionName"] as! NSString) as String
let regions = Regions(context: context)
regions.name = RegionName
CoreDataManager.instance.saveContext(context: context)
Alamofire.request(url+token+"&RegionId="+String((liquidLocations![i]["Id"] as! NSNumber) as! Int)).responseJSON{ response in
if (response.error == nil){
//дальше по аналогии
}
}
}
Добавлено через 8 минут
То есть требуется вот что, применительно к коду выше, во втором запросе мы получим районы, один район загрузился, записался - мы увеличили прогресс и отобразили этот прогресс пользователю, чтобы он видел, сколько районов и какие на данный момент загружены уже. Само окошко я сделал разными способами, задаётся какой-нибудь самый первый район, прогресс 0.1 и всё, до конца процесса стоит на месте, хотя в консоли я этот прогресс вижу, как он доходит до 1.
0
ExFau$t
638 / 538 / 122
Регистрация: 08.05.2012
Сообщений: 2,701
17.08.2017, 12:43  [ТС] 4
Подозреваю, дело в записи в БД, которая происходит в основном потоке. Сама по себе эта запись длится очень долго, что наводит на мысль о неверной реализации.

Objective-C
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
//
//  CoreDataManager.swift
//
//
 
import CoreData
import Foundation
 
class CoreDataManager {
    
    static let instance = CoreDataManager()
    
    private init() {}
    
    @available(iOS 10.0, *)
    lazy var persistentContainer: NSPersistentContainer = {
        
        let container = NSPersistentContainer(name: "Addresses")
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error {
                
                fatalError("Unresolved error \(error)")
            }
        })
        return container
    }()
    
    func getContext () -> NSManagedObjectContext {
        var context: NSManagedObjectContext?
        
        if #available(iOS 10.0, *) {
            context = persistentContainer.viewContext
        } else {
            guard let modelURL = Bundle.main.url(forResource: "Addresses", withExtension:"momd") else {
                fatalError("Error loading model from bundle")
            }
            guard let mom = NSManagedObjectModel(contentsOf: modelURL) else {
                fatalError("Error initializing mom from: \(modelURL)")
            }
            let psc = NSPersistentStoreCoordinator(managedObjectModel: mom)
            let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
            let docURL = urls[urls.endIndex-1]
            let storeURL = docURL.appendingPathComponent("Addresses.sqlite")
            do {
                try psc.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: nil)
            } catch {
                fatalError("Error migrating store: \(error)")
            }
            context = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
            context?.persistentStoreCoordinator = psc
        }
        return context!
    }
    
    func saveContext(context: NSManagedObjectContext){
        if (context.hasChanges){
            do {
                try context.save()
                //print("saved!")
            } catch let error as NSError  {
                print("Could not save \(error), \(error.userInfo)")
            } catch {
                
            }
        }
    }
    
    
}
Эти классы отличаются только EntityName:
Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//
//  Regions+CoreDataClass.swift
//
//
 
import Foundation
import CoreData
 
 
public class Regions: NSManagedObject {
    convenience init(context:NSManagedObjectContext) {
        let entity = NSEntityDescription.entity(forEntityName: "Regions", in: context)
        
        self.init(entity: entity!, insertInto: context)
    }
}
0
Миниатюры
Progress dialog  
ExFau$t
638 / 538 / 122
Регистрация: 08.05.2012
Сообщений: 2,701
17.08.2017, 12:47  [ТС] 5
Самая трудоемкая операция - добавление в БД по конкретному региону/району/улице - адреса, здесь необходимо также добавлять связи. Улицы и адреса лежат вместе в одном json, поэтому, чтобы не дублировать улицы, я проверяю их наличие сначала. Весь код метода (код так себе, не будем об этом):

Добавлено через 1 минуту
Objective-C
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
        let context = CoreDataManager.instance.getContext()
        let token: String = defaults.string(forKey: "token")!
        //let concurrentQueue = DispatchQueue(label: "queuename", attributes: .concurrent)
        Alamofire.request(url+token).responseJSON{ response in
            if (response.error == nil){
                let jsonData: Data = response.data!
                do{
                    if let jsonResult = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String:AnyObject] {
                        if (jsonResult["Status"] as! Int==0){
                            let nomRegions = jsonResult["Regions"] as? [[String: Any]]
                            for i in stride(from: 0, to: (nomRegions?.count)!, by: 1){
                                let RegionName: String = (nomRegions![i]["RegionName"] as! NSString) as String
                                let regions = Regions(context: context)
                                var countDists:Int = 0
                                regions.name = RegionName
                                Alamofire.request(url+token+"&RegionId="+String((nomRegions![i]["Id"] as! NSNumber) as! Int)).responseJSON{ response in
                                    if (response.error == nil){
                                        let jsonData: Data = response.data!
                                        do{
                                            if let jsonResult = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String:AnyObject] {
                                                if (jsonResult["Status"] as! Int==0){
                                                    let nomDistrics = jsonResult["districts"] as? [[String: Any]]
                                                    let modalViewController = ViewControllerShowProgressLong()
                                                    modalViewController.modalPresentationStyle = .overCurrentContext
                                                    let labelText: UILabel = modalViewController.view.viewWithTag(1) as! UILabel
                                                    labelText.text = "Округ: ХХХ\nРайон: ХХХ"
                                                    let labelPercent: UILabel = modalViewController.view.viewWithTag(3) as! UILabel
                                                    let progress: UIProgressView = modalViewController.view.viewWithTag(2) as! UIProgressView
                                                    progress.setProgress(0, animated: true)
                                                    self.dismiss(animated: true){
                                                        self.present(modalViewController, animated: true, completion: nil)
                                                    }
                                                    //let progressDialog = ProgressDialog()
                                                    //progressDialog.presentFromView(view: self.view)
                                                    countDists = countDists + (nomDistrics?.count)!
                                                    var count:Int = 0
                                                    for j in stride(from: 0, to: (nomDistrics?.count)!, by: 1){
                                                        let DistName: String = (nomDistrics![j]["DistrictName"] as! NSString) as String
                                                        let districts = Districts(context: context)
                                                        districts.name = DistName
                                                        regions.addToRegToDist(districts)
                                                        Alamofire.request(url+token+"&districtid="+String((nomDistrics![j]["Id"] as! NSNumber) as! Int)).responseJSON{ response in
                                                            if (response.error == nil){
                                                                let jsonData: Data = response.data!
                                                                do{
                                                                    if let jsonResult = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String:AnyObject] {
                                                                        if (jsonResult["Status"] as! Int==0){
                                                                            print(Float(count)/Float(countDists))
                                                                            if(count != 0){
                                                                                labelText.text = "Округ: " + RegionName + "\nРайон: "+DistName
                                                                                progress.setProgress(Float(count)/Float(countDists), animated: true)
                                                                                labelPercent.text = String(Float(count)/Float(countDists)*100)+"%"
                                                                            }
                                                                            count = count + 1
                                                                            let nomStreets = jsonResult["Addresses"] as? [[String: Any]]
                                                                            for k in stride(from: 0, to: (nomStreets?.count)!, by: 1){
                                                                                labelText.text = DistName + " " + String(k)
                                                                                let billbObj = nomStreets![k]["Billboards"] as? [[String: Any]]
                                                                                if (billbObj?.count != 0){
                                                                                    let Name: String = (nomStreets![k]["Street"] as! NSString) as String
                                                                                    let fetchRequest: NSFetchRequest<Streets> = Streets.fetchRequest()
                                                                                    let predicate = NSPredicate(format: "name == %@ && strToDist.name == %@",Name, DistName)
                                                                                    fetchRequest.predicate = predicate
                                                                                    do {
                                                                                        let searchResults = try context.fetch(fetchRequest)
                                                                                        if (searchResults.count == 0){
                                                                                            let streeets = Streets(context: context)
                                                                                            streeets.name = Name
                                                                                            districts.addToDistToStr(streeets)
                                                                                            for z in stride(from: 0, to: (billbObj?.count)!, by: 1){
                                                                                                let addresses = Addresses(context: context)
                                                                                                addresses.house = nomStreets![k]["House"] as! String?
                                                                                                addresses.build = nomStreets![k]["Building"] as! String?
                                                                                                ...
                                                                                                streeets.addToStrToAddresses(addresses)
                                                                                                districts.addToDistToStr(streeets)
                                                                                            }
                                                                                        }else{
                                                                                            for result1 in searchResults {
                                                                                                for z in stride(from: 0, to: (billbObj?.count)!, by: 1){
                                                                                                    let addresses = Addresses(context: context)
                                                                                                    addresses.house = nomStreets![k]["House"] as! String?
                                                                                                    addresses.build = nomStreets![k]["Building"] as! String?
                                                                                                    ...
                                                                                                    result1.addToStrToAddresses(addresses)
                                                                                                    districts.addToDistToStr(result1)
                                                                                                }
                                                                                            }
                                                                                        }
                                                                                    } catch {
                                                                                        print("Error with request: \(error)")
                                                                                    }
                                                                                }
                                                                            }
                                                                            if (i == (nomRegions?.count)! - 1  && j == (nomDistrics?.count)! - 1){
                                                                                CoreDataManager.instance.saveContext(context: context)
                                                                                UIApplication.shared.isIdleTimerDisabled = false
                                                                                let defaults = UserDefaults.standard
                                                                                defaults.set(0, forKey: "NomPhotoDone")
                                                                                defaults.set(true, forKey: "isShowSend")
                                                                                defaults.set("Date", forKey: "sortType")
                                                                                defaults.synchronize()
                                                                                self.isSuccess = true
                                                                                self.dismiss(animated: true){
                                                                                    let vc = self.createMenu()
                                                                                    self.present(vc, animated: true, completion: nil)
                                                                                }
                                                                            }
                                                                        }
                                                                    }
                                                                }catch{
                                                                    
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }catch{
                                            
                                        }
                                    }
                                    
                                }
                            }
                        }
                    }
                }catch{
                    
                }
            }
            
        }
Добавлено через 33 секунды
Буду признателен за любую помощь.
0
ExFau$t
638 / 538 / 122
Регистрация: 08.05.2012
Сообщений: 2,701
29.08.2017, 14:10  [ТС] 6
Короче, если кто вдруг следит за моими успехами, разрулил так:
Убрал проверку наличия улиц совсем, выиграл немного времени, проиграл место в базе, приходится на выводе проверять и выводить только одну из множества, терпимо.
Исходя из предыдущего пункта, теперь потоки не связаны никак и можно распихать их по фоновым потокам.
Objective-C
1
.responseJSON(queue: queue)
Контекст тоже вынес в фоновый поток.
С прогрессом пришлось повозиться, но суть в том, что раз потоки асинхронные, можно получить сначала все районы, посчитать их, а уже потом делать прогресс по всему кол-ву.
Работу с Alamofire вынес в синглтон, по непонятной причине так работает намного лучше.
Прогресс забегал, не совсем как хотелось, но уже лучше.
0
29.08.2017, 14:10
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.08.2017, 14:10

Progress Bar
Допустим, нужно сделать так чтобы после нажатия на кнопку, прогресс бар начинал...

Gauge1.Progress
Добрый вечер хотелать спросить как можно сдела Gauge1.Progress не + 1 а...

Progress bar
Я собственно совсем новичок в программировании, так что не ругайтесь строго....


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

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru