Git Hub
коротко
90 заметок с тегом

Swift

Ctrl + ↑ Позднее

Swift: Audio

18 января 2017, 23:19

проигрывать кастомный звук

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   iOS   Swift

iOS: IBDesignable и IBInspectable

18 января 2017, 11:34

Пример класса

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()
    }
}

Полезный сайт

#iOS   iOS   Swift

Swift: Работа с датой

15 января 2017, 16:35

как можно пользоваться датой в 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
    }
}
#iOS   iOS   Swift

Swift: Generics (Дженерики)

12 января 2017, 14:09

Пример Generics в функции

class GenericsDemo {
    class func swap<T>(_ a: inout T,_ b: inout T){
        let temp = a
        a = b
        b = temp
    }
}

var n1 = 100
var n2 = 200

GenericsDemo.swap(&n1, &n2)

var s1 = "s1"
var s2 = "s2"

print("s1=\(s1) <-> s2=\(s2)")
GenericsDemo.swap(&s1, &s2)
print("swap\ns1=\(s1) <-> s2=\(s2)")

Genereics в типах

protocol Container {
   typealias ItemType
   mutating func append(item: ItemType)
   var count: Int { get }
   subscript(i: Int) -> ItemType { get }
}

struct TOS<T>: Container {
   // original Stack<T> implementation
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   
   mutating func pop() -> T {
      return items.removeLast()
   }

   // conformance to the Container protocol
   mutating func append(item: T) {
      self.push(item)
   }
   
   var count: Int {
      return items.count
   }

   subscript(i: Int) -> T {
      return items[i]
   }
}

var tos = TOS<String>()
tos.push("Swift")
println(tos.items)

tos.push("Generics")
println(tos.items)

tos.push("Type Parameters")
println(tos.items)

tos.push("Naming Type Parameters")
println(tos.items)
Swift

iOS: Code Injection (on runtime)

11 января 2017, 15:01

Интересная штука инъекция кода в запущенном приложении

на github


#iOS   Swift

Паттерн Fabric Method

11 января 2017, 11:33

Оглавление

Фабричный метод

Фабричный метод порождает объекты одного и того же типа.

import Foundation
import UIKit

// Protocol for "Product" 
protocol AppleProduct {

    var name: String {get set}
    var screenSize: Double {get set}
    var price: Double {get set}

    func getProduct() -> String
}

// Protocl for "Creator" 
protocol AppleProductCreator {

    func createProduct() -> AppleProduct
}

// Class for "ConcreteProduct"
class IPhoneProduct: AppleProduct {

    var name: String = "iPhone 6"
    var screenSize: Double = 4.7
    var price: Double = 199.00

    func getProduct() -> String {

        return "Apple product "(name)", with screen size in (screenSize) inch, at proce: $(price)"
    }
}

class IPadProduct: AppleProduct {

    var name: String = "iPad Air 3"
    var screenSize: Double = 10.1
    var price: Double = 499.00

    func getProduct() -> String {

        return "Apple product "(name)", with screen size in (screenSize) inch, at proce: $(price)"
    }
}

// Class for "ConcreteCreator"
class IPhoneProductCreator: AppleProductCreator {

    static let sharedInstance:IPhoneProductCreator = IPhoneProductCreator()

    func createProduct() -> AppleProduct {

        return IPhoneProduct()
    }
}

class IPadProductCreator: AppleProductCreator {

    static let sharedInstance:IPadProductCreator = IPadProductCreator()

    func createProduct() -> AppleProduct {

        return IPadProduct()
    }
}

Применение

let product1: AppleProduct = IPhoneProductCreator.sharedInstance.createProduct()
print("Got a new device: " + product1.getProduct())

let product2: AppleProduct = IPadProductCreator.sharedInstance.createProduct()
print("Got a new device: " + product2.getProduct())

Пример 2

protocol Currency {
    func symbol() -> String
    func code() -> String
}

class Euro : Currency {
    func symbol() -> String {
        return "€"
    }

    func code() -> String {
        return "EUR"
    }
}

