30DaysofSwift继续学习中,目测下部分更有趣些,小白笔记继续中···
另外作者在简书上也有记录,自学 iOS - 三十天三十个 Swift 项目
十六、上边栏目录菜单的实现 (day16)
在此之前我们可以去拜读一下猫神的iOS7中的ViewController切换,了解下
-
UIViewControllerTransitioningDelegate
: 切换中应该发生什么 -
UIViewControllerAnimatedTransitioning
: 询问是否需要使用自定义的切换效果
另外详细看看这个View Controller切换效果。
以及调用snapshotViewAfterScreenUpdates
创建一个复合视图的快照,就是截屏。
另外要注意一下 Storyboard unwind segues使用小结,这样也不失为不使用 delegate 模式传递回调数据的好方法。
这个Demo中可以深究的地方有蛮多的,有空再单独做笔记的
十七、模仿微博点击Tab中编辑后弹出的效果 (day17)
再次学习ViewController的动画切换,对Transitioning
更加了解···
private var presenting = false
//MARK:-UIViewControllerContextTransitioning
// 完成容器转场动画的主要方法,我们对于切换时的UIView的设置和动画都在这个方法中完成
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
}
// 系统给出一个切换上下文,我们根据上下文环境返回这个切换所需要的花费时间
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 0.5
}
//MARK:- UIViewControllerTransitioningDelegate
// 呈现VC时CallBack的方法
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
self.presenting = true
return self
}
//解散VC时CallBack的方法
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
self.presenting = false
return self
}
在animateTransition
中的实现
1、我们需要得到参与切换的两个ViewController的信息,使用context的方法拿到它们的参照;
2、对于要呈现的VC,我们希望它什么样的方式入场,Transform
的设置;
3、将view添加到containerView中;
4、开始动画。这里的动画时间长度和切换时间长度一致。
5、在动画结束后我们必须向context报告VC切换完成,是否成功。系统在接收到这个消息后,将对VC状态进行维护
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
// 初始化
let container = transitionContext.containerView()
// 得到参与切换的两个ViewController的信息,使用context的方法拿到它们的参照
let screens : (from:UIViewController, to:UIViewController) = (transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!, transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!)
let menuViewController = !self.presenting ? screens.from as! MenuViewController : screens.to as! MenuViewController
let bottomViewController = !self.presenting ? screens.to as UIViewController : screens.from as UIViewController
let menuView = menuViewController.view
let bottomView = bottomViewController.view
//对于要呈现的VC,我们希望它以什么样的方式入场
if (self.presenting) {
// 初始化需要建立好的 Transform
self.offStageMenuController(menuViewController)
}
//将view添加到containerView中
container!.addSubview(bottomView)
container!.addSubview(menuView)
// 后面是开始动画啦
let duration = self.transitionDuration(transitionContext)
UIView.animateWithDuration(duration, delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.8, options: [], animations: {
if (self.presenting){
self.onStageMenuController(menuViewController)
} else {
self.offStageMenuController(menuViewController)
}
}, completion: { finished in
// 在动画结束后我们必须向context报告VC切换完成,是否成功。系统在接收到这个消息后,将对VC状态进行维护
transitionContext.completeTransition(true)
UIApplication.sharedApplication().keyWindow!.addSubview(screens.to.view)
})
}
十八、键盘的弹出跟随InputAccessoryView(day18)
首先顺便归纳下,让键盘下移的常用三种方法
// 方法一、UIApplication.sharedApplication().keyWindow
@IBAction func tapDownAction(sender: AnyObject) {
UIApplication.sharedApplication().keyWindow?.endEditing(true)
}
// 方法二、textField的resignFirstResponder方法
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
// 方法三、任意点击屏幕
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.view.endEditing(true)
}
而此Demo主要的是通知的运用和动画小弹出的熟练了,注意userInfo
字典的key
let keyBoardBounds = (userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()
let duration = (userInfo![UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
// 这个options的转换,很有意思
let options = UIViewAnimationOptions(rawValue: UInt((userInfo![UIKeyboardAnimationCurveUserInfoKey] as! NSNumber).integerValue << 16))
最要注意UIKeyboardAnimationCurveUserInfoKey
转换成 UIViewAnimationOptions
的过程。
十九、加闪烁字体的刷新效果 (day19)
首先了解下 UIViewAnimationOptions
动画速度控制的几个参数;
CurveEaseInOut: UIViewAnimationOptions // 动画先缓慢,然后逐渐加速
CurveEaseIn: UIViewAnimationOptions // 动画逐渐变慢
CurveEaseOut: UIViewAnimationOptions // 动画逐渐加速
CurveLinear: UIViewAnimationOptions // 动画匀速执行
对CGAffineTransform
进一步了解
总得来说,这个类中包含3张不同类型,分别使用如下3个方法创建数值;
1.CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty)(平移:设置平移量)
2.CGAffineTransformMakeScale(CGFloat sx, CGFloat sy)(缩放:设置缩放比例)仅通过设置缩放比例就可实现视图扑面而来和缩进频幕的效果。
3.CGAffineTransformMakeRotation(CGFloat angle)(旋转:设置旋转角度)
以上3个都是针对视图的原定最初位置的中心点为起始参照进行相应操作的,在操作结束之后可对设置量进行还原:
view.transform=CGAffineTransformIdentity;
二十、CollectionView中点击Cell直接放大Cell (day20)
首先先说一个问题,之前我看作者也是这样的,就是我们在设置Item的时候直接将它的size 设置死了,是不适配的,所以此时是否还是要用呢,或者换成UITableView其实也OK 的,毕竟一行只有一个item。
当然先看看核心代码
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
// 获取当前Cell
let cell = collectionView.cellForItemAtIndexPath(indexPath) as! TestCollectionViewCell
// 并把到放在最前面
cell.superview?.bringSubviewToFront(cell)
// 动画效果
UIView.animateWithDuration(0.5, delay: 0.0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: [], animations: { () -> Void in
cell.frame = self.collectionView.frame
self.collectionView.scrollEnabled = false
cell.backButton.hidden = false
cell.backButton.addTarget(self, action: Selector("backButtonDidTouch"), forControlEvents: UIControlEvents.TouchUpInside)
}, completion: nil)
}
func backButtonDidTouch() {
self.collectionView?.scrollEnabled = true
//选中的cell
let indexPath = self.collectionView!.indexPathsForSelectedItems()
//刷新当前 index,恢复成原来的位置
self.collectionView?.reloadItemsAtIndexPaths(indexPath!)
}
二十一、cell左边滑动删除或其他 (day21)
注意UITableViewRowAction
创建删除按钮和 UIActivityViewController
在应用里为分享和操作数据提供了一个统一的服务接口
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
let delete = UITableViewRowAction(style: .Normal, title: "Delete"){
(action: UITableViewRowAction!, indexPath: NSIndexPath) -> Void in
// 删除某一行
self.dataArray.removeAtIndex(indexPath.row)
self.tableView.reloadData()
}
delete.backgroundColor = UIColor.redColor()
let share = UITableViewRowAction(style: .Normal, title: "Share") { (action: UITableViewRowAction!, indexPath: NSIndexPath) -> Void in
// 分享某个东西
let firstActivityItem = self.dataArray[indexPath.row]
let activityViewController = UIActivityViewController(activityItems: [firstActivityItem as NSString], applicationActivities: nil)
self.presentViewController(activityViewController, animated: true, completion: nil)
}
share.backgroundColor = UIColor.greenColor()
return [delete, share]
}
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
// 确保上面那个方法生效,可以什么都不写
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
}
二十二、3D Touch 的使用(day22)
可以去看这篇文章iOS9系列专题一——3D Touch,虽说模拟器也可以通过安装插件尝试,但是还是想着后期真机尝试,那感觉偷懒的有价值,😄。
发现这篇也不错iOS9-by-Tutorials-学习笔记九:3D-Touch/
二十三、侧滑效果的实现 (day23)
Demo基于SWRevealViewController这个来实现的。
初次使用的时候,如果是用storyBoard的需要注意
NSString * const SWSegueRearIdentifier = @"sw_rear";
NSString * const SWSegueFrontIdentifier = @"sw_front";
NSString * const SWSegueRightIdentifier = @"sw_right";
也就是默认跳转的几个segue
的标识。
二十四、滑动图片时循序渐进的出现,瀑布流中一个很好效果(day24)
逐渐变化是用透明度的,item的size是用FMMosaicLayout自适应的,处理更方便。
透明度变化的效果:
let randomBlue = CGFloat(drand48())
let randomRed = CGFloat(drand48())
let randomGreen = CGFloat(drand48())
cell.backgroundColor = UIColor(red: randomRed, green: randomGreen, blue: randomBlue, alpha: 1.0)
cell.alpha = 0
let cellDelay = UInt64((arc4random() % 600 ) / 1000 )
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(cellDelay * NSEC_PER_SEC )), dispatch_get_main_queue(), ({ () -> Void in
UIView.animateWithDuration(0.8, animations: ({
cell.alpha = 1.0
}))
}))
二十五、常用的动画效果展示(day25)
Position
,Opacity
, Scale
,Color
,Rotation
其实也是对这个方法的熟练,以及CGAffineTransform
的熟悉。
二十六、通过UIAlertController增加UITableViewCell和删除 (day26)
也是对UIAlertController
的熟悉下
let alert = UIAlertController(title: "AddNew", message: "", preferredStyle: UIAlertControllerStyle.Alert)
alert.addTextFieldWithConfigurationHandler({
(textField) in
textField.placeholder = "add content data"
})
let alertOK = UIAlertAction(title: "OK", style: .Default, handler:({
(action: UIAlertAction) -> Void in
let inputField = (alert.textFields?.first)! as UITextField
self.dataArray .append(inputField.text!)
self.tableView.reloadData()
}))
let alertCancel = UIAlertAction(title: "Cancel", style: .Cancel, handler:({
(action: UIAlertAction) -> Void in
print("cacel Handle")
}))
alert.addAction(alertOK)
alert.addAction(alertCancel)
self.presentViewController(alert, animated: true, completion: nil)
二十七、TabBar
storyBoard 制作tabBar,并且回顾了之前那个动画让cell走动,以及几个动画效果的实现,算是对前几次的一个回顾吧,综合练习题。
二十八、通过外部的搜索,直接进入APP里面
也就是CoreSpotlight
框架的使用,这个框架可以为iOS的搜索提供一些App内部的数据,能够使我们在iPhone上下拉出现得搜索框中,搜索我们使用的App中的内容。
了解一下Core Spotlight Framework搜索App的内容
二十九、模仿QQ选择图片,直接在界面浏览相册
作者用了ImagePickerSheetController,确实方便简单,但是目前github 上貌似没有更新, 暂时不怎么好用,可以直接用作者提供的。
let controller = ImagePickerSheetController()
controller.addAction(ImageAction(title: NSLocalizedString("Take Photo or Video", comment: "Action Title"), secondaryTitle: NSLocalizedString("Use this one", comment: "Action Title"), handler: { (_) -> () in
}, secondaryHandler: { (action, numberOfPhotos) -> () in
controller.getSelectedImagesWithCompletion({ (images) -> Void in
self.profileImage = images[0]
self.userProfileImageView.image = self.profileImage
})
}))
controller.addAction(ImageAction(title: NSLocalizedString("Cancel", comment: "Action Title"), style: .Cancel, handler: nil, secondaryHandler: nil))
presentViewController(controller, animated: true, completion: nil)
最近发现了一个新的HySideScrollingImagePicker,对于选择图片的做的也不错,可以看看。
三十、通过搜索名字展现图片
首先是网络请求,它这边寻找的图像是需要翻墙的,其次对人脸的识别处理可以了解下。
#使用Core Image来检测眨眼以及微笑
// 获得图片
let faceImage = imageView.image
// 初始化 CIDetector
let detector = CIDetector(ofType: CIDetectorTypeFace, context: CIContext(options: nil), options: [CIDetectorAccuracy:CIDetectorAccuracyHigh])
// 转化CIImage
let ciImage = CIImage(CGImage: faceImage!.CGImage!)
// 识别图片
let features = detector.featuresInImage(ciImage)
if features.count > 0 {
// 去获得特征
var face:CIFaceFeature!
for rect in features
{
face = rect as! CIFaceFeature
}
// 检查笑脸
if (face.hasSmile)
{
print("笑了");
}
else
{
print("没有笑");
}
// 当然眼睛的位置和嘴巴的位置也可以找到的
/*
public var bounds: CGRect { get }
public var leftEyePosition: CGPoint { get }
public var rightEyePosition: CGPoint { get }
public var mouthPosition: CGPoint { get }
*/
}
总的说来,通过这些Demo重写,让我基本对Swift以及iOS好多知识点有了进一步的认识,当然有好多方面的也没有深入,同时这边最大的感觉应该是对动画效果没有那么畏惧了,不会像以前觉的动画效果感觉很难的似的。当然里面Demo中有一些编码习惯是可以有选择的,但是想想作者并不是专业的iOS开发人员,本人还是相当汗颜的,学习!学习啊!