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

#iOS

всё что связано с приложения под iOS и их интеграцией с сайтами и интернет магазинами

Generamba: как использовать ?

3 мая 2017, 23:58

пример rambafile

### Headers settings
company: adeveloper

### Xcode project settings
project_name: SkillViperT
xcodeproj_path: SkillViperT.xcodeproj

### Code generation settings section
# The main project target name
project_target: SkillViperT

### 
project_file_path: SkillViperT/Modules

### Templates
templates:
#- {name: local_template_name, local: 'absolute/file/path'}
#- {name: remote_template_name, git: 'https://github.com/igrekde/remote_template'}
#- {name: catalog_template_name}
- {name: swifty_viper}
#iOS

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

xcode: Создаём свой шаблон проекта для XCode

12 января 2017, 16:27

Создаём шаблон проекта на основе 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

! Теперь мы можем наполнить папку проекта своими исходниками и всё.
Шаблон проекта готов к использованию.

Создание своих шаблонов исхдников

#iOS   iOS   xcode

iOS: Code Injection (on runtime)

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

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

на github


#iOS   Swift

iOS: VIPER архитектура

26 декабря 2016, 13:44

Сделай настолько просто, насколько это возможно, но не проще.

(с)Альберт Эйнштейн

признаки хорошей архитектуры:

  1. сбалансированное распределение обязанностей между сущностями с жесткими ролями;
  2. тестируемость. Обычно вытекает из первого признака (без паники, это осуществимо при соответствующей архитектуре);
  3. простота использования и низкая стоимость обслуживания.

VIPER

Архитектура VIPER

Архитектура VIPER

Разделение обязанностей — это очень хорошо

View: отвечает за отображение данных на экране и оповещает Presenter о действиях
пользователя. Пассивен, сам никогда не запрашивает данные, только получает их от
презентера.

Interactor: содержит всю бизнес-логику, необходимую для работы текущего модуля.

Presenter: получает от View информацию о действиях пользователя и преображает ее
в запросы к Router’у, Interactor’у, а также получает данные от Interactor’a,
подготавливает их и отправляет View для отображения.

Entity: объекты модели, не содержащие никакой бизнес-логики.

Router: отвечает за навигацию между модулями.

Книга VIPER

#iOS

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

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: Изменить цвет векторной картинки 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

iOS: Модальные окна

4 ноября 2016, 11:42

закрытие модального окна

dismiss(animation:true,nil)

чтобы окно-всплывашка была поверх текущего окна

  1. выставляем цвет у View backgound: Clear Color
  2. у ViewController указыаем presentation: Over Current Context
let frame:CGRect   = CGRect(x: 50, y: 30, width: 200, height: 300)
        self.view.frame           = frame

ставим рамку и цвет рамки у PopUp окна

override func viewDidLayoutSubviews() {
     ... 
       self.view.layer.borderWidth = 1
        self.view.layer.borderColor = UIColor.black.cgColor
}

получаем контроллер из Storyboard программно

let SpecialViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SpecialViewController") as! SpecialViewController
#iOS   Swift

Аналог foreach в Objective-C

22 января 2016, 14:32

По массиву можно пробежать обычным for
пример:

//arItems - это массив  NSArray содержащий элементы типа NSString
for (NSString *item in arItems){
  NSLog(@" item:%@",item);
}

Конкатенация строк

NSString *tmpText = [NSString stringWithFormat:@"%@\n%@",_txtView.text,_txtMessage.text];

Публичная переменная класса

@public NSString *message;

Выход из приложения похоже уже не применяют, но тем не менее он делается так

exit(EXIT_SUCCESS);
#iOS   Objective-C
Ctrl + ↓ Ранее