Страницы

Поиск по вопросам

Показаны сообщения с ярлыком swift. Показать все сообщения
Показаны сообщения с ярлыком swift. Показать все сообщения

четверг, 9 апреля 2020 г.

Как нарисовать рваную линию?

#ios #objective_c #swift

                    
Есть ли возможность, стандартная, а если и нет, то скажите, как можно нарисовать
рваную линию, похожу на баллончик, или рваную кисть, которая не полностью зарисовывает
область, а как бы оставляет след. Я реализовываю такую вот штуку. Заранее, спасибо
за помощь.

[Обновление] Задача упростилась, теперь просто нужно узнать как рисовать линию изображением.
    


Ответы

Ответ 1



Я так понимаю, единственный вариант это накладывать одно и то же изображение снова и снова, каждый раз, когда курсор смещается. В том примере, который у вас просто рисуется одно и то же изображение, именно так, как я описал в комментарии выше. просто изображение необычной формы и по краям, судя по всему есть полупрозрачные пиксели. если предположить, что у вас есть заднее изображение и переднее. то вам надо по клику в переднем изображении создавать прозрачный кусок установленной формы. вот пример с SO как это сделать // get access to the image bytes CFDataRef pixelData = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage)); // create a buffer to hold the mask values size_t width = CGImageGetWidth(image.CGImage); size_t height = CGImageGetHeight(image.CGImage); uint8_t *maskData = malloc(width * height); // iterate over the pixel data, reading the alpha value uint8_t *alpha = (uint8_t *)CFDataGetBytePtr(pixelData) + 3; uint8_t *mask = maskData; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { *mask = *alpha; mask++; alpha += 4; // skip to the next pixel } } // create the mask image from the buffer CGDataProviderRef maskProvider = CGDataProviderCreateWithData(NULL, maskData, width * height, NULL); CGImageRef maskImage = CGImageMaskCreate(width, height, 8, 8, width, maskProvider, NULL, false); // cleanup CFRelease(pixelData); CFRelease(maskProvider); free(maskData); Потом, чтобы все это запустить сделать: CGImageRef subtractedImage = CGImageCreateWithMask(b.CGImage, maskImage); Еще добавлю, что этот фокус скорее всего будет есть очень много ресурсов для большой картинки. может есть смысл поделить на несколько маленьких.

Ответ 2



Менее ресурсоемким решением было бы использование GLKit, работало бы быстро и на всех девайсах, но не на всех iOS, кажется начиная с iOS 7. С другой стороны, можно поиграться с CGPath, UIBezierPath, маской картинкой и получить "почти" тот же результат, ключевое слово почти :) UPD: Приведу пару ссылок Линк 1 Линк 2 Линк 3

воскресенье, 15 марта 2020 г.

Рассчитать размер прямоугольника с текстом

#ios #objective_c #swift


В делегате func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath:
NSIndexPath) -> CGFloat я должен высчитать высоту моего текста в UILabel. Какими путями
мне это сделать, скажите, пожалуйста?

upd1(к первому комментарию) :

    let text = self.posts[indexPath.row]["story"]! as NSString
    let sizeOfLabel = text.boundingRectWithSize(
        CGSize(width: <>, height: Int.min),
        options: NSStringDrawingOptions.UsesLineFragmentOrigin,
        attributes: ["NSFontAttributeName":UIFont.systemFontOfSize(17)],
        context: nil)

    


Ответы

Ответ 1



Если я правильно понял, то у Вас проблема с размером UILabel в UITableView. При создании вашей UILabel в методе UITableViewDataSource нужно указать yourLabel.layoutIfNeeded(). Если это не то, опишите проблему точнее

Ответ 2



extension UILabel { func calculateHeight() -> Float { let text = self.text as NSString let size = text.sizeWithAttributes([NSFontAttributeName: self.font]) return size.height } }

Ответ 3



То, что у вас в апдейте должно работать, единственноheight не минимальный а максимальный let sizeOfLabel = text.boundingRectWithSize( CGSize(width: <>, height: DBL_MAX), options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: ["NSFontAttributeName":UIFont.systemFontOfSize(17)], context: nil)

понедельник, 9 марта 2020 г.

Как работать с TCP в Swift?

#ios #swift #tcp_ip


У меня есть TCP сервер, который слушает входящие команды и общается с БД. Как мне
слать к нему запросы из ios приложения? Работаю со swift 2.

Другими словами, нужно реализовать следующее:
Пользователь вводит логин и пароль, пытается войти в свой аккаунт. В это время посылается
запрос на сервер - "Проверь, есть ли такой юзер в БД". Он это делает, и шлет ответ
обратно на ios приложение. 

Никак не могу понять, как мне такое реализовать. Насколько я понимаю, мне нужно работать
с потоками, но ничего путного про это на ios я не нашел.
    


Ответы

Ответ 1



