iOS
MPM
Вибрация в приложении
Самый быстрый способ добавить вибрацию в приложение
import AudioToolbox ... AudioServicesPlayAlertSound(SystemSoundID(kSystemSoundID_Vibrate)) // vibration ...
Zinc Scanner
Сканер штрих кодов партий готовой продукции
Стек: Swift, MVVM, AVFoundation, RxRealm, Moya(REST), GCD
Сборка билда
- — переходим в дев
- — создаём релизную ветку
- — меняем версию
- — коммитим и пушим ветку
- — собираем билд и кладём его в Fabric
переходим в дев
создаём релизную ветку
git flow release start 0.4
меняем версию коммитим и пушим ветку собираем билд и кладём его в Fabric
ChemNote
Push Notifications
Оглавление
- получаем токен устройства
- генерация фалов из сертификатов
- настраиваем серверную часть (PHP)
- меняем звук уведомления по умолчанию
- удаляем бейджи
APNS — Apple Push Notification Service
1. получить токен устройства
для этого в файл AppDelegate.swift добавляем два метода
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. let notifyCenter = UNUserNotificationCenter.current() notifyCenter.delegate = self notifyCenter.requestAuthorization(options: [.sound, .alert, .badge]){ (granted, error) in print("ok: \(granted)") print("err: \(error)") } application.registerForRemoteNotifications() return true } func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { let token = PushNotifyHelper.getTokenFromDeviceToken(deviceToken) print("Registration device token: \(token)") }
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { print("Handle push from foreground") // custom code to handle push while app is in the foreground print("\(notification.request.content.userInfo)") } func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { print("Handle push from background or closed") // if you set a member variable in didReceiveRemoteNotification, you will know if this is from closed or background print("\(response.notification.request.content.userInfo)") }
PushNotifyHelper
import UserNotifications class PushNotifyHelper { class func getTokenFromDeviceToken(_ deviceToken: Data) -> String{ var token = "" for i in 0..<deviceToken.count { token = token + String(format: "%02.2hhx", arguments: [deviceToken[i]]) } return token } }
3. Настраиваем серверную часть (PHP)
$deviceToken = "0000000000000000000000000000000000000000000000000"; class PushSender{ static public function run($deviceToken){ $certificateFile = "push.pem"; $certificateString = file_get_contents('push.pem'); $port = 2195; $host = "gateway.sandbox.push.apple.com"; $address = "ssl://{$host}:{$port}"; $title = "title"; $message = "Privet"; $arMessage = array( 'aps' => array( 'alert' => array( 'title' => $title, 'body' => $message, ), 'url-args' => array( '', ), 'sound'=>'default' ), ); $error = 0; $errorString = ""; $context = $streamContext = stream_context_create(); $path = tempnam(sys_get_temp_dir(), 'cert_'); file_put_contents($path, $certificateString); stream_context_set_option($streamContext, 'ssl', 'local_cert', $path); $client = @stream_socket_client( $address, $error, $errorString, 2, STREAM_CLIENT_CONNECT, $context ); $encodedPayload = json_encode($arMessage); $binaryData = chr(0). chr(0). chr(32). pack('H*', $deviceToken). chr(0).chr(strlen($encodedPayload)). $encodedPayload; fwrite($client, $binaryData); fclose($client); } } PushSender::run($deviceToken);
для примера я сделал анти-рефакторинг и объединил несколько разных классов в один метод нарушив сразу несколько парадигм ООП. но сделал это чтобы не размазывать код, а попытаться наглядно показать объём который нужен для отправки уведомлений с сервера на iOS устройства.
5. удаляем бейджи )
UIApplication.shared.applicationIconBadgeNumber = 0;
изменить цвет pdf картинки
чтобы изменить цвет pdf картинки(иконки) в свойствах Render As надо выставить template
tintColor
backgroundColor
iOS: SwiftMonkey
Swift: Audio
проигрывать кастомный звук
import AVFoundation /// example: /// player = AudioHelper() /// player.prepare("r2d2") /// player.playSound() class AudioHelper { private var player = AVAudioPlayer() func prepare(name:String){ let path = Bundle.main.path(forResource: name, ofType: "mp3") let url = URL(fileURLWithPath: path!) do { self.player = try AVAudioPlayer(contentsOf: url) self.player.prepareToPlay() } catch{ print("error plaing sound") } } func playSound() { player.play() } }
let player = AudioHelper() player.prepare("r2d2") player.playSound()
iOS: IBDesignable и IBInspectable
Пример класса
import UIKit @IBDesignable class UIViewDes: UIView { @IBInspectable var borderColor: UIColor = UIColor.clear{ didSet{ layer.borderColor = borderColor.cgColor } } @IBInspectable var borderWidth:CGFloat = 1 { didSet{ layer.borderWidth = borderWidth } } @IBInspectable var corderRadius: CGFloat = 0 { didSet{ layer.cornerRadius = corderRadius } } override func awakeFromNib() { super.awakeFromNib() } }
Swift: Работа с датой
как можно пользоваться датой в swift
// форматируем дату строку формата "dd.mm.yyyy" func getDate() -> String{ let formatter = DateFormatter() formatter.dateFormat = "dd.mm.yyyy" let date = formatter.string(from: dateEnd as Date) return date }
/// Хелпер для работы с датами class DateHelper { /// преобразует строку вида YYYY-MM-DD -> NSDate /// /// - Parameter dateStr: строка формата YYYY-MM-DD /// - Returns: NSDate class func dateFromString (dateStr: String) -> NSDate? { let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd" let date = dateFormatter.date(from: dateStr) return date as NSDate? } // форматируем дату строку формата "dd.mm.yyyy" class func toString(date:Date, format:String) -> String{ let formatter = DateFormatter() formatter.dateFormat = format let dateResult = formatter.string(from: date as Date) return dateResult } }
ещё вариант в виде extension
extension Date { static func from(_ value: String) -> Date? { let dateFormatter = DateFormatter() // doc: http://userguide.icu-project.org/formatparse/datetime dateFormatter.dateFormat = "dd.MM.yyyy" if let newDate = dateFormatter.date(from: value) { return newDate } else { return nil } } // форматируем дату строку формата "dd.mm.yyyy" func to(format:String) -> String { let formatter = DateFormatter() formatter.dateFormat = format let dateResult = formatter.string(from: self) return dateResult } }
xcode: Создаём свой шаблон проекта для XCode
Создаём шаблон проекта на основе Single Application View
1 Шаг.
Идём в /Applications
правой кнопокой на приложении XCode и пункт Show Package Content
и заходим в папку Cmd+G ->
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/Project Templates/iOS/Application/
Копируем папку Single Application View и вставляем её по пути
~/Library/Developer/Xcode/Templates/[Templates group name]
Если вы это делаете в первый раз то папки Custom у вас нет и её надо создать
2 шаг. Меняем идентификатор шаблона в файле TemplateInfo.plist
CoreData: Create Read Update Delete
https://habrahabr.ru/post/303798/
// // DataHelper.swift // DaysList // // Created by Kirill on 13/03/2016. // Copyright © 2016 Kirill. All rights reserved. // import Foundation import UIKit import CoreData class DataHelper{ var context:NSManagedObjectContext init(context _context:NSManagedObjectContext){ self.context = _context } class func addRecord(_ _comment:String) -> Int64 { let newId:Int64 = (getLastId()+1) let context = persistentContainer.viewContext let day = Day(context: context) day.id = newId day.comment = _comment print("added day id=\(day.id):\(day.comment)") DataHelper.saveContext() return day.id } class func getAll(){ } /// Изменяем элемент /// /// - Parameters: /// - id: <#id description#> /// - _comment: <#_comment description#> class func updateById(id: Int64, comment _comment:String){ let day = getById(id: id) if (day != nil && (day?.id)! > 0){ day?.comment = _comment saveContext() } } class func deleteById(_ id:Int64){ let context = persistentContainer.viewContext let day = getById(id: id) if ((day?.id)! > 0){ context.delete(day!) } } class func delete<T>(item:T){ let context = persistentContainer.viewContext context.delete(item as! NSManagedObject) } class func getById(id:Int64)-> Day?{ let context = persistentContainer.viewContext let request: NSFetchRequest<Day> = Day.fetchRequest() request.predicate = NSPredicate(format: "id == %@", argumentArray: [id]) var days:[Day] = [] do{ days = try context.fetch(request) as [Day] } catch{ print("getById error") } let day = days.first return day } class func getLastId()-> Int64 { let context = persistentContainer.viewContext let request: NSFetchRequest<Day> = Day.fetchRequest() request.predicate = NSPredicate(format: "id == max(id)", argumentArray: []) var days:[Day] = [] do{ days = try context.fetch(request) as [Day] } catch{ print("getLastId error") } let day = days.first return (day?.id)! } static var persistentContainer: NSPersistentContainer = { let container = NSPersistentContainer(name: "DaysList") container.loadPersistentStores(completionHandler: { (storeDescription, error) in if let error = error as NSError? { fatalError("Unresolved error \(error), \(error.userInfo)") } }) return container }() class func saveContext () { let context = persistentContainer.viewContext if context.hasChanges { do { try context.save() } catch { let nserror = error as NSError fatalError("Unresolved error \(nserror), \(nserror.userInfo)") } } } }
let resultId = DataHelper.addRecord("текстовая строка")
Памятка
Обычно файл базы данных лежит где-то здесь
/Users/<USER>/Library/Developer/CoreSimulator/Devices/<DEVICE_ID>/data/Containers/Data/Application/<APPLICATION_ID>/Documents/<FileName>.sqlite