高仿小日子Swift2.0

不知不覺十一馬上到了,承諾給大家分享的Swift項目也該兌現(xiàn)了,本次項目為高仿小日子,廢話不多說,先看效果吧


探店效果圖
探店效果圖

探店詳情頁效果圖
探店詳情頁效果圖

附近地圖效果圖
附近地圖效果圖

體驗效果圖
體驗效果圖

分類效果圖
分類效果圖

我的效果圖
我的效果圖

搜索效果圖
搜索效果圖

搖一搖效果圖
搖一搖效果圖

更多效果請用Xcode7.0正式版運(yùn)行程序查看

此項目相對來說比較簡單,之前用Swift1.2編寫的,9月18號,蘋果發(fā)布了Xcdoe7.0正式版,小熊也將代碼更新到了Swift2.0,由于Swift語言還不穩(wěn)定,每個版本都會出現(xiàn)語法修改,本項目用最新的Xcode7正式版編寫,建議使用Xcode7正式版運(yùn)行工程,項目的接口依然有加密,抱著學(xué)習(xí)的態(tài)度,小熊截取了網(wǎng)絡(luò)請求返回數(shù)據(jù),并且將數(shù)據(jù)寫入到了本地,所以讀者用到的數(shù)據(jù)都是固定的

本來想挑一個復(fù)雜點的項目分享給大家,考慮到公司的項目要在十一前上線,時間比較緊,以及自己對Swift語言還處于摸索階段,經(jīng)常也是連蒙加猜的,很多寫法還是沿用OC的套路,不過相信對于大家學(xué)習(xí)Swift語言還是有一定幫助的.很多時候,小熊都是被一個很簡單的語法卡住很久,比如如何動態(tài)實例化AnyClass對象,還有升級到2.0后,通過NSStringFromClass:方法創(chuàng)建對象是需要追加命名空間的前綴,我記憶很深刻...

此次寫代碼的過程中吸取了讀者的提議,用的源代碼管理工具是git,大家可以在項目的歷史版本回退查看項目的從無到有是如何一步一步完善的,由于白天上班,晚上寫這個項目,所以中間博客沒有怎么更新,讀者也可以從代碼提交時間看出...都是半夜1 . 2點左右

在學(xué)習(xí)Swift語言中,自己也斷斷續(xù)續(xù)的總結(jié)了一些OC和Swift語法的區(qū)別,以及Swift于OC中相同方法的不用寫法,我也會在后續(xù)時間發(fā)布到博客里,讓大家避免不必要的麻煩,請持續(xù)關(guān)注小熊的博客


下面來介紹此項目的每個模塊的思路,這里就按照程序運(yùn)行展示的頁面的順序逐一與大家分析吧

引導(dǎo)頁(新特性頁面)

  • 引導(dǎo)頁只在用戶第一次運(yùn)行程序,或者APP升級后第一次運(yùn)行程序時候出現(xiàn),為了是提示用戶APP的新功能以及改變如下圖所展示的效果

    引導(dǎo)頁
    引導(dǎo)頁

  • 目前比較主流的方法是使用UICollectionview來實現(xiàn)引導(dǎo)頁可以直接復(fù)用,如果只是單純的圖片和簡單的動畫建議使用UICollectionview,如果有比較復(fù)雜的動畫,也可以用ScrollView來實現(xiàn),根據(jù)項目的不同需求來選擇,這里的引導(dǎo)頁只有一頁,我就直接用的View

  • 在程序啟動成功的方法中,首先判斷用戶是否是第一次運(yùn)行當(dāng)前版本的APP,我的做法是用版本號來判斷,首先在info中拿出當(dāng)前程序的版本號,在從UserDefaults取出上次用戶運(yùn)行程序的版本號對比,如果相等,說明沒有新版本,直接進(jìn)入,如果不相等則顯示導(dǎo)引頁,并且將當(dāng)前版本寫入UserDefaults中,以便下次用戶運(yùn)行APP判斷.具體代碼如下,返回的控制器作為keyWindow的rootViewController,如果是引導(dǎo)頁,并且用戶點擊了體驗按鈕,可以發(fā)出通知,將KeyWindow的rootViewController切換即可