class UnitedStatesDolar : Currency {
    func symbol() -> String {
        return "$"
    }

    func code() -> String {
        return "USD"
    }
}

enum Country {
    case unitedStates, spain, uk, greece
}

enum CurrencyFactory {
    static func currency(for country:Country) -> Currency? {

        switch country {
            case .spain, .greece :
                return Euro()
            case .unitedStates :
                return UnitedStatesDolar()
            default:
                return nil
        }

    }
}

Применение

let noCurrencyCode = "No Currency Code Available"

CurrencyFactory.currency(for: .greece)?.code() ?? noCurrencyCode
CurrencyFactory.currency(for: .spain)?.code() ?? noCurrencyCode
CurrencyFactory.currency(for: .unitedStates)?.code() ?? noCurrencyCode
CurrencyFactory.currency(for: .uk)?.code() ?? noCurrencyCode

CoreData: Получение контекста

11 января 2017, 10:00

Получение контекста managedObjectContext в CoreData
Каждый объект хранимый в CoreData имеет ссылку на контекст

let context = someCoreDataItem.managedObjectContext
CoreData   Swift

Паттерн Iterator

10 января 2017, 11:38

Оглавление

Пример

//: Playground - noun: Паттерн Iterator

import UIKit

struct BanksLevel{
    let price:Double
    let time:UInt32
    let comment:String
}

struct Levels {
    let arLevels: [BanksLevel]
}

struct LevelsIterator: IteratorProtocol {
    
    private var current = 0
    private let levels: [BanksLevel]
    
    init(levels: [BanksLevel]) {
        self.levels = levels
    }
    
    mutating func next() -> BanksLevel? {
        defer { current += 1 }
        return levels.count > current ? levels[current] : nil
    }
}

extension Levels: Sequence {
    func makeIterator() -> LevelsIterator {
        return LevelsIterator(levels: arLevels)
    }
}

Применение

let arLevels = Levels(arLevels: [
    BanksLevel(price: 1.06740, time: 1, comment: "Первый банковский уровень"),
    BanksLevel(price: 1.06210, time: 2, comment: "Второй банковский уровень")
] )

for level in arLevels {
    print("Определён: \(level)")
}

Пример 2

import UIKit



class Item{
    let name:String
    
    init(_ name:String){
        self.name = name
    }
}



class IteratableItems{
    var arItems: [Item] = []
    
    init(items:[Item]){
        self.arItems = items
    }
}

class ItemIterator: IteratorProtocol{
    private var current = 0
    private let arItems: [Item]
    
    init(items:[Item]){
        self.arItems = items
    }
    func next()-> Item?{
        defer {
             current += 1
        }
        return arItems.count > current ? arItems[current] : nil
    }
    
}

extension IteratableItems: Sequence {
    
    func makeIterator() -> ItemIterator {
        return ItemIterator(items: arItems)
    }
}

Используем:

let arItems = IteratableItems(items: [Item("One"),Item("Two"),Item("Three")])

for item in arItems{
    print("item: \(item.name)")
}

Carthage: менеджер зависимостей

25 декабря 2016, 15:15

Carthage: менеджер зависимостей, как о нём говорят «простой и безжалостный»

carthage version

Cartfile — простой текстовый файл, который описывает зависимости Вашего проекта для Carthage, таким образом, он определяет, что устанавливать. Каждая строка в Cartfile указывает, откуда извлечь зависимость, имя зависимости, и при необходимости, какая версия зависимости используется. Cartfile аналогичный файлу Podfile в CocoaPods.

| Cartfile — создаём любым блокнотом

touch Cartfile
open -a Xcode Cartfile
github "CocoaLumberjack/CocoaLumberjack"
carthage update --platform iOS


#iOS   Swift

Swift: Проверяем интернет соединение

6 декабря 2016, 11:23

Всегда в приложениях работающих с сетью стоит проверять наличие сети.

import Foundation
import SystemConfiguration

public class CheckInternet {
    class func isConnectedToNetwork() -> Bool {
        
