Swift-高仿半糖App

IOS-Swift2.0 高仿半糖App


寫在前面的話

--少年我是去年畢業做IOS開發的,這個項目大概是2016年1月份到現在做完的,項目剛開始沒學過Swift語言,但想著不會就該去挑戰,于是邊學習邊做這個項目,現在對Swift也有了一定的了解
,在此感謝維尼的小熊的指導

關于項目(GitHub地址在文章最下方)

--這個開源項目為半糖,官網?,類似于美麗說,一款電商App,使用語言:Swift2.0,開發工具: Xcode 7.1,純代碼開發,耗時兩個多月,數據為本地數據,用Charles進行抓包。
--項目測試機為5S,UI沒有對6/6S進行適配
--因為開發時間有限,APP里面的各種分類相當繁多,因此首頁中測試的話點第一個分類,第一個cell,一般都是有數據的,沒有也會提示。
--我是個新手,Bug是難免的嘛。如果發現有Bug和疑問,請向我聯系,QQ、簡書、微博都可以
--Tips:首頁支持3D Touch,可以試試哦~

項目效果圖

首頁展示

首頁輪播圖加展示.gif
首頁-清單展示
首頁-清單展示.gif
首頁-搜索分類展示
首頁-搜索展示.gif

3D Touch展示(用6S及6S以上測試)

3DTouch展示.gif

廣場展示

首頁-廣場展示.gif

秀我展示.gif

消息(這一部分??,我沒好友,沒粉絲,抓包木有數據,所以就按照自己的想法做咯)

消息.gif

個人中心(換頭像請用真機測試~)

個人中心.gif

項目詳細講解 (按APP的啟動順序來)

啟動頁面

啟動頁面.gif

主要代碼如下:
1.在appDelegate中
self.window?.rootViewController = mainViewController()

//MARK: App首次啟動顯示 app的簡介
    func mainViewController() -> UIViewController{
        //firstStart不為空,不是是第一次啟動
        if  NSUserDefaults.standardUserDefaults().objectForKey("FirstStart") != nil {
            return self.tabbarController
        }else {
            //是第一次啟動
            NSUserDefaults.standardUserDefaults().setObject(false, forKey: "FirstStart")
            let firstVC = FirstStartViewController()

            return firstVC
        }
    }

Tips: 用戶第一次啟動App的時候self.window.rootViewController = FirstStartViewController() 使用戶進入引導頁,動畫完成后,點擊『開啟App之旅』,引導頁發出 通知,appDelegate接受通知,再將self.window?.rootViewController = self.tabBarController

首頁-展示

①最好的設計思路應該是這樣的:
tmp4c68a801.png

Tips:以下的思路 在個人中心很完整,前去看看哈

1.紅色部分設計為 collectionHeaderView

方法: 初始化collecitonView時 在其layout參數中設置
layout.headerReferenceSize = CGSizeMake(width, height)
然后collectionView 注冊這個headerView

public func registerClass(viewClass: AnyClass?, forSupplementaryViewOfKind elementKind: String, withReuseIdentifier identifier: String)`
然后 在collectionView代理方法
`func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
        var reuseView = UICollectionReusableView()
        if kind == UICollectionElementKindSectionHeader {
            let headView = collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: "collectionViewHeaderView", forIndexPath: indexPath)
            
            headView.addSubview(collectionHeadView)
            reuseView = headView
        }
        return reuseView
    }
2.綠色部分為collectionView 只作為容器使用
3.藍色部分為顯示的tableview,添加到collectionView的cell.contentView進行顯示

Tips:現在很多App的啟動頁面也是這個思路,整體為一個UICollectionView,每一個cell都添加UITableView進行顯示

②關于cell 動態高度的問題,上圖:

tmp3734bf84.png

藍色的這一部分是清單詳情中的描述內容,JSON中的描述文字都不一樣,所以導致整個cell的高度都是動態不定的
Tips:
1.在cell所有的model中添加cellHeight字段,在tableView代理方法heightForRowAtIndexPath中,判斷model中的cellHeight字段是不是為空,有值則返回該值,類似

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
       //model為對應cell的model
      if model.cellHeight != nil {
             return model.cellHeight
       }
    return 30
}