privete func showLeadpage() -> UIViewController {
    let versionStr = "CFBundleShortVersionString"
    let cureentVersion = NSBundle.mainBundle().infoDictionary![versionStr] as! String
    let oldVersion = (NSUserDefaults.standardUserDefaults().objectForKey(versionStr) as? String) ?? ""

    if cureentVersion.compare(oldVersion) == NSComparisonResult.OrderedDescending {
    NSUserDefaults.standardUserDefaults().setObject(cureentVersion, forKey: versionStr)
    NSUserDefaults.standardUserDefaults().synchronize()
    return LeadpageViewController()
    }

UITabbarController(KeyWindow.rootViewController)

  • 這里小熊自己定義的MainTabBarController繼承至UITabBarController,里面裝了四個MainNavigationController繼承UINavigationController作為子控制器
  • MainNavigationController繼承UINavigationController,重寫了pushViewController方法,方便統(tǒng)一管理返回按鈕和每次Push出新的控制器,自動隱藏底部的TabBar,具體代碼如下
 override func pushViewController(viewController: UIViewController, animated: Bool) {

    if self.childViewControllers.count > 0 {
        let vc = self.childViewControllers[0]

        if self.childViewControllers.count == 1 {
            backBtn.setTitle(vc.tabBarItem.title!, forState: .Normal)
        } else {
            backBtn.setTitle("返回", forState: .Normal)
        }

        viewController.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backBtn)
        viewController.hidesBottomBarWhenPushed = true
    }

    super.pushViewController(viewController, animated: animated)
}

左上角的城市

  • 由于探店, 體驗, 分類都有城市選擇按鈕,并且一個改變,其余的也都會改變,我的做法是提供一個父類,MainViewController繼承至UIViewController,設(shè)置navigationItem.leftBarButtonItem為自定義的按鈕,并且在viewDidLoad:方法中,添加通知,監(jiān)聽city的改變,一旦監(jiān)聽到當(dāng)前城市發(fā)生改變的通知后,對應(yīng)的控制器就可以執(zhí)行對應(yīng)的操作,需要注意的是每次要將改變后的城市寫入到本地持久化存儲,以便程序被關(guān)閉后再次運(yùn)行時,可以保留上次用戶所選擇的城市
  • 選擇城市的控制器是CityViewController如下圖,城市的展示小熊用的UICollectionview來展示的,需要注意每次ViewController彈出后,用戶上一次選擇的城市都會自動進(jìn)入選中狀態(tài),具體實現(xiàn)是拿出上一次用戶選擇的城市,遍歷城市列表取出所屬的indexPath,然后執(zhí)行下面方法
    let lastSelectedCityIndexPaht = selectedCurrentCity()
    collView.selectItemAtIndexPath(lastSelectedCityIndexPaht, animated: true, scrollPosition: UICollectionViewScrollPosition.None)
城市選擇控制器
城市選擇控制器
  • 當(dāng)用戶再次選擇城市后,將城市寫入到本地保存,并且發(fā)出城市改變的通知,通知監(jiān)聽者做出相應(yīng)的操作

探店如下圖所示