        var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
        zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
        zeroAddress.sin_family = sa_family_t(AF_INET)
        
        let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
            $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
                SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
            }
        }
        
        var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: 0)
        if SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) == false {
            return false
        }
        
        let isReachable = flags == .reachable
        let needsConnection = flags == .connectionRequired
        
        return isReachable && !needsConnection
        
    }

}
if (CheckInternet.isConnectedToNetwork() == true) {
    ...  // есть интернет
    }
    else{
   ...  // у вас нет интернета
    }
#iOS   Swift

Swift: Animation

4 декабря 2016, 15:46

Анимацию элементов сделать довольно не сложно

Скрытие элементов

let step1 = 0.5
        let step2 = 1.0
        let step3 = 1.5
        
        UIView.animate(withDuration: step1, animations: {
            self.labelDate.alpha = 0
            self.view.layoutIfNeeded()
        })
        
        UIView.animate(withDuration: step2, animations: {
            self.labelLevelUP.alpha = 0
            self.view.layoutIfNeeded()
        })
        
        UIView.animate(withDuration: step3, animations: {
            self.labelLevelDN.alpha = 0
            self.view.layoutIfNeeded()
        })

Показ элементов

func showUI(){
        let step1 = 1.0
        let step2 = 2.0
        let step3 = 3.5
        
        UIView.animate(withDuration: step3, animations: {
            self.labelDate.alpha = 1
            self.view.layoutIfNeeded()
        })
        
        UIView.animate(withDuration: step2, animations: {
            self.labelLevelUP.alpha = 1
            self.view.layoutIfNeeded()
        })
        
        UIView.animate(withDuration: step1, animations: {
            self.labelLevelDN.alpha = 1
            self.view.layoutIfNeeded()
        })
        
    }

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

sleep(3)

Перемещение объектов

uiViewedObject.view.center = CGPoint(x,y)
#iOS   Swift

Swift: Загружем из XIB файла

3 декабря 2016, 15:52

UIView

let cell = Bundle.main.loadNibNamed("MenuCellDefault", owner: self, options: nil)?.first as! MenuCellDefault

MenuCellDefault — имя xib файла
загрузка nib файла

такой вариант подходит для UIView производных, но не годится для UIViewController

UIViewController

let globalTasksVC  = GlobalTasksVC(nibName: "GlobalTasksVC", bundle: nil)
        self.present(globalTasksVC, animated: true, completion: nil)
#iOS   Swift

Swft: uiAlertView

1 декабря 2016, 9:07

Пример 1

let alert = UIAlertController(title: "Alert", message: "Message", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)

Пример 2

let alert = UIAlertController(title: "Alert", message: "Message", preferredStyle: UIAlertControllerStyle.alert)
        alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default){
            UIAlertAction in
                print("close")
        })
        
        self.present(alert, animated: true, completion: {
            print("show AlertMessage")
        })
Swift

Swift: Unit Test

30 ноября 2016, 23:06

Тесты

Правила написания тестов:

  1. Тестируем одно поведение (один тест тестирует одно поведение)

для того чтобы протестировать свои классы приложения нужно добавить в начало файла с тестами

@testable import PrjoectNameApp

где PrjoectNameApp — имя вашего iOS приложения/проекта

Памятка по методам

Всегда ошибка

XCTFail(@"always failed")

Равенство базовых типов

let primitive1:Int = 5
        let primitive2:Int = 5
        XCTAssertEqual(primitive1, primitive2)
}

Равенство с погрешностью базовых типов

let constOne:Float = 5.012
        let constTwo:Float = 5.014
        let accuracy:Float = 0.005
        XCTAssertEqualWithAccuracy(constOne, constTwo, accuracy: accuracy)

—-

Проверка на nil

id foo = nil;
    XCTAssertNil(foo, @"pointer:%p", foo);

—-

Проверка с задержкой по времени

XCTestExpectation *expectation = [self expectationWithDescription:@"block not call"];
    NSTimeInterval timeout = 1.0f;
    [expectation performSelector:@selector(fulfill)
                      withObject:nil
                      afterDelay:0.3f];
    [self waitForExpectationsWithTimeout:timeout
                                 handler:nil];

