读“三十天三十个 Swift 项目”笔记(下)

30DaysofSwift继续学习中,目测下部分更有趣些,小白笔记继续中···

另外作者在简书上也有记录,自学 iOS - 三十天三十个 Swift 项目

三十天三十个 Swift 项目
十六、上边栏目录菜单的实现 (day16)

在此之前我们可以去拜读一下猫神的iOS7中的ViewController切换,了解下

  • UIViewControllerTransitioningDelegate: 切换中应该发生什么
  • UIViewControllerAnimatedTransitioning: 询问是否需要使用自定义的切换效果

另外详细看看这个View Controller切换效果

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的熟悉。

UIView.Animation

二十六、通过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开发人员,本人还是相当汗颜的,学习!学习啊!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,194评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,058评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,780评论 0 346
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,388评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,430评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,764评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,907评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,679评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,122评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,459评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,605评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,270评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,867评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,734评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,961评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,297评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,472评论 2 348

推荐阅读更多精彩内容

  • 比赛达到高潮,街魂只差两分就能拿下这一局了。 可是,到目前为止,李逸风的数据,居然只有4个失误! 没有得分,没有篮...
    RainyMorning阅读 818评论 0 0
  • 凌云社·赵娅梨 寒风秋月悲寂寥, 穷途末路亦逍遥。 天南地北相环绕, 铁马行川皆自嘲。
    笔渡春秋阅读 372评论 0 1