探店效果圖
探店效果圖
  • 導(dǎo)航條上的美天和美輯是將navigationItem.titleView 設(shè)置為自定義的DoubleTextView來實現(xiàn),內(nèi)部封裝好功能,并且通過設(shè)置代理將點擊事件傳遞給控制器,順便提一嘴,Swift中的代理和OC中的一樣,也是采用軟引用即:weak var delegate: <Delegate>?,提供一個方法便于在scrollView的offsetX發(fā)生改變時更新內(nèi)部控件狀態(tài)具體實現(xiàn)請參考項目中的代碼

  • 在view的最底層添加一個scrollView,設(shè)置scorllView的contentSize為屏幕的寬度的2倍,在scrollView上添加倆個TableView,分別是美天的TableView和美輯的TabelView,注意觀察,美天tableViewCell有一種cell的樣式于美輯的樣式是一樣的,所以這里只用了兩種cell,參考下圖,這里是根據(jù)服務(wù)器返回數(shù)據(jù)來判斷加載哪一種cell,美天的tableView采用的是樣式是Group樣式,每一組有一個或者多個cell


    EventCell樣式效果圖
    EventCell樣式效果圖

    ThemeCell樣式效果圖
    ThemeCell樣式效果圖
  • 在TableView的代理方法中,根據(jù)服務(wù)器返回的數(shù)據(jù)創(chuàng)建對應(yīng)的cell,喜歡專研的朋友可以查看項目中CustomData文件中的events.json文件查看規(guī)律

  • 這里提一下Swift的閉包方法中,需要像OC中一樣創(chuàng)建一個weak的指針weak var tmpSelf = self,在閉包方法中調(diào)用tmpSelf,直接調(diào)用self會引起循環(huán)引用,照成內(nèi)存泄露,控制器無法被銷毀問題

  • 點擊EventCell彈出的詳情頁我著重講一下,先看效果圖


    美天詳情效果圖
    美天詳情效果圖
  • 頂部的導(dǎo)航條是自定義的view,在EventViewController的viewWillAppaer方法中,將系統(tǒng)的導(dǎo)航條隱藏掉,添加定義的view作為導(dǎo)航條,按鈕也是如此,根據(jù)scrollView的偏移量計算透明度,圖片的拉伸和按鈕的圖片改變,由于有倆個scrollView,有些效果需要判斷不同scrollView來執(zhí)行,需要注意的是適當(dāng)添加標(biāo)記來防止重復(fù)判斷,消耗內(nèi)存

  • 店發(fā)現(xiàn)和店詳情掌握之前提的導(dǎo)航條titelView也可以輕松搞定,位置也是根據(jù)scrollView的Y軸的偏移量來計算,代碼并不復(fù)雜,具體代碼如下


extension EventViewController: UIScrollViewDelegate {

    func scrollViewDidScroll(scrollView: UIScrollView) {

        // 解決彈出新的控制器后返回后contentSize自動還原的問題
        if loadFinishScrollHeihgt > webView.scrollView.contentSize.height && scrollView === webView.scrollView {
            webView.scrollView.contentSize.height = loadFinishScrollHeihgt
        }

        let offsetY: CGFloat = scrollView.contentOffset.y
        // 判斷頂部自定義導(dǎo)航條的透明度,以及圖片的切換
        customNav.alpha = 1 + (offsetY + NavigationH + EventViewController_ShopView_Height) / scrollShowNavH
        if offsetY + EventViewController_ShopView_Height >= -NavigationH && showBlackImage == false {
            backBtn.setImage(UIImage(named: "back_1"), forState: .Normal)
            likeBtn.setImage(UIImage(named: "collect_1"), forState: .Normal)
            sharedBtn.setImage(UIImage(named: "share_1"), forState: .Normal)
            showBlackImage = true
        } else if offsetY < -NavigationH - EventViewController_ShopView_Height && showBlackImage == true {
            backBtn.setImage(UIImage(named: "back_0"), forState: .Normal)
            likeBtn.setImage(UIImage(named: "collect_0"), forState: .Normal)
            sharedBtn.setImage(UIImage(named: "share_0"), forState: .Normal)
            showBlackImage = false
        }

        // 頂部imageView的跟隨動畫
        if offsetY <= -DetailViewController_TopImageView_Height - EventViewController_ShopView_Height {
            topImageView.frame.origin.y = 0
            topImageView.frame.size.height = -offsetY - EventViewController_ShopView_Height
            topImageView.frame.size.width = AppWidth - offsetY - DetailViewController_TopImageView_Height
            topImageView.frame.origin.x = (0 + DetailViewController_TopImageView_Height + offsetY) * 0.5
        } else {
            topImageView.frame.origin.y = -offsetY - DetailViewController_TopImageView_Height - EventViewController_ShopView_Height
        }

        // 處理shopView
        if offsetY >= -(EventViewController_ShopView_Height + NavigationH) {
            shopView.frame = CGRect(x: 0, y: NavigationH, width: AppWidth, height: EventViewController_ShopView_Height)
        } else {
            shopView.frame = CGRect(x: 0, y: CGRectGetMaxY(topImageView.frame), width: AppWidth, height: EventViewController_ShopView_Height)
        }

        // 記錄scrollView最后的偏移量,用于切換scrollView時同步倆個scrollView的偏移值
        lastOffsetY = offsetY
    }
}

  • 店發(fā)現(xiàn) 這里相對來說有點麻煩,這里服務(wù)器返回的是好長的一串htmlString,由于沒有css的布局文件,直接加載htmlStr的話圖片是超級的大,有的像素達(dá)到4480*3000,直接用webView.loadHTMLString:的方法很不現(xiàn)實,這里我放一段服務(wù)器返回的字符串給讀者看一下如下圖

    html返回的字符串
    html返回的字符串

  • 由于沒有css的布局文件,只能靠自己來約束圖片的大小,我采用的方法是通過正則語句過濾出所有圖片的寬和高,然后按照屏幕的寬度等比例計算圖片的大小,在將修改過的寬和高替換插入到原有的htmlStr中,觀察服務(wù)器返回的htmlStr是沒有title和tag的,也就意味這展示的內(nèi)容沒有標(biāo)題和標(biāo)簽,所以再動態(tài)的將title以及tag的標(biāo)簽插入到字符串中插入代碼如下

                if model?.title != nil {
                    titleStr = String(format: "<p style='font-size:20px;'> %@</p>", model!.title!)
                }

                if model?.tag != nil {
                    titleStr = titleStr?.stringByAppendingFormat("<p style='font-size:13px; color: gray';>%@</p>", model!.tag!)
                }
  • 再加載修改過圖片寬高的htmlStr,然后webViewDidFinishLoad的方法中,通過JS代碼將內(nèi)容的背景色修改,此種方法瑕疵很多,代碼如下
