第五天--微博的展示

前言

公司忙着开放发功能,一直都都没时间来更新,废话不多。今天主要完成的功能
1、微博列表的展示
2、下拉刷新和上拉加载更多
3、点击查看大图和长按图片保存的本地相册。
首先来来张效果图

5.gif

1、普通微博界面的UI

我把其分为三部分,如下图

1.1、布局分析
个人信息和微博内容为一部分(偷懒没有自定义view)
图片展示用CollectView来展示
底部三个按钮则是用xib拖得的View
布局的话用AutoLayout的第三方SnapKit来进行布局的。
这里就不贴代码了。
1.2不等高Cell问题的解决
由于不同的微博内容,导致cell的高度不同,因此需要定义一个方法来获取cell的高度。

// MARK:计算cell的高度
func getCellHeight(status:YJStatus) -> CGFloat {
    
    self.status = status
    
    layoutIfNeeded()

    
    return CGRectGetMaxY(bottomToolBar.frame);
}

该方法在cell的返回高度的地方调用,

 override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    
    let status = statusArry[indexPath.row]

    let height = calCell.getCellHeight(status)

    print("计算高度")
    return height
}

注意:这里的calCell我是懒加载一个专门用来计算cell高度的cell,懒加载的目的是不要重复创建cell。因为使用下面方法获取cell计算的高度是有问题的。所以暂时这样计算高度。

  let cell = tableView.dequeueReusableCellWithIdentifier(reuseID)

2、数据的处理

微博官网文档的数据结构如下(截图不完整


3C9F9DD7-A130-41F3-92D2-35C6F9D34444.png


从上图中我们中我们可以看出返回的包含微博对象的数组,微博对象中又包含了User对象。因此我们需要新建两个对象,将返回的数据包装到两个对象中,方法使用。

微博对象

class YJStatus: NSObject

用户对象

class YJUser: NSObject

重写init方法将字典转为对象

 init(dict: [String:AnyObject]) {
    
    super.init()
    
    setValuesForKeysWithDictionary(dict)
}

这里重写setValueForKey是为叫user转为对象

override func setValue(value: AnyObject?, forKey key: String) {
    
    
    if key == "user" {
        
        user = YJUser(dict: value as![String:AnyObject])
        return
    }
    super.setValue(value, forKey: key)
}

因为我创建的对象YJStatus没包含数据中所有的key值,所有需要重写下面的方法,防止程序崩溃,注意不需要实现

   //重写该方法是为不崩溃
override func setValue(value: AnyObject?, forUndefinedKey key: String) {
    
}

有了数据后,剩下就是把数据赋值给cell,然后更新UI。以前OC中我一般会重写model的set方法,在该方法中去更新UI,swift中我的写法如下,在didSet中赋值,更新UI,其他和OC中一样。

 //微博模型
var status:YJStatus?{

    didSet {
    
        //在这里赋值
        sourceLabel.text = status?.source
        
        contentLabel.text  = status?.text
        
        crateTimeLabel.text = status?.created_at
        
        userIconImageView.sd_setImageWithURL(status?.user!.iconURL)
        nickNameLabel.text = status?.user?.name
        
        
        //给缩略图片赋值
        pictureView.imageURLS = status!.thumbURLs
        
        // 赋值给大图
        pictureView.largeURLs = status!.largeURLs
        
        //图片赋值完后计算图片大小,更新约束
        let size = pictureView.calPictureSize()
        
        print(size)

        self.pictureHeighCons?.constraint.updateOffset(size.height)
        self.pictureWidthCons?.constraint.updateOffset(size.width)
    }
}

这里另外讲下微博时间的处理,因为返回的时间并不是我们想要的格式,我们需要对其处理,在给时间赋值的didSet方法中进行处理,处理如下

 //微博的创建时间
var created_at: String? {

    didSet {
    
        //在这里处理时间
        //先把时间处理为NSDate
        let formatter = NSDateFormatter()
        
        //设置时间的格式
        formatter.dateFormat = "EEE MMM d HH:mm:ss Z yyyy"
        // 设置时间的区域
        formatter.locale = NSLocale(localeIdentifier: "en")
        
        // 转化为NSDate
        let cratedDate = formatter.dateFromString(created_at!)
        
        if let realDate = cratedDate {
        
            //在这里与当前时间比较
            //获取当前日历
            let currentCalendar = NSCalendar.currentCalendar()
            
            if currentCalendar.isDateInToday(realDate) {
                
                //如果在今天之内
                //计算当前时间和系统时间之差
                let interval = Int(NSDate().timeIntervalSinceDate(realDate))
                
                if interval<60 {
                    created_at = "刚刚"
                }
                if interval<60*60 {
                    
                    created_at = "\(interval/60)分钟前"
                }
                
                created_at = "\(interval/60/60)小时前"
            }
            
            // 2.判断是否是昨天
            var formatterStr = "HH:mm"
            if currentCalendar.isDateInYesterday(realDate) {
                
                formatterStr = "昨天:" + formatterStr
            }
            else {
            
                //处理一年以内
                formatterStr = "MM-dd " + formatterStr
                
                //获取年份
                let comps = currentCalendar.components(NSCalendarUnit.Year, fromDate: realDate, toDate: NSDate(), options:  NSCalendarOptions(rawValue: 0))
                
                if comps.year >= 1 {
                    
                    formatterStr = "yyyy-" + formatterStr
                }
                
            }
            
            
            //设置格式化
            formatter.dateFormat = formatterStr
            created_at = formatter.stringFromDate(realDate)
            
        }
        
        
    }
}

3、点击查看大图的实现

分析:点击图片的present一个控制器用来展示大图,和起对象处于哪一张,所以点击的时候需要把大图的数组和图片对应的索引传递给首页的控制。由于View的层级超过了三层,我们就不用闭包了,采用通知的形式。在collectionVIew的点击事件中发送通知,实现如下:

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
 
    
    print("我是图片我被点击拉")

    //在这里发送通知,info中包含大图数组,和被点击图片所在的索引
    let info:[String:AnyObject] = [YJLargeURLSkey:largeURLs!,YJIndexKey:indexPath]
    NSNotificationCenter.defaultCenter().postNotificationName(YJShowPhotoBrowerNotification, object: nil, userInfo: info)
}

