Вот решение сделать новый быстрый файл и скопировать этот код
import UIKit
class UltravisualLayout: UICollectionViewLayout {
private var contentWidth:CGFloat!
private var contentHeight:CGFloat!
private var yOffset:CGFloat = 0
var maxAlpha:CGFloat = 1
var minAlpha:CGFloat = 0
//DEFAULT VALUES
//var widthOffset:CGFloat = 35
// var heightOffset:CGFloat = 35
var widthOffset:CGFloat = 100
var heightOffset:CGFloat = 100
private var cache = [UICollectionViewLayoutAttributes]()
private var itemWidth:CGFloat{
return (collectionView?.bounds.width)!
}
private var itemHeight:CGFloat{
return (collectionView?.bounds.height)!
}
private var collectionViewHeight:CGFloat{
return (collectionView?.bounds.height)!
}
private var numberOfItems:Int{
return (collectionView?.numberOfItemsInSection(0))!
}
private var dragOffset:CGFloat{
return (collectionView?.bounds.height)!
}
private var currentItemIndex:Int{
return max(0, Int(collectionView!.contentOffset.y / collectionViewHeight))
}
var nextItemBecomeCurrentPercentage:CGFloat{
return (collectionView!.contentOffset.y / (collectionViewHeight)) - CGFloat(currentItemIndex)
}
override func prepareLayout() {
cache.removeAll(keepCapacity: false)
yOffset = 0
for item in 0 ..< numberOfItems{
let indexPath = NSIndexPath(forItem: item, inSection: 0)
let attribute = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)
attribute.zIndex = -indexPath.row
if (indexPath.item == currentItemIndex+1) && (indexPath.item < numberOfItems){
attribute.alpha = minAlpha + max((maxAlpha-minAlpha) * nextItemBecomeCurrentPercentage, 0)
let width = itemWidth - widthOffset + (widthOffset * nextItemBecomeCurrentPercentage)
let height = itemHeight - heightOffset + (heightOffset * nextItemBecomeCurrentPercentage)
let deltaWidth = width/itemWidth
let deltaHeight = height/itemHeight
attribute.frame = CGRectMake(0, yOffset, itemWidth, itemHeight)
attribute.transform = CGAffineTransformMakeScale(deltaWidth, deltaHeight)
attribute.center.y = (collectionView?.center.y)! + (collectionView?.contentOffset.y)!
attribute.center.x = (collectionView?.center.x)! + (collectionView?.contentOffset.x)!
yOffset += collectionViewHeight
}else{
attribute.frame = CGRectMake(0, yOffset, itemWidth, itemHeight)
attribute.center.y = (collectionView?.center.y)! + yOffset
attribute.center.x = (collectionView?.center.x)!
yOffset += collectionViewHeight
}
cache.append(attribute)
}
}
//Return the size of ContentView
override func collectionViewContentSize() -> CGSize {
contentWidth = (collectionView?.bounds.width)!
contentHeight = CGFloat(numberOfItems) * (collectionView?.bounds.height)!
return CGSizeMake(contentWidth, contentHeight)
}
//Return Attributes whose frame lies in the Visible Rect
override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var layoutAttributes = [UICollectionViewLayoutAttributes]()
for attribute in cache{
if CGRectIntersectsRect(attribute.frame, rect){
layoutAttributes.append(attribute)
}
}
return layoutAttributes
}
override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool {
return true
}
override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
let itemIndex = round(proposedContentOffset.y / (dragOffset))
let yOffset = itemIndex * (collectionView?.bounds.height)!
return CGPoint(x: 0, y: yOffset)
}
override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
// Logic that calculates the UICollectionViewLayoutAttributes of the item
// and returns the UICollectionViewLayoutAttributes
return UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)
}
}
В файле Main.storyboard используйте компонент UICollectionView или UICollectionViewController, выберите UICollectionView, перейдите в инспектор атрибутов и измените Layout from Flow на custom и set атрибут класса UltravisualLayout
здесь является ссылкой [ проекта ] и этой ссылкой на учебник
Надеюсь, это может помочь ХОРОШЕЕ LUCK ..
Ваша реализация очень хорошо, и она будет работать отлично на большинство целей.
не необходимо поместить каждый запрос в блоке попытки/выгоды, и на самом деле в большинстве случаев Вы на самом деле не хотите. Причина этого состоит в том, что, если запрос генерирует исключение, это - результат фатальной проблемы как синтаксическая ошибка или проблема базы данных, и те не проблемы, которые необходимо объяснять с каждым запросом, который Вы делаете.
, Например:
try {
$rs = $db->prepare('SELECT * FROM foo');
$rs->execute();
$foo = $rs->fetchAll();
} catch (Exception $e) {
die("Oh noes! There's an error in the query!");
}
запрос здесь будет или работать правильно или не работать вообще. Обстоятельства, где это не работало бы вообще, никогда не должны происходить ни с какой регулярностью в производственной системе, таким образом, они не условия, на которые необходимо проверить здесь. Выполнение так на самом деле контрпродуктивно, потому что Ваши пользователи получают ошибку, которая никогда не будет изменяться, и Вы не получаете сообщение об исключении, которое предупредило бы Вас к проблеме.
Вместо этого просто запишите это:
$rs = $db->prepare('SELECT * FROM foo');
$rs->execute();
$foo = $rs->fetchAll();
В целом, единственное время, когда Вы захотите поймать и обработать исключение запроса, - когда Вы хотите сделать что-то еще, если запрос перестал работать. Например:
// We're handling a file upload here.
try {
$rs = $db->prepare('INSERT INTO files (fileID, filename) VALUES (?, ?)');
$rs->execute(array(1234, '/var/tmp/file1234.txt'));
} catch (Exception $e) {
unlink('/var/tmp/file1234.txt');
throw $e;
}
Вы захотите записать простой обработчик исключений, который регистрирует или уведомляет Вас относительно ошибок базы данных, которые происходят в Вашей продуктивной среде, и отображает дружественное сообщение об ошибке Вашим пользователям вместо трассировки исключения. См. http://www.php.net/set-exception-handler для получения информации о том, как сделать это.
Несколько протестов здесь:
О, я должен указать, что эта точка иллюстрирует, как можно было перенести единственную функцию для обработки всей обработки исключений для запросов. Я не пишу блоки выгоды попытки почти больше нигде теперь, потому что отслеживание стека от запроса дает мне всю информацию, что я должен отладить проблему и зафиксировать ее.
Вот моя текущая реализация класса обертки PDO:
class DB extends PDO
{
// Allows implementation of the singleton pattern -- ndg 5/24/2008
private static $instance;
// Public static variables for configuring the DB class for a particular database -- ndg 6/16/2008
public static $error_table;
public static $host_name;
public static $db_name;
public static $username;
public static $password;
public static $driver_options;
public static $db_config_path;
function __construct($dsn="", $username="", $password="", $driver_options=array())
{
if(isset(self::$db_config_path))
{
try
{
if(!require_once self::$db_config_path)
{
throw new error('Failed to require file: ' . self::$db_config_path);
}
}
catch(error $e)
{
$e->emailAdmin();
}
}
elseif(isset($_ENV['DB']))
{
self::$db_config_path = 'config.db.php';
try
{
if(!require_once self::$db_config_path)
{
throw new error('Failed to require file: ' . self::$db_config_path);
}
}
catch(error $e)
{
$e->emailAdmin();
}
}
parent::__construct("mysql:host=" . self::$host_name . ";dbname=" .self::$db_name, self::$username, self::$password, self::$driver_options);
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('QueryStatement', array($this)));
if(!isset(self::$error_table))
{
self::$error_table = 'errorlog_rtab';
}
}
/**
* Return a DB Connection Object
*
* @return DB
*/
public static function connect()
{
// New PDO Connection to be used in NEW development and MAINTENANCE development
try
{
if(!isset(self::$instance))
{
if(!self::$instance = new DB())
{
throw new error('PDO DB Connection failed with error: ' . self::errorInfo());
}
}
return self::$instance;
}
catch(error $e)
{
$e->printErrMsg();
}
}
/**
* Returns a QueryBuilder object which can be used to build dynamic queries
*
* @return QueryBuilder
*
*/
public function createQuery()
{
return new QueryBuilder();
}
public function executeStatement($statement, $params = null, $FETCH_MODE = null)
{
if($FETCH_MODE == 'scalar')
{
return $this->executeScalar($statement, $params);
}
try {
try {
if(!empty($params))
{
$stmt = $this->prepare($statement);
$stmt->execute($params);
}
else
{
$stmt = $this->query($statement);
}
}
catch(PDOException $pdo_error)
{
throw new error("Failed to execute query:\n" . $statement . "\nUsing Parameters:\n" . print_r($params, true) . "\nWith Error:\n" . $pdo_error->getMessage());
}
}
catch(error $e)
{
$this->logDBError($e);
$e->emailAdmin();
return false;
}
try
{
if($FETCH_MODE == 'all')
{
$tmp = $stmt->fetchAll();
}
elseif($FETCH_MODE == 'column')
{
$arr = $stmt->fetchAll();
foreach($arr as $key => $val)
{
foreach($val as $var => $value)
{
$tmp[] = $value;
}
}
}
elseif($FETCH_MODE == 'row')
{
$tmp = $stmt->fetch();
}
elseif(empty($FETCH_MODE))
{
return true;
}
}
catch(PDOException $pdoError)
{
return true;
}
$stmt->closeCursor();
return $tmp;
}
public function executeScalar($statement, $params = null)
{
$stmt = $this->prepare($statement);
if(!empty($this->bound_params) && empty($params))
{
$params = $this->bound_params;
}
try {
try {
if(!empty($params))
{
$stmt->execute($params);
}
else
{
$stmt = $this->query($statement);
}
}
catch(PDOException $pdo_error)
{
throw new error("Failed to execute query:\n" . $statement . "\nUsing Parameters:\n" . print_r($params, true) . "\nWith Error:\n" . $pdo_error->getMessage());
}
}
catch(error $e)
{
$this->logDBError($e);
$e->emailAdmin();
}
$count = $stmt->fetchColumn();
$stmt->closeCursor();
//echo $count;
return $count;
}
protected function logDBError($e)
{
$error = $e->getErrorReport();
$sql = "
INSERT INTO " . self::$error_table . " (message, time_date)
VALUES (:error, NOW())";
$this->executeStatement($sql, array(':error' => $error));
}
}
class QueryStatement extends PDOStatement
{
public $conn;
protected function __construct()
{
$this->conn = DB::connect();
$this->setFetchMode(PDO::FETCH_ASSOC);
}
public function execute($bound_params = null)
{
return parent::execute($bound_params);
}
}
BigDecimal
, который является всем смыслом.
– EntangledLoops
2 October 2015 в 14:23