2.cell中的屬性model 重寫set方法,類似

var model: YourModel{
  didSet{
        //--------
            做你的操作
        //-------
        if model.cellHeight == nil {
        model.cellHeight = 你計算后的高度
        }
    }
}
③ 3D Touch

Tips:其實App中應用最多的也就是不用點進去看。可以預覽下一級顯示的內容,比如 微信

3D Touch通用.gif

上代碼:
viewDidLoad()self.add3DTouch()

//MARK: 添加 3D touch功能
    func add3DTouch() {
        //1.檢測 3D touch 是否可用
        if traitCollection.forceTouchCapability == .Available {
            //3DTouch可用,
            registerForPreviewingWithDelegate(self, sourceView: view)
        }else {
            //不可用
            TipView.showMessage("不支持3Dtouch,換個6S吧,不謝??")    
        }
    }

Tips:
1 registerForPreviewingWithDelegate(delegate: UIViewControllerPreviewingDelegate, sourceView: UIView)方法中delegate即為當前控制器self,sourceView即為感應3DTouch功能的View,當前控制器中,我選擇的是self.view
2.控制器上添加代理UIViewControllerPreviewingDelegate,實現方func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController?func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController),
看代碼:

①這一部分其實就兩個步驟

  • 1.給3D Touch 你要預覽的ViewController
  • 2.設定3D Touch預覽控制器的尺寸大小
func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
        
        
        //-----這一過程這么繁瑣  說白了就是找到當前手指點到的 tableviewCell,后面 3Dtouch 預覽的時候會用到 原尺寸 cell.frame
        let index = Int( showCollectionView.contentOffset.x / SCREEN_WIDTH )
        let collectionViewCell = showCollectionView.cellForItemAtIndexPath(NSIndexPath(forRow: 0, inSection: index))
        var tableView = UITableView()
        for aview in collectionViewCell!.contentView.subviews {
            if aview.isKindOfClass(UITableView.self) {
                tableView = aview as! UITableView
            }
        }
        //*******
        
        let indexPath = tableView.indexPathForRowAtPoint(location)
        let cell = tableView.cellForRowAtIndexPath(indexPath!) as! HomeCell
        
        let detailListContrller = ListDetailViewController(listId: "1872",transImage: cell.imgView.image!)
        
    
        //預顯示的尺寸
        detailListContrller.preferredContentSize = CGSizeMake(SCREEN_WIDTH, 600)
        //源尺寸
        previewingContext.sourceRect = cell.frame
        
        return detailListContrller
    }

②對即將預覽的ViewController,做一些操作,比如隱藏tabbar,隱藏導航欄等等,然后顯示出來

func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController) {
        showViewController(viewControllerToCommit, sender: self)
    }

廣場-展示

設計思路如圖:

tmp4c3452b2.png
與首頁相似,紅色部分View是藍色 mainCollectionView的headerView,紅色View中又包含著一個collectionView
下拉刷新控件:
下拉刷新控件.gif

Tips:下拉刷新控件 使用SVPullToRefresh 框架,然后在它的文件中修改了一個方法,把自己想要出現的動圖加了進去

- (SVPullToRefreshArrow *)arrow {
    if(!_arrow) {
        _arrow = [[SVPullToRefreshArrow alloc]initWithFrame:CGRectMake(0, self.bounds.size.height-54, 22, 48)];
        _arrow.backgroundColor = [UIColor clearColor];
              //將框架自帶的刷新箭頭屏蔽掉
//      [self addSubview:_arrow];
        
        //這一部分是我自定義顯示的View
        UIImageView *gifImgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, self.bounds.size.height-54, 125, 125)];
        self.clipsToBounds = YES;
        gifImgView.backgroundColor = [UIColor whiteColor];
        gifImgView.image = [UIImage sd_animatedGIFNamed:@"refreshGif"];
        //設置刷新動圖只在Loading狀態下顯示
        [self setCustomView:gifImgView forState:SVPullToRefreshStateLoading];

    }
    return _arrow;
}

秀出自我