在主控制器注册通知

// 注册显示图片浏览器的通知
    NSNotificationCenter.defaultCenter().addObserverForName(YJShowPhotoBrowerNotification, object: nil, queue: nil) { (notice) in
        
        
        if let info = notice.userInfo {
        
            //通知处理
            let photoBrowserVC = YJPhotoBrowseViewController()
            photoBrowserVC.sourceImageURLs = info[YJLargeURLSkey] as?[NSURL]
            photoBrowserVC.clickIndex = (info[YJIndexKey] as! NSIndexPath).row
            
            self.presentViewController(photoBrowserVC, animated: true, completion: nil)
            
        }
        
    }

注意记得移除通知

//MARK: 移除通知
deinit {

NSNotificationCenter.defaultCenter().removeObserver(self)
}

YJPhotoBrowseViewController的实现,也是collectinVIew来实现。
定义两个变量,一个是图片数组,还有就是记录被点击图片的索引

 // 图片数组
var sourceImageURLs:[NSURL]?{

    didSet {
    
        collectView.contentSize = CGSizeMake(CGFloat(sourceImageURLs!.count)*UIScreen.mainScreen().bounds.size.width, UIScreen.mainScreen().bounds.size.height)
    }
}

// 点击图片的所在索引
var clickIndex:Int? {

    didSet {
    
        topLabel.text = "\(clickIndex! + 1)/\(sourceImageURLs!.count)"
        
        let offSetX = (CGFloat(clickIndex!)*UIScreen.mainScreen().bounds.size.width)
        
        print(offSetX)
        collectView.contentOffset = CGPointMake(offSetX, 0)
    }
}

在图片的didSet中设置collectionVIew的contensize,在索引didSet中设置contenOffset。

大图的展示和图片比较大的显示进度的图片处理