webView.stringByEvaluatingJavaScriptFromString("document.getElementsByTagName('body')[0].style.background='#F5F5F5';")
  • 對webView圖片的處理,小熊感覺還有一個更好的思路可以嘗試,不過在項目中沒有實現(xiàn)成功,這里我覺得可以動態(tài)的將所有的的htmlStr中image都攔截掉,不讓webView自己加載圖片,并且通過條件過濾保留圖片的url地址,動態(tài)的計算出圖片的位置和大小,用本地加載圖片的方法加載圖片,放到對應(yīng)webView.scrollView的位置,這樣就可以實現(xiàn)緩存,以及點擊等事件,不過需要于js端的配合,這個以后我一定會再嘗試的,可行的話我會將demo分享給大家

  • 在webView的最底部,也會根據(jù)服務(wù)器返回的數(shù)據(jù)動態(tài)的加入猜你喜歡的cell,這里只需要在webView加載完畢后,確認(rèn)webView.scrollView.contentSize.height后面添加對應(yīng)的moreView即可!需要注意的是,添加內(nèi)容后,也要相應(yīng)的增加webView.scrollView.height的高度用來顯示新添加的控件

附近(效果如下圖所示)

附近地圖效果圖
附近地圖效果圖
  • 在程序啟動成功的方法中,首先會獲取用戶授權(quán)使用定位功能,這里我封裝了一個管理用戶位置的單例,當(dāng)用戶授權(quán)App可以使用定位后,獲取用戶當(dāng)前的經(jīng)緯度并且將用戶位置的經(jīng)緯度保存,當(dāng)用戶點擊附近按鈕彈出控制器時,發(fā)送網(wǎng)絡(luò)請求給服務(wù)器,服務(wù)器通過用戶當(dāng)前的經(jīng)緯度返回附近店鋪的信息,由于沒有數(shù)據(jù),所以每次返回的都是小熊寫在本地的數(shù)據(jù),解析對應(yīng)的數(shù)據(jù)加載到tableView顯示,通過用戶的位置以及店鋪的位置可以計算出距離給label設(shè)置用戶當(dāng)前距離店鋪的距離KM
  • 翻轉(zhuǎn)動畫,根據(jù)右上角按鈕的狀態(tài)使用下面方法完成翻轉(zhuǎn)動畫
        if sender.selected {
            UIView.transitionFromView(nearTableView, toView: mapView, duration: 1.0, options: UIViewAnimationOptions.TransitionFlipFromLeft, completion: nil)
        } else {
            UIView.transitionFromView(mapView, toView: nearTableView, duration: 1.0, options: UIViewAnimationOptions.TransitionFlipFromRight, completion: nil)
        }
  • mapView中,有一個UICollectionview,一個定位到當(dāng)前用戶位置的按鈕,以及自定義的大頭針若干,判斷大頭針的選中狀態(tài)切換大頭針的圖片,根據(jù)選中的shopCell切換選中大頭針等,都是一些計算性的代碼,具體代碼參考WNXMapView.swift文件,點擊shopCell推出對應(yīng)的控制器即可