這一部分的實現思路比較簡單
1.在appdelegate中,實現tabbarControllerDelegate方法,shouldSelectViewController中,判斷每次點擊的是不是ShowMeController,如果是,則返回false,然后在當前的控制器viewController.presentViewController(ShowMeViewController, animated: true, completion: nil)

func tabBarController(tabBarController: UITabBarController, shouldSelectViewController viewController: UIViewController) -> Bool {
        
        
        let childArray = tabbarController.childViewControllers
        let index = childArray.indexOf(viewController)
        if index == 2 {
            print("Show me!")
            presentShowMeViewController(viewController)
            return false
        }else if index == 3 {
            //點擊 '消息中心' 延遲5s 后發出通知
            //模擬網絡刷新
            viewController.tabBarItem.title = nil
            postNotificationCenter(tabbarController.viewControllers!)
        }
        
        return true
    }

2.對于調用照相機的方法,首先判斷有沒有攝像頭

if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera) {
            imagePicker.sourceType = UIImagePickerControllerSourceType.Camera
            presentViewController(imagePicker, animated: true, completion: nil)
        }else {
            TipView.showMessage("騷年,找個有攝像頭的手機吧。。")
        }

然后viewController中添加代理 UIImagePickerControllerDelegate,UINavigationControllerDelegate
在代理方法中可以獲取到剛拍好的圖片進行處理

func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
        dispatch_async(dispatch_get_main_queue()) { () -> Void in
            picker.dismissViewControllerAnimated(true, completion: nil)
            self.topView.headerImage = image
        }
        
    }

消息這一部分就很少東西了,因為我沒有粉絲,沒有消息??,

為了模擬后臺發送消息,在tabBarController的"shouldSelectViewController"中,當點擊該控制器時,appdelegate發出通知,MessageViewController中接收通知,提示用戶收到消息
//接受 模擬后臺的推送、、、、 NSNotificationCenter.defaultCenter().addObserver(self, selector: "hasNewMessage", name: UserHasNewMessage, object: nil)

收到通知以后執行的方法:

func hasNewMessage(){
        print("收到通知了。")
        TipView.showMessage("您有新的消息。但是你看不見??")
    }

個人中心

這一部分設計思路與廣場類似,也都是上面是HeaderView,下面是UICollectionView,不同的是個人中心最上面有一個背景圖片,會隨著collectionView的contentOffSet變化而放大
設計思路:


tmp2ae3bf03.png

1.黃色View為 UIImageView,處于整個View的下層,collectionView和它的headerView的backgroundColor = UIColor.clearColor()
最后在func scrollViewDidScroll(scrollView: UIScrollView)中調整 backImageView的transform屬性即可
2.關于停靠問題,

停靠問題.gif

上圖
tmp19a4b2b9.png

,姑且叫它titleView, titleView滾到設定位置時會停靠到導航欄底下,思路如下:

  1. titleView是添加到headerView中的,在scrollViewDidScroll方法中,監聽collectionView的contentOffset.y的變化,當titleView到達設定的位置時,titleView.removeFromSuperview(),然后計算frame,將其添加到View上,這樣就做除了停靠的效果,這樣做比較簡單
    ??: 剛開始我單獨將titleView添加到view上,collectionView滑動時還得一直更改titleView.frame

聊聊感想哈

其實從OC轉向Swift非常簡單,這個項目不難,很適合從OC轉向swift,或swift初學者。
少年也是第一次發布自己的項目,忘老鳥輕拍,新手共勉,有什么問題或bug聯系我哈,歡迎來我的GitHub上賞個Star??

GitHub 代碼下載地址

代碼下載地址,給個star再走??
直接打開運行工程

tmp1cbb03b9.png

收到有童鞋反應說,會遇到這樣的Bug導致無法運行

tmp788532b0.png

Tips:由于GitHub上傳的問題,解決辦法如下:

tmp44a0f1ff.png

項目編寫中用的切圖、標注、及本地數據在我的百度云

切圖、數據下載地址-ManoBpp的百度云

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,527評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,687評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,640評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,957評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,682評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,011評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,009評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,183評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,714評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,435評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,665評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,148評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,838評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,251評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,588評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,379評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,627評論 2 380

推薦閱讀更多精彩內容