var photoURL:NSURL?{

    didSet {
    
        
        // 重置起状态
        reset()
        
        // 下载图片
        SDWebImageManager.sharedManager().downloadWithURL(photoURL, options: SDWebImageOptions.HighPriority, progress:{ (totalSize, receiveSize) in
            
            
            SVProgressHUD.showProgress(Float(receiveSize)/Float(totalSize))
           
            if totalSize ==  receiveSize {
                
                SVProgressHUD.dismiss()
            }
            
        }) { (originImage, _, _, _) in
            
            
            if originImage == nil {
            
                return
            }
            let originWidth = originImage.size.width
            let originHeight = originImage.size.height
            let screenWidth = UIScreen.mainScreen().bounds.size.width
            let screenHeight = UIScreen.mainScreen().bounds.size.height
            let realImageHeight = (originWidth/originHeight)*screenWidth
            
            if realImageHeight<screenHeight {
                 self.photeImageView.frame = CGRectMake(0, (screenHeight - realImageHeight)*0.5, screenWidth , realImageHeight)
            }else {
            
                
                self.photeImageView.frame = CGRectMake(0, 0, screenWidth, originHeight)
                
                self.backScrollView.contentSize = CGSizeMake(screenWidth, realImageHeight)
            }
            
            
            self.photeImageView.image = originImage
        }
       
    }
}

点击图片dimiss和长按保存的实现,给图片添加分别添加一个tap手势和长按手势,然后通过闭包传递事件给YJPhotoBrowseViewController

首先定义两个闭包

//图片单击一闭包
var imageClick:(()->())?

//图片长按闭包,传递需要保存的图片参数
var imageLongPress:((saveImage:UIImage)->())?

给图片添加tap和长按手势

 //图片添加一个点击事件
    let tap = UITapGestureRecognizer.init(target: self, action: "tapClick")
    photeImageView.userInteractionEnabled = true
    photeImageView.addGestureRecognizer(tap)
    
    //给图片添加一个长按手势
    let longPressGesture = UILongPressGestureRecognizer.init(target: self, action: "longPressAction:")
    photeImageView.addGestureRecognizer(longPressGesture)

事件方法

 //MARK:点击事件
func tapClick() {
    
  imageClick?()
}

//MARK:长按点击事件
func longPressAction(longPressGeture:UILongPressGestureRecognizer){

    
    let clickImageView = longPressGeture.view as! UIImageView
    if longPressGeture.state == .Ended {
        
        //长按收拾结束哦
        print("长按保存图片可以吗")
        imageLongPress?(saveImage:clickImageView.image!)
    }
}

在控制返回cell进行事件处理

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    
    
    let cell = collectView.dequeueReusableCellWithReuseIdentifier(YJPhotoBrowseViewReuseID, forIndexPath: indexPath) as! YJPhotoBrowserCell
    
    cell.backgroundColor = UIColor.yj_randomColor()
    
    cell.photoURL = sourceImageURLs![indexPath.row]
    
    
    // 图片的点击事件
    cell.imageClick = {
    
        //dismiss
        self.dismissViewControllerAnimated(true, completion: nil)
    }
    
    // 长按保存图片的点击事件
    cell.imageLongPress = {
    
        (saveImage:UIImage)->() in
    
        self.saveImage = saveImage
        //保存图片到相册
        let alertView = UIAlertView()

        alertView.message = "保存图片到相册?"
        alertView.addButtonWithTitle("取消")
        alertView.addButtonWithTitle("保存")
        alertView.delegate = self
        alertView.show()
        
        
    }
    
    
    return cell
    
}

保存图片的方法如下

 UIImageWriteToSavedPhotosAlbum(saveImage!, self, "image:didFinishSavingWithError:contextInfo:", nil)

保存的结果OC中会在该方法中回调, - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo;
坑爹的事没有swift方法函数,我们只能直接将OC方法改成swift中的写法,处理如下。

 func image(image:(UIImage),didFinishSavingWithError error:(NSError?) ,contextInfo:(AnyObject)){

    if error != nil {
        
        SVProgressHUD.showErrorWithStatus("保存失败", maskType: SVProgressHUDMaskType.Black)
    }
    else {
    
        SVProgressHUD.showSuccessWithStatus("保存成功", maskType: SVProgressHUDMaskType.Black)
    }
}

还有图片的缩放,我是利用了UIScorllView的缩放来实现。

今天就到这里,晚安!!!

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

推荐阅读更多精彩内容