體驗

  • 體驗控制器值得一提的是TableViewCell的高度計算方法采用了iOS8.0的新方法,通過約束cell底部來自動計算cell的高度,在xib中約束好cell底部后,在初始化TableView時,通過下面?zhèn)z句代碼就可以實現(xiàn)cell自動計算高度
        // 估算cell的高度
        tableV.estimatedRowHeight = 200
         // 設(shè)置tableView的自動布局樣式
        tableV.rowHeight = UITableViewAutomaticDimension
  • 這個方法局限性比較大,只可以在確定cell底部約束對象時才可以采用,根據(jù)需求情況有時使用會比較方便必須iOS8.0以上才可以

體驗詳情控制器效果如下圖所示

  • 可以看出體驗詳情控制器與探店詳情控制器大同小異,不同的是底部動態(tài)添加的控件.
  • 報名控制器需要注意鍵盤對TextField的遮蓋,監(jiān)聽鍵盤將要改變Frame的通知,設(shè)置scrollView的偏移Y軸的偏移值,保證鍵盤無法遮蓋住輸入框,網(wǎng)網(wǎng)項目中最耗時的就是這些細(xì)節(jié)性的動畫,既考驗開發(fā)人員的細(xì)心,又考驗開發(fā)人員的耐心
  • 當(dāng)用戶輸入好報名信息并且點擊提交后,將報名信息通過sql語句插入到本地數(shù)據(jù)庫,為了給后面我的訂單中使用

搜索控制器(效果圖如下)

搜索控制器
搜索控制器
  • 這里有個小小的動畫,是根據(jù)鍵盤監(jiān)聽鍵盤Frame改變發(fā)出的通知來做出相應(yīng)的動畫,值得提醒大家的是:通過真機(jī)調(diào)試發(fā)現(xiàn),當(dāng)用戶手機(jī)安裝三方的鍵盤時(搜狗輸入法...),鍵盤彈出和隱藏的通知會連續(xù)發(fā)出多次,需要加上標(biāo)記來判斷即可,模擬器中我還沒發(fā)現(xiàn)這種情況,望大家注意

我的

用戶頭像View
  • 首先利用封裝的用戶賬號管理工具判斷當(dāng)前用戶是否登陸,如果未登錄,則推出登陸界面,當(dāng)用戶登陸或者注冊后,將用戶的賬號,以及加密過的密碼發(fā)送給服務(wù)器,以及在本地備份,便于程序關(guān)閉后,下次運(yùn)行程序時,用戶不需要再次登陸.

  • 如果用戶已登錄并且點擊iconView后,打開UIImagePickerController,根據(jù)用戶選擇的是打開相冊還是相機(jī)來設(shè)置UIImagePickerController對象的sourceType.當(dāng)用戶點擊相機(jī)時,需要先判斷用戶當(dāng)前攝像頭是否可用,注意模擬器沒有攝像頭,需要在真機(jī)調(diào)試才可以打開攝像頭,設(shè)置照片為可編輯模式,這樣用戶選擇的圖片將會是正方形,方便頭像的圓形的裁剪

  • 這里有一個地方值得注意,就是隨著相機(jī)像素的提高,實際用戶選擇的圖片都是很大的,有的高達(dá)5.6M,如果直接使用用戶選著的圖片,非常消耗內(nèi)存,并且也用不到這么高像素的圖片,可以當(dāng)用戶選著好圖片后,在UIImagePickerController對應(yīng)的代理方法中,先將圖片進(jìn)行重新繪制為需要的大小,在設(shè)置給iconView具體代碼如下所示