Если я Вас правильно понял, то потоки Вам вовсе не нужны. Тут надо использовать блоки. Скажем Вы отправляете запрос и включаете индикатор загрузки, а когда приходит ответ Вы прекращаете загрузку и в зависимости от результата с сервера используете success или же failure блок. Советую использовать AFNetworking. Что-то на подобии let manager = AFHTTPRequestOperationManager() manager.GET( "http://myServerUrl.com", parameters: ["email":"myemail@gmail.com", "password":"1234Password"], success: { (operation: AFHTTPRequestOperation!, responseObject: AnyObject!) in //TODO - make login action }, failure: { (operation: AFHTTPRequestOperation!, error: NSError!) in // TODO - show error message } )

Ответ 2



На сколько я понимаю вам необходимо выполнить HTTP запрос авторизации пользователя к вашему серверу и получить какой то ответ. Для работы с сетью на Swift вам подойдет Alamofire. Самый простой пример выполнения GET запроса: Alamofire.request(.GET, "https://yourserver.org/get", parameters: ["name": "user", "pass": "12345"]) .responseJSON { response in print(response.result) // result of response serialization } Более подробные примеры запросов приведены в описании либы.

воскресенье, 8 марта 2020 г.

Как получать html документы из другого приложения?

#objective_c #xcode #swift


Во многих программах есть кнопка "Share", которая открывает список приложений, умеющих
обрабатывать этот тип файлов, например:



Я хочу, чтобы мое приложение могло обрабатывать html файлы.
Например пользователь нажимает кнопку "Share" в Google Chrome или в DropBox, а ссылка
передается моему приложению.
Где искать информацию?
    


Ответы

Ответ 1



Сначала в Info.plist прописываете: CFBundleDocumentTypes CFBundleTypeName HTML LSHandlerRank Alternate LSItemContentTypes public.html public.xhtml В AppDelegate: //Swift func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool { //do something with html file here return true } //Objective-C - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options { //do something with html file here return YES; } И передавайте: Чтобы получить url из Safari создайте App Extension: File -> New -> Target -> Share Extension Соглашаетесь создать схему, запускаете и видите: Схема как это работает: Подробнее в Документации Далее необходимо настроить. Для начала в - (BOOL)isContentValid { // Do validation of contentText and/or NSExtensionContext attachments here return YES; } Проверяете что Вам необходимо и если подходит, return YES; если что-то не то return NO;. Включить и настроить App Groups: И сохранять данные можно через NSUserDefaults: NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.test.one"]; [shared setObject:object forKey:@"yourkey"]; [shared synchronize]; Получить: NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.test.one"]; id value = [shared valueForKey:@"yourkey"]; NSLog(@"%@",value);

понедельник, 24 февраля 2020 г.

Проверка пароля при вводе в TextField

#ios #xcode #swift #apple


Подскажите пожалуйста, у меня есть TextField в который я ввожу пароль. После добавления
нового символа мне необходимо проверять соответствие пароля некоторым требованиям (например
8 символов). Как можно этого добиться?
Заранее спасибо)
    


Ответы

Ответ 1



Самый простой вариант: 1 2 Задаете тип Connection - Action, Type - UITextField, Event - Editing Changed. 3 Проверяете что необходимо. К примеру, длина введенного текста 8 и больше символов: @IBAction func myTfToCheck(_ sender: UITextField) { if let text = sender.text { let textLength = text.characters.count if textLength > 7 { //Do something print("\(text), length: \(textLength)") } } }

Ответ 2



Можно использовать готовый валидатор, этот TextFieldValidator для obj-c, но и под свифт аналогов тьма. Множество настроек, подсказки юзеру, проверка на совпадение паролей и тд.

Ответ 3



Вот ссылка, тут есть все что вам надо ) https://stackoverflow.com/questions/25223407/max-length-uitextfield Чуть не забыл, не забудьте прописать делегат в расширении класса - UITextFieldDelegate и указать этот делегат своему TextField yourTextField.delegate = self Пользуйся.

пятница, 14 февраля 2020 г.

Переход в настройки батареи Swift

#ios #swift


У меня есть приложение при запуске которого я проверяю включен ли у меня режим энергосбережения,
если да я вызываю Alert и предлагаю его выключить! Если пользователь соглашается то
я должен открывать настройки батареи.
Проверку на энергосбережение я сделал а открытие настроек батареи не получается,
подскажите пожалуйста
    


Ответы

Ответ 1



Начиная с iOS 11 разрешено открыть программно только настройки своего приложения. Плюс, если Вы все же сделаете это для прошлых версий (App-prefs:root=...), то с большой вероятностью приложение будет отклонено с формулировкой: Your app uses the "prefs:root=" non-public URL scheme Можете пользователю предложить перейти в нужный пункт меню настроек и показать инструкцию как именно.

Ответ 2



Targets -> Ваше приложение -> Info -> URL Types -> + В поле URL Schemes добавьте prefs Для вызова: UIApplication.shared.open(URL(string: "App-prefs:root=BATTERY_USAGE")!) Вот тут можете посмотреть доступные URL Schemes

суббота, 8 февраля 2020 г.

swift ios как запустить анимацию во время вычислений

#ios #swift #loading


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

У меня есть контроллер, в котором я ввожу данные, клацаю на кнопку и перехожу к другому
контроллеру, в котором производятся вычисления и выводятся на экран. Все вычисления
прописаны во viewDidLoad второго контроллера, и если введенное значение слишком большое,
то они занимают много времени. И все это время экран зависает на первом контроллере.

Я хочу сделать так, чтобы пока производятся вычисления на экране была гифка, но вышло
так, что сначала все считается, потом включается гифка и тут же переход. (subView я
пробовала добавлять и в функцию кнопки и в функцию ShouldPerformSegue)
    


Ответы

Ответ 1



В методе viewDidLoad вам нужно выполнять вычисления в бекграунд потоке, а пока все это вычисляется, показывать анимацию, и как только все вычисления будут закончены, в completion блоке останавливать анимацию.

Ответ 2



Как уже было сказано, вам надо выполнять код на отдельном потоке. Скорее всего в результате вычислений сделанных в отдельном потоке, вам надо будет делать апдейт информации на экране. Помните, что это обязательно делать на mainThread, то есть после вычислений вам надо указать в программе, что вы хотите выполнить какой то код в основном потоке. Приведу несколько примеров как это сделать: dispatch_async(dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) { () -> Void in //код, который надо выполнить асинхронно здесь dispatch_sync(dispatch_get_main_queue(), { () -> Void in //код, который должен выполниться в главном потоке }) } или override func viewDidLoad() { super.viewDidLoad() self.performSelectorInBackground(Selector("backgroundTask"), withObject: nil) } func backgroundTask () { //код, который надо выполнить асинхронно здесь self.performSelectorOnMainThread(Selector("anotherSelector"), withObject: nil, waitUntilDone: false) } или let opQueue: NSOperationQueue = NSOperationQueue() opQueue .addOperationWithBlock { () -> Void in //код, который надо выполнить асинхронно здесь NSOperationQueue.mainQueue() .addOperationWithBlock({ () -> Void in //код, который должен выполниться в главном потоке }) }

воскресенье, 2 февраля 2020 г.

Class или struct в Swift?

#swift #классы


Когда лучше использовать класс, а когда структуру в Swift?
    


Ответы

Ответ 1



Основное различие в том, что структуры передаются по значению, а классы — по ссылке. С точки зрения производительности важно, что экземпляры структур могут быть созданы в стеке, а экземпляры классов — только в куче. В соответствии с The Swift Programming Language: Структуры подходят, если выполняется одно или несколько условий: Инкапсуляция небольшого набора простых значений. Значения следует копировать, а не передавать по ссылке. Свойства самой структуры — value-типы, которые тоже передаются по значению. Структуры не наследует свойства или поведения. Хорошие примеры: Размеры фигуры: ширина и высота. Точка в пространства: x, y и z типа double. В большинстве случаев следует использовать классы.

Ответ 2



Предлагаю такие вопросы себе задавать: 1) Нужно ли мне наследование? 2) Нужно ли использовать классовые дженерики ('class SomeClass: ClassName')? 3) Нужно ли будет такое, чтобы инстанс объекта был доступен из нескольких мест и его можно было менять из них. (объект по ссылке, вместо копирования)? 4) Нужен ли деинициализатор? Если на все ответ нет, то используйте структуру.

среда, 29 января 2020 г.

Объяснение по fatal error: unexpectedly found nil while unwrapping an Optional value

#swift


На сегодняшний день у нас есть 6 практически одинаковых вопросов по сабжу. Давайте
один раз напишем полный ответ по этому вопросу и будем в будущем на него ссылаться.
Пока публикую под своим именем, если будут добавления/редактирования переставим на
сообщество.
    


Ответы

Ответ 1



Давайте один последний раз пройдемся по unexpectedly found nil while unwrapping an Optional value и больше никогда к нему не будем возвращаться. Когда вы создаете переменные инстанса, swift от вас хочет, чтобы вы либо сразу им присвоили значения по дефолту, либо инициализировали их в init. Во многих случаях это нам не подходит, тогда мы объявляем свои переменные как optional. var test:Int? // вопрос в конце, это объявление опциональной переменной Что значит Optional? Это значит, что вместо просто переменной, например Int, мы получаем инумерацию из двух значений: none и some(Wrapped). Вот это Wrapped и есть значение нашей переменной. Соответственно, если переменная не присвоена, то при попытке к ней обратиться, получим none т.е. nil. Если же она содержит значение мы получим Optional(value) Вот пример: var test:Int? print(test) // напечатает 'nil' test = 42 print(test) // напечатает 'Optional(42)' Далее, чтобы избавиться от этого Optional нам надо ее развернуть (unwrap), то есть сказать, что мы точно уверены, что там что то есть и мы хотим получить это самое что то. Другими словами, вместо Optional(value), получить value. Чтобы сделать принудительное разворачивание (forced unwrap) мы добавляем '!'. При этом, если переменная не присвоена, мы получим крэш - тот самый unexpectedly found nil while unwrapping an Optional value. Пример: var test:Int? print(test!) // крэш unexpectedly found nil и т.д. var test2:Int? test2 = 42 print(test2!) // напечатает 42 Дальше, если мы хотим создать переменную как Optional, но точно знаем, что в нее будет что-то присвоено до того, как мы ее будем читать первый раз, мы можем ее объявить как Implicitly Unwrapped Optional Type, посредством добавления '!' в объявлении. В этом случае, она опять же будет Optional, но система будет ее принудительно разворачивать (force unwrap) при любом обращении к ней. var test:Int! // '!' в конце, это обявление implicitly unwrapped optional print(test) // крэш unexpectedly found nil... var test2:Int! test2 = 42 print(test2) // напечатает 42 А что делать, если мы понятия не имеем есть там что то в этой optional или нет? var test:Int? if(test != nil) { print(test!) // развернутое значение } else { print(test) // nil } Либо другой способ, который создает временную переменную с развернутым значением var test:Int? if let unwrappedTest = test { print(unwrappedTest) } else { print("no value") } UPDATE: то же самое через guard var test:Int? guard let unwrappedTest = test else { print("No value") return // либо throw по ситуации } print(unwrappedTest) Ну и если вам надо force unwrapped превратить обратно в Optional: var test:Int! print(test as Optional) // напечатает nil Optional chaining: Есть еще такая ситуация, когда надо сделать цепочку вызовов, при этом где то в цепочке может содержаться опциональная перменная. Вот такой пример дает apple: Допустим есть класс Residence, и в нем есть переменная numberOfRooms; и есть класс Person, который имеет опциональную переменную типа Residence. Другими словами у человека может быть жилье, с каким то количеством комнат, а может и не быть жилья. То есть при попытке обратиться к человек-жилье-комнаты, мы можем наткнуться на nil вместо жилья. class Person { var residence: Residence? } class Residence { var numberOfRooms = 1 } Теперь мы хотим создать новый Person, и узнать сколько комнат в его жилище (при этом residence может быть nil поскольку он Optional). Для этого мы говорим системе, что мы хотим делать с опциональным значением - либо оставлять его опциональным ('?') со всеми вытекающими последствиями, в частности получить nil вместо количества комнат; либо принудительно его разворачивать, при этом имея риск получить fatal error. let john = Person() print(john.residence!.numberOfRooms) // крэш unexpectedly ... print(john.residence?.numberOfRooms) // напечатает nil let tom = Person() tom.residence = Residence() print(tom.residence!.numberOfRooms) // напечатает 1 print(tom.residence?.numberOfRooms) // напечатает Optional(1) Тут надо заметить, что хотя numberOfRooms не является опциональной, она в этой цепи становится таковой, поскольку цепь идет через опциональную residence?

вторник, 28 января 2020 г.

if else else else через тернарный оператор Swift

#swift #if #условия


Не могу вывести ниже изложенное выражение через тернарные операторы. Может кто-то
подскажет?

let child = 0    
let teenager = 12    
let youth = 16    
let adult = 25    
let mature = 40    
let elderly = 55    
let aged = 75    
let anton = 31    
var age: String    

if anton > aged {        
    age = "is aged"        
} else {        
    if anton > elderly {            
        age = "is elderly"            
    } else {            
        if anton > mature {                
            age = "is mature"                
        } else {                
            if anton > adult {                    
                age = "is adult"                    
            } else {                    
                if anton > youth {                        
                    age = "is youth"                        
                } else {                        
                    if anton > teenager {                            
                        age = "is a teenager"                            
                    } else {                            
                        if anton > child {                                
                            age = "is a child"                                
                        } else {                                
                            age = "was never born"                                
                        }                            
                    }                        
                }                    
            }                
        }            
    }
}
print("Anton \(age)")

    


Ответы

Ответ 1



не знаю зачем вам это let child = 0 let teenager = 12 let youth = 16 let adult = 25 let mature = 40 let elderly = 55 let aged = 75 let anton = 31 var age: String age = (anton > aged ? "aged" : (anton > elderly ? "is elderly" : (anton > mature ? "is mature" : (anton > adult ? "is adult" : (anton > youth ? "is youth" : (anton > teenager ? "is a teenager" : (anton > child ? "is a child" : "was never born"))))))) print("Anton \(age)")

Ответ 2



Никогда не стоит делать столько вложенных if - else, такой код не возможно читать. switch - case тоже не очень удобный вариант. Предлагаю такое решение, создаете словарь, где число это ключ и текст значение. Далее создаете цикл и проходите по каждому ключу и сравниваете его с нужным вам значением, как только ключ больше чем значение, значит выводите текст с данным ключем. var dictionary = [0 : "is a child", 12 : "is a teenager", 16 : "is youth", 25 : "is adult", 40 : "is mature", 55 : "is elderly", 75 : "is aged"] var age: String = "was never born" let anton = 31 var temp = 0 for (key, value) in dictionary { if anton > key && key > temp { age = value temp = key } } print("anton \(age)") Обратите внимание на переменную var temp = 0, она создана для того, чтобы сохранять максимальный возраст, который был найдет в словаре, так как словарь не гарантирует вам порядок элементов, в отличии от массива, вы не можете просто пройти по словарю и найти то значение, которое будет больше чем anton. Как только в цикле нашли элемент, который больше чем anton, сохраняем значение в temp и идем дальше по словарю, в поисках элемента который больше чем anton И больше чем temp.

четверг, 23 января 2020 г.

Как создать RSA (PEM 1024 bit) пару ключей на Objective-C или Apple Swift?

#swift #objective_c #ios #rsa #key


Доброе время суток, в общем нужно создать RSA (PEM 1024 bit) пару ключей, пробовал
разные варианты, но проблема в том, что как оказалось под iOS это большая редкость,
пробовал таким образом:

Способ #1

Способ #2

Но это не то что нужно, они создаются в HEX нужен PEM, либо же как можно преобразовать
ключ в PEM?
    


Ответы

Ответ 1



Получилось реализовать с помощью библиотеки.

среда, 22 января 2020 г.

Как правильно разрабатывать UI для iOS приложения? Advanced UIKit?

#ios #xcode #swift


Не имею четкого представления и понимания о правильных подходах к реализации/программированию
именно UI-части приложения, с так скажем "backend" частью пока особых проблем нет.
Приведу пример:
Когда понял, что приложение нуждается в подчинении чему-то более продвинутому и современному
чем простой MVC, изучил вопрос архитектурных паттернов, выбрал подходящую(VIPER), изучил
более подробно и реализовал. 

Однако следующие задачи:

      Сделать переиспользуемую сетку с элементами вида "иконка - подпись", причем
на маленьком экране показывать в три столбца, на больших в четыре, плюс слегка увеличивать-уменьшать
размер самих этих иконок и подписей. В итоге создал xib-файл для одного такого элемента
сетки, и класс-наследник UIView, в который передается массив картинок/подписей и он
там у себя все высчитывает и строит
      Два блока(верхний и нижний) могут изменяться в размерах относительно контента,
а блок между ними(label) занимать все оставшееся место. При этом текст в UILabel не
должен уходить половиной строки под frame. Пришлось в коде слегка обрезать высоту label
чтобы длина была кратна высоте одной строки
     Переиспользовать таблицу, убрав некоторые кнопки из tab-bar. Например есть основная
лента элементов, а есть такая же лента, только с избранными

вызвали у меня намного больше проблем и гуглить их реализацию было намного сложнее.
В итоге все сделал сам, однако уверен что есть более правильные и элегантные подходы
к решению тех задач с UI, которые появляются с каждым днем. Также есть вопрос: Storyboard
или UI в коде? Или часть там, часть  - там? Пока что у меня второй вариант с отдельным
сторибордом для каждого контроллера и  вкраплениями xib-файлов для каких-нибудь переиспользуемых
вьюшек вроде круглая иконка и подпись. Однако есть подозрения что лучше делать это
в коде (задание размеров, позиций, constraint-ов), с использованием сторонних библиотек
для layout-а, т.к.  быстрее с точки зрения работы приложения , удобнее и легче с точки
зрения контроля версий. 

Вопрос не по конкретно вышеперечисленным моментам, а по общей теоретической подготовке
и хорошим практикам по работе с UIKit. Ибо просто накидать нужный не-адаптивный интерфейс,
связать аутлетами и заполнить view нужным контентом я могу уже давно, даже 70 процентов
задач autolayout удается реализовать вполне себе хорошо. Однако в процессе разрастания
и усложнения ui и возможностей приложения, все сильнее нуждаюсь в теории и практикам
по UIKit уровня выше junior. Подскажите пожалуйста, какие на данный момент bad/best
practices, что считается хорошим тоном, а что нет?  Может есть какие-нибудь сайты/туториалы,
где показывают как создавать переиспользуемые UI-компоненты, как строить сложный autolayout(как
правило все туториалы очень простые и в реальной жизни приходится делать что-то в разы
сложнее, а правильной теоретической базы по решению тех или инных более менее сложных
и реальных задач UI нет).
    


Ответы

Ответ 1



Тут вопрос зависит от ваших ресурсов, если не требуется детальная обработка UIView, то лучше использовать XIB или Storyboard, это сэкономит вам уму времени. Если нужно нарисовать сложный UI то лучше сдлетаь это кодом в кастомном классе наследуемом от UIView, с добавлением Core Graphics и Core Animation. Вот тут более детально описываются плюсы и минусы. Статья довольно старая, но концепция не изменилась. Ручная верстка vs Storyboard/Nib По воду практики могу посоветовать только платные курсы. С свое время они мне очень сильно помогли. Custom Controls in iOS, Drawing in iOS Предпочтительнее пройти второй курс, так-как он написан на swift 4. Так-ж если собираетесь создавать UIView кодом. Эта библиотека очень упростит вам жизнь. SnapKit

пятница, 27 декабря 2019 г.

Как сделать логин к сайту api без токена?

#ios #django #swift #django_rest_framework


Создал тестового юзера:
username: "david"
password: "framework"

let urlString = "http://gemcave.pythonanywhere.com/api/order"

            let email = "david"
            let password = "framework"

            let parameters = [
                "username": email,
                "password": password
            ]   

            Alamofire.request(.GET, urlString,parameters: parameters).responseJSON
{response in
                let json = JSON(response.data!)
                let swiftyJsonVar = json["truckType"].string
                print(swiftyJsonVar)
            }


Ошибка: return nil - аутентификация не проходит
Я не знаю в чем именно проблема в сервере или приложении

Бэкэнд: Django Rest Framework

JSON пример:

[
    {
        "id": 1,
        "textDep": "Paris",
        "textDest": "Deli",
        "truckType": "Грузовик1",
        "created_date": "2015-12-22T09:42:38Z",
        "author": 1
    },
    {
        "id": 4,
        "textDep": "Astana",
        "textDest": "Almata",
        "truckType": "Грузовик1",
        "created_date": "2015-12-22T09:44:13Z",
        "author": 1
    }
]



    


Ответы

Ответ 1



Могу предположить, что вы не активировали тестового юзера, попробуйте поднять django-admin, и оттуда уже проверить есть ли пользователь, активен ли он, есть ли у него соответствующие права, по части сервера всё сразу станет ясно.

среда, 18 декабря 2019 г.

Swift, воспроизведение mp3 в фоне

#ios #swift


У меня с периодичностью запускается фоновый поток scheduledTimerWithTimeInterval(),
который проверяет наличие в базе записей с определенным статусом

Если такие записи есть, то необходимо воспроизвести mp3. 

Делал воспроизведение с помощью:

1. AVAudioPlayer

Включил Audio, AirPlay and Picture in Picture в BackgroundModes

    do {
    try   AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
    try AVAudioSession.sharedInstance().setActive(true)
    } catch _ {
    return print("error")
    }


Установил категорию AVAudioSessionCategoryPlayback

Проблема: на открытом экране каждые 20 секунд издается звук (играет музыка), а вот
когда просто сверну приложение, звук сам уже не воспроизводится. 

2. AudioServicesPlayAlertSound(1009)

Работал но APPLE отклоняли с причиной "Включен режим backgroundModes но ни чего не
воспроизводится".

Что можно использовать для такой задачи?

UPD

Это метод который запускает таймер с интервалом 20 секунд:

func scheduledTimerWithTimeInterval(){
timer = NSTimer.scheduledTimerWithTimeInterval(20, target: self, selector: #selector(ListOfOrders.checkNewOrder),
userInfo: nil, repeats: true)
registerBackgroundTask()
}


Это метод, который запускает таймер, в котором происходит закачка и проверка данных.
Если есть новые данные, в теории телефон должен пищать

func checkNewOrder() {
WorkWithInternet().getOrders(self, token: prefs.stringForKey("token")!, col: 0, add:
false, vc: ListOfOrders())
}


UPD2 Воспроизведение звука по файлу:

do {
    let soundURL: NSURL = NSBundle.mainBundle().URLForResource("notif", withExtension:
"mp3")!
    audioPlayer = try AVAudioPlayer(contentsOfURL: soundURL)
    audioPlayer!.delegate = self
    audioPlayer!.prepareToPlay()
    audioPlayer!.play()
}catch{
    print("Error")
}


UPD3

var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid


Регистрирует таск в фоне: 

func registerBackgroundTask() {
    backgroundTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler {
    [unowned self] in
    self.endBackgroundTask()
    }
    assert(backgroundTask != UIBackgroundTaskInvalid)
 }


Функция завершения бэкграунд-таска:

func endBackgroundTask() {
   NSLog("Background task ended.")
   UIApplication.sharedApplication().endBackgroundTask(backgroundTask)
   backgroundTask = UIBackgroundTaskInvalid
}

    


Ответы

Ответ 1



Взгляни на этот проект из книги Я лично протестировал его на iOS 9.3 iPhone 6+ все работает.

Swift: AVAudioPlayer время трека

#ios #swift #время


Есть ViewController с AVAudioPlayer. Нужно показать на экране текущее время трека
и время до окончания.  

Мой код:

@IBAction func play(sender: AnyObject) {
    if !audioPlayer.isPlaying{
        audioPlayer.play()
        slider.maximumValue = Float(audioPlayer.duration)
        slider.value = 0.0
        timer = Timer(timeInterval: 1.0, target: self, selector: #selector(self.updateTime),
userInfo: nil, repeats: true)
        RunLoop.main.add(timer!, forMode: .commonModes)
    }
}

func updateTime() {
    let currentTime = Int(audioPlayer.currentTime)
    let minutes = currentTime/60
    let seconds = currentTime - minutes * 60
    timeElapsed.text = NSString(format: "%02d:%02d", minutes,seconds) as String
}


Проблема в том, что иногда timeElapsed прибавляет несколько секунд сразу, а иногда
одну. Как правильно показать на экране текущее время трека и время до окончания трека?
    


Ответы

Ответ 1



Проблема таймера в том, что он не совсем точно отсчитывает заданный интервал. Он срабатывает, когда у системы есть свободные ресурсы в примерно необходимое время. В принципе, оно для человека и незаметно, но когда Вы запускаете проигрыватель и одновременно с ним таймер, возможно и возникает ситуация, что пошла уже вторая секунда песни, а таймер немного запоздал. Попробуйте просто изменить интервал таймера с 1 на 0.5 секунды.

воскресенье, 15 декабря 2019 г.

Зачем Apple придумала язык программирования Swift?

#objective_c #swift #apple #дизайн_языка


Чем не устроил их Objective-C? Какие преимущества у Swift перед Objective-C?     


Ответы

Ответ 1



Swift — гораздо более современный язык, не отягощённый проблемами совместимости с C. Добавить фичи наподобие безопасности памяти (memory safety), обобщённых классов/методов (generics), необнуляемых ссылок (non-nullable reference types) было бы очень сложно, оставаясь в рамках Objective C. (Сравните, например, лямбды в Objective C и в Swift'е.) Синкатсис, да и семантика C хороши для низкоуровневых языков (каким, например, C и является), но высокоуровневые фичи проще делать на другой основе.

среда, 11 декабря 2019 г.

swift: in-app purchase

#ios #swift #button


Нужно на кнопке показать стоимость встроенной покупки в валюте страны покупателя. 

Для России мой текст выглядит так: 299.00 RUB 


Как посмотреть как выглядит покупка для США?
Как вместо RUB поставить знак ₽ или вместо USD знак $? 


Мой код:

func productsRequest (_ request: SKProductsRequest, didReceive response: SKProductsResponse) {

    let count : Int = response.products.count
    if (count>0) {
        let validProduct: SKProduct = response.products[0] as SKProduct
        if (validProduct.productIdentifier == self.product_id) {
            print(validProduct.localizedTitle)
            print(validProduct.localizedDescription)
            print(validProduct.price)
            buyProduct(product: validProduct);

            let numberFormatter = NumberFormatter()
            numberFormatter.formatterBehavior = .behavior10_4
            numberFormatter.numberStyle = .currency
            numberFormatter.locale = validProduct.priceLocale
            let price = numberFormatter.string(from: validProduct.price)
            self.buyButton.setTitle(price, for: .normal)
            NSLog("The price of this product is \(validProduct.price)")
        } else {
            print(validProduct.productIdentifier)
        }
    } else {
        print("nothing")
    }
}


UPD

func buyProduct(product: SKProduct){
    print("Sending the Payment Request to Apple");
    let payment = SKPayment(product: product)
    let price = localizedPriceForProduct(product)
    buyButton.setTitle("\(price)", for: .normal)
    SKPaymentQueue.default().add(payment);

}

func localizedPriceForProduct(_ product:SKProduct) -> String {
    let priceFormatter = NumberFormatter()
    priceFormatter.formatterBehavior = NumberFormatter.Behavior.behavior10_4

    priceFormatter.numberStyle = NumberFormatter.Style.currencyISOCode
    //эта строка отвечает за формат написания (USD или $ использовать .currency)

    priceFormatter.locale = product.priceLocale
    return priceFormatter.string(from: product.price)!
}

    


Ответы

Ответ 1



func localizedPriceForProduct(_ product:SKProduct) -> String { let priceFormatter = NumberFormatter() priceFormatter.formatterBehavior = NumberFormatter.Behavior.behavior10_4 priceFormatter.numberStyle = NumberFormatter.Style.currencyISOCode //эта строка отвечает за формат написания (USD или $ использовать .currency) priceFormatter.locale = product.priceLocale return priceFormatter.string(from: product.price)! } Вызовите функцию: var product = SKProduct() ... let price = localizedPriceForProduct(product)

Ответ 2



1) посмотреть какой банк предоставляет API для перевода валют по текущему курсу. И использовать этот API 2) использовать replacingOccurrences let aString = "100 USD!" let newString = aString.replacingOccurrences(of: "USD", with: "$", options: .literal, range: nil)

вторник, 10 декабря 2019 г.

swift 3: NSTimer

#ios #swift


Использую этот код для проигрывания аудио. Проблема в том, что из-за этой строчки
RunLoop.main.add(timer!, forMode: .commonModes) устройство сильно греется. Как это
исправить?

Полный код:

@IBAction func playAudio(sender: AnyObject) {
    if !audioPlayer.isPlaying{
        audioPlayer.play()
        slider.maximumValue = Float(audioPlayer.duration)
        slider.value = 0.0
        timer = Timer(timeInterval: 0.0, target: self, selector: #selector(self.updateTime),
userInfo: nil, repeats: true)
        RunLoop.main.add(timer!, forMode: .commonModes)
    } else {
        audioPlayer.pause()
        playButton.setImage(UIImage(named: "pause.png"), for: UIControlState.normal)
        timer?.invalidate()
    }
}

func updateTime() {
let currentTime = Int(audioPlayer.currentTime)
let minutes = currentTime/60
let seconds = currentTime - minutes * 60
timeElapsed.text = NSString(format: "%02d:%02d", minutes,seconds) as String
}

    


Ответы

Ответ 1



Жарко ему от этой строчки? :) Или вы все-таки будете хоть немного конкретизировать возникающие проблемы, наверно нагрузка на процессор высокая, от того и нагрев? Код тоже анализируйте, интервал 0.0 это практически while (true) {} что нагрузит одно из ядер процессора почти на 100%.