Тест асинхронного взаимодействия

func testNetModel(){
        var items:[Post] = []
        let expect = expectation(description: "Test net Model")
        let model = NetModel()
        model.npGetList({
            posts in
            items = posts
            expect.fulfill()
        })
        
        waitForExpectations(timeout: 4.0, handler: { error in
            if let error = error {
                XCTFail(error.localizedDescription)
            }
            
            let isLoaded:Bool = (items.count > 1)
            XCTAssertTrue(isLoaded)
            if isLoaded == false {
                print("posts: \(items)")
            }
            
        })
    }

—-

#iOS   Swift   Test

Swift: читаем куки

29 ноября 2016, 10:53

просто читаем куки

func readCookies(){
        
        if let cookies = HTTPCookieStorage.shared.cookies {
            for cookie in cookies {
                print("\n\n\(cookie)\n\n")
            }
        }
    }

ставим куки к запросу

...
 let request =  NSMutableURLRequest(url: url! as URL)
 let cookies = HTTPCookieStorage.shared.cookies
        for cookie in cookies! {
             request.setValue(cookie.value, forHTTPHeaderField: cookie.name)
        }
 webView.delegate = self
 webView.loadRequest(request as URLRequest)
#iOS   Swift

Swift: выполнить код в основном потоке

27 ноября 2016, 23:55
DispatchQueue.main.async {
                let urlSmallImage = "https:" + smallImage.string!
                let url = NSURL(string: urlSmallImage)
                let data = NSData(contentsOf:url! as URL)
                self.profilePhoto.image = UIImage(data:data! as Data)
            }
Swift

Swift: преобразование опционального типа к строгому

25 ноября 2016, 15:04

(imageOption?.description)!

let imageOption = value[0].dictionary!["photo"]?.dictionary?["src"]?.dictionary?["small"]
                        let imageSmall = "https:" + (imageOption?.description)!
Swift

Swift: Изменить цвет векторной картинки pdf

8 ноября 2016, 9:43

Часто требуется изменить цвет отрисовки контурной иконки, в Swift 3 это делается так

let logo = UIImage(named: "Home")
let imageView = UIImageView(image:logo)
imageView.image = imageView.image!.withRenderingMode(.alwaysTemplate)
imageView.tintColor = UIColor.white
self.navigationItem.titleView = imageView
#iOS   Swift

UIButton: скруглёные края

7 ноября 2016, 13:21
layer.cornerRadius   Number  10
layer.masksToBounds Boolean Yes
#iOS   Swift

Нельзя просто так взять и обновить UI, когда пришел ответ с сервера

6 ноября 2016, 21:01

Нельзя просто так взять и обновить UI, когда пришел ответ с сервера

Программисты с опытом ObjC могут посмеяться над этой «ловушкой», потому что она должна быть общеизвестна: методы, связанные с UI, безопасно дергать только из главного потока. Иначе — непредсказуемость и баги, толкающие в тотальный ступор. Но это наставление почему-то проходило мимо меня, пока я, наконец, не столкнулся с жуткими багами.

Пример «проблемного» кода:

func fetchFromServer() {
    let url = NSURL(string:urlString)!
    NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: { data, response, error in
        if (error != nil) {
            ...
        } else {
            self.onSuccess(data)
        }
    })!.resume()
}
func onSuccess(data) {
    updateUI()
}

Обратите внимание на блок completionHandler — все это будет исполняться вне главного потока! Тем, кто еще не столкнулся с последствиями, советую не экспериментировать, а просто не забыть обставить updateUI следующим образом:

func onSuccess(data) {
    dispatch_sync(dispatch_get_main_queue(), {
        updateUI()
    })
}
DispatchQueue.main.sync(execute: {
            let item = arRecords[indexPath.row] as TaskModel
            detailVC.setDataSource(item: item)
        })
#iOS   Swift
Ctrl + ↓ Ранее