/// MARK: 攝像機(jī)和相冊的操作和代理方法
extension MeViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    
    /// 打開照相功能
    private func openCamera() {
        if UIImagePickerController.isSourceTypeAvailable(.Camera) {
            pickVC.sourceType = .Camera
            self.presentViewController(pickVC, animated: true, completion: nil)
        } else {
            SVProgressHUD.showErrorWithStatus("模擬器沒有攝像頭,請鏈接真機(jī)調(diào)試", maskType: SVProgressHUDMaskType.Black)
        }
    }
    
    /// 打開相冊
    private func openUserPhotoLibrary() {
        pickVC.sourceType = .PhotoLibrary
        pickVC.allowsEditing = true
        presentViewController(pickVC, animated: true, completion: nil)
    }
    
    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
        // 對用戶選著的圖片進(jìn)行質(zhì)量壓縮,上傳服務(wù)器,本地持久化存儲
        if let typeStr = info[UIImagePickerControllerMediaType] as? String {
            if typeStr == "public.image" {
                if let image = info[UIImagePickerControllerEditedImage] as? UIImage {
                    var data: NSData?
                    let smallImage = UIImage.imageClipToNewImage(image, newSize: iconView!.iconButton.size)
                    if UIImagePNGRepresentation(smallImage) == nil {
                        data = UIImageJPEGRepresentation(smallImage, 0.8)
                    } else {
                        data = UIImagePNGRepresentation(smallImage)
                    }
                    
                    if data != nil {
                        do {
                            // TODO: 將頭像的data傳入服務(wù)器
                            // 本地也保留一份data數(shù)據(jù)
                            try NSFileManager.defaultManager().createDirectoryAtPath(theme.cachesPath, withIntermediateDirectories: true, attributes: nil)
                        } catch _ {
                        }
                        NSFileManager.defaultManager().createFileAtPath(SD_UserIconData_Path, contents: data, attributes: nil)
                        
                        iconView!.iconButton.setImage(UIImage(data: NSData(contentsOfFile: SD_UserIconData_Path)!)!.imageClipOvalImage(), forState: .Normal)
                        
                    } else {
                        SVProgressHUD.showErrorWithStatus("照片保存失敗", maskType: SVProgressHUDMaskType.Black)
                    }
                }
            }
        } else {
            SVProgressHUD.showErrorWithStatus("圖片無法獲取", maskType: SVProgressHUDMaskType.Black)
        }
        
        picker.dismissViewControllerAnimated(true, completion: nil)
    }
    
    func imagePickerControllerDidCancel(picker: UIImagePickerController) {
        pickVC.dismissViewControllerAnimated(true, completion: nil)
    }
}

搖一搖