Ответ 2



можно также использовать в Swift не NSTimer a GСD-шный и более Swift-style вариант где то в вашем классе объявите свойство var timer:DispatchSourceTimer? если стартуете новую мелодию, переинициализируйте его timer = DispatchSource.makeTimerSource() timer?.scheduleRepeating(deadline: .now(), interval: .seconds(1) ) timer?.setEventHandler { DispatchQueue.main.async { // ваш код для обновления времени проигрывания на UI } } в обработчике кнопки Play/Stop если хотите запустить timer?.resume() если остановить совсем timer?.cancel() если поставить на паузу timer?.suspend()

понедельник, 9 декабря 2019 г.

По каким причинам в Swift 3 будут удалены инкремент и декремент (++ и --)?

#ios #swift


Потихоньку начинаю изучать Swift и программирование вообще. В одном из уроков рассказывается
про инкремент, декремент, постфиксную, префиксную формы записи и прочее. Но попробовав
получаю такое предупреждение:



Т.к. с английским туго как и с программированием (близко к нулю) с Гугл переводчиком
стало понятно, что это все будет удалено в третьей версии. Но почему? По описанию очень
удобные вещи.
    


Ответы

Ответ 1



О-о, на эту тему опубликован целый документ, предлагающий удаление. По всей видимости, предложение было принято. Из значимых аргументов против: Не экономят место. По сравнению с x += 1 выражение x++ не особо-то короче. Конфликтуют с семантикой остального языка. В Swift присваиания и схожие изменяющие действия возвращают Void. Эти — нет. Запутывают разработчиков. Код, использующий возвращаемые значения этих операторов, очень тяжело воспринимается. Swift определяет порядок вычисления своих конструкций, поэтому foo(++a, a++)... хотя бы ведёт себя известным образом (в С++, скажем, такой роскоши нет), но для понимания нужно знать дебри языка. А можно, где это важно, произвести изменения заранее в нужном порядке. Полученный код будет даже лучше отражать алгоритм. Редко применимы. Они применимы к довольно небольшому числу типов: целым и вещественным числам, чему-нибудь итератороподобному... но для комплексных чисел, матриц и т. п. они просто не имеют смысла. Редко нужны. Где использовать их? В циклах? В Swift уже достаточно синтаксических удобств для них (for-in, диапазоны, enumerate, map и другие), поэтому подобные конструкции в идиоматичном Swift-коде не должны возникать вообще. Считаю нужным предупредить, что сам я не знаю Swift, но со стороны Ruby, где этого семейства операторов нет и не было, это выглядит очень осмысленным изменением. Когда можно безопасно инкапсулировать сложные способы итерации внутрь классов-генераторов (или других аналогичных механизмов: в Ruby это методы с блоками), частое использование сокращений вроде ++ и -- перестаёт иметь смысл. А когда конструкция используется редко, мало смысла иметь в языке её сокращённый синоним: это лишнее усложнение синтаксиса*, что плохо действует на понимание кода программистами и как следствие на стабильность итогового продукта. Напоминаю также, что "ошибка на единицу" очень часто встречающаяся штука. * --x можно распознать и как -(-x), два применения унарного минуса, что несколько отличается от того, что делает предекремент — подобные синтаксические неоднозначности делают язык более сложным в использовании, поэтому от них есть смысл избавляться

воскресенье, 8 декабря 2019 г.

Стоит ли начинать писать на Apple Swift? [закрыт]

#ios #objective_c #swift


        
             
                
                    
                        
                            Closed. This question is off-topic. It is not currently
accepting answers.
                            
                        
                    
                
                            
                                
                
                        
                            
                        
                    
                        
                            Want to improve this question? Update the question so
it's on-topic for Stack Overflow на русском.
                        
                        Closed 4 года назад.
                                                                                
           
                
        
Доброе время суток! В общем в скорем времени предстоит написать проект под iOS, по
объемам не маленький, раньше сентября не выйдет, необходим от 6 iOS, вопрос вот в чём,
есть ли смысл начинать реализовывать на Swift? Или же писать на старом, добром Objective-C?
Что вы думаете по этому поводу? Интересно узнать ваше мнение.    


Ответы

Ответ 1



Apple Swift не поддерживает платформы ниже Mac OS X 10.9, iOS 7.0. К тому же до тех пор пока не будет стабильной версии Xcode 6 вы не сможете задеплоить в аппстор Ваше приложение (что произойдет вероятно осенью, после следующего Apple-ивента).

Ответ 2



Я сейчас пишу на Swift огромный проект (Аэрофлот iPad) и все ок, бывают небольшие проблемы с самим xCode (автокомплит отваливается постоянно, сама IDE крешится время от времени, возникают совершенно идиотские проблемы) и несколько функций языка еще недоделаны (например, override var) да и пока нельзя засабмитить проект в стор, но к осени все должно быть. На самом деле, Swift здорово сокращает время разработки такими вещами, как мощные конструкции switch, pattern matching, associated values в enums и многое другое. все это дело отлично дружит с Objective-C классами и категориями и одном проекте Разрабатываю на Swift fulltime недели 3, полет нормальный! Коротко опишу ситуацию: Проект был под iPhone на Objective-C, сейчас iPhone практически готов, сделали из проекта universal, добавили сториборд для iPad. Само-собой модель данных, сервер-клиент взаимодействие и некоторая логика вынесены и готовы для iPhone проекта в Objective-C. Все, что делается под iPad - делается на Swift, при этом используюется огромное количество классов, написанных ранее на Objective-C. Иногда, значительно реже, в Objective-C используются классы или категории, написанные на Swift. С этим проблем не выявил. Пока самая большая проблема - xCode 6, он реально глючит, в остальном работать можно даже с реально большими проектами, самое главное, смотрите, чтобы ваш дедлайн не стоял раньше сентября, иначе не залиться в App Store! В остальном - настоятельно рекомендую к изучению и использованию и говорю это как человек, разрабатывающий на Objective-C уже более 3.5 лет! По поводу доступа к Swift классам из Objective-C: во-первых, все классы (или протоколы), доступ к которым будет нужен, должны начинаться с ключевого слова @objc, например: @objc class MyClass : NSObject /* or any NSObject subclass */ { } @objc protocol MyProtocol { } во-вторых, в документации не точно указано, если у вас только один дефалтовый модуль, то есть вы НЕ создавали отдельно других, вам нужно импортить только MyProject-Swift.h то есть просто в нужном месте пишем: #import "MyProject-Swift.h" далее мне доступны все классы и протоколы, написанные на Swift с пометкой @objc Никаких дополнительных настроек в проекте выставлять не потребовалось, проект изначально был создан в xCode 5.1, думаю, что проекты, созданные в xCode 6 Beta не должны и подавно требовать дополнительных настроек, хотя не проверял... Надеюсь, это поможет, а то в комментах много вопросов на эту тему, всем удачи!

Ответ 3



В общем, поработав на чистом Swift'e - в целях обучения на небольшом проекте - могу сказать, что язык понравился, за исключением некоторых вещей. Например вместо set теперь =, вместо [] теперь . - мелочи, но уж до боли не привычно как-то всё, потом удивило, назначить на кнопку Action - теперь строкой писать нужно - из-за этого возникили у меня проблемы, так как компилятор её не проверяет, а я почему-то не подумал туда сразу посмотреть, но у языка есть будущее :) Но я думаю, что чтоит начинать писать на Swift'e, так как в будущем его Apple ещё дальше пропехнёт, вопрос только когда вы потратите время на "обучение", сейчас или через некоторое время, поддерживаемые версии по заявлеием от 7, но у меня и на 6 работает (возможно временно).

Ответ 4



Swift типа официально вышел. Мне хватило нескольких видеоуроков для знакомства со ним. Раньше мне просто не нравился его синтаксис, теперь я обнаружил я одну вещь, которая может превратить абсолютно любой проект в АД. Я имею в виду ПОЛНОЕ ОТСУТСТВИЕ неявного приведения типов, которое касается не только классов. Простой пример - объявите 2 переменные: целочисленную и дробную - и попробуйте их сложить. НИЧЕГО НЕ ПОЛУЧИТСЯ без приведения целого числа к дробному. А теперь представьте, сколько формул может быть в проекте. Да вы повеситесь каждую переменную переводить в дробный тип