搖一搖效果圖
搖一搖效果圖
  • 搖一搖使用的是蘋果提供好的方法override func motionBegan(motion: UIEventSubtype, withEvent event: UIEvent?),每當(dāng)用戶搖晃手機(jī)時,系統(tǒng)就會自動調(diào)用此方法,在方法內(nèi)部做出相應(yīng)的動畫即可關(guān)鍵代碼就這下面這幾句,如果是使用模擬器可以點擊窗口上**Hardware -> Shake Gesture**來進(jìn)行模擬調(diào)試
    override func motionBegan(motion: UIEventSubtype, withEvent event: UIEvent?) {
        tableView!.hidden = true
        let animateDuration: NSTimeInterval = 0.3
        let offsetY: CGFloat = 50
        
        UIView.animateWithDuration(animateDuration, animations: { () -> Void in
            self.yaoImageView1.transform = CGAffineTransformMakeTranslation(0, -offsetY)
            self.yaoImageView2.transform = CGAffineTransformMakeTranslation(0, offsetY)
            
            }) { (finish) -> Void in
                let popTime = dispatch_time(DISPATCH_TIME_NOW,Int64(0.5 * Double(NSEC_PER_SEC)))
                dispatch_after(popTime, dispatch_get_main_queue(), { () -> Void in
                    
                    UIView.animateWithDuration(animateDuration, animations: { () -> Void in
                        self.yaoImageView1.transform = CGAffineTransformIdentity
                        self.yaoImageView2.transform = CGAffineTransformIdentity
                        }, completion: { (finish) -> Void in

                            self.loadShakeData()
                            // 音效
                            AudioServicesPlayAlertSound(self.soundID!)
                    })
                })
        }

清理緩存

  • 這里我封裝了一個工具類:FileTool,通過類方法可以調(diào)用查看指定路徑文件夾的大小FileTool.folderSize(path: String),以及異步刪除指路徑下的全部文件夾FileTool.cleanFolder(path: String, complete: () -> ()),complete為刪除完成后的回調(diào)

三方分享

  • 這里我封裝了一個分享工具類ShareTool,集成了新浪SSO,微信SSO認(rèn)證,以及新浪OAuth認(rèn)證.采用的是友盟分享SDK,以及自定義的分享界面,需要注意的是由于微信沒有OAuth認(rèn)證,所以只有在設(shè)備安裝了微信時才可以分享(插上你的真機(jī)分享點擊分享試一試),模擬器中只可以使用新浪微博的分享.
  • 如果想要將新浪分享的來自xx和圖片修改為自己應(yīng)用的圖標(biāo),可以在新浪的開發(fā)者平臺注冊成為開發(fā)者,添加應(yīng)用并且上線,通過審核,在友盟網(wǎng)站我的產(chǎn)品中將設(shè)置主題修改相應(yīng)的屬性即可.
  • 在iOS9.0后,需要設(shè)置白名單以及回調(diào)的白名單才可以完成分享后的回調(diào)

關(guān)于項目的介紹基本就這么多了,更多的細(xì)節(jié)和內(nèi)容直接看代碼來的更快捷一些,對于Swift小熊也是又愛又恨,相信隨著版本的不斷更新,Swift語言也會越來越趨于穩(wěn)定,Xcode對Swift的支持也會越來越好的,總算對自己的承諾有了一個小小的交代,如果有小熊的項目有幫助到大家,請到我的GitHub點個星,項目中會有很多不足之處,歡迎到我的博客留言與交流,小熊希望與大家共同進(jìn)步_~,提前祝大家十一快樂


直接打開運(yùn)行工程

打開工作組運(yùn)行工程
打開工作組運(yùn)行工程


代碼下載地址

代碼下載地址,歡迎點贊和反饋

小熊的技術(shù)博客

點擊鏈接我的博客

小熊的新浪微博

我的新浪微博


本文為作者原著,歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明作者出處

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市屑那,隨后出現(xiàn)的幾起案子锨能,更是在濱河造成了極大的恐慌,老刑警劉巖传黄,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異队寇,居然都是意外死亡膘掰,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進(jìn)店門佳遣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來识埋,“玉大人凡伊,你說我怎么就攤上這事≈现郏” “怎么了系忙?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長辜纲。 經(jīng)常有香客問我笨觅,道長,這世上最難降的妖魔是什么耕腾? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任见剩,我火速辦了婚禮,結(jié)果婚禮上扫俺,老公的妹妹穿的比我還像新娘苍苞。我一直安慰自己,他們只是感情好狼纬,可當(dāng)我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布羹呵。 她就那樣靜靜地躺著,像睡著了一般疗琉。 火紅的嫁衣襯著肌膚如雪冈欢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天盈简,我揣著相機(jī)與錄音抖甘,去河邊找鬼简烤。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的回梧。 我是一名探鬼主播丁溅,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼快毛,長吁一口氣:“原來是場噩夢啊……” “哼晤斩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起宴霸,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤囱晴,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后瓢谢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體畸写,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年恩闻,在試婚紗的時候發(fā)現(xiàn)自己被綠了艺糜。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片剧董。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡幢尚,死狀恐怖破停,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情尉剩,我是刑警寧澤真慢,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站理茎,受9級特大地震影響黑界,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜皂林,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一朗鸠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧础倍,春花似錦烛占、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至德迹,卻和暖如春芽卿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背胳搞。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工卸例, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人流酬。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓币厕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親芽腾。 傳聞我的和親對象是個殘疾皇子旦装,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容