├── TextUtil
├── Images
│ ├── 001.png
│ ├── 002.png
│ ├── 003.png
│ ├── 004.png
│ ├── 005.png
│ ├── 006.png
│ ├── 007.png
│ ├── 008.png
│ ├── 009.png
│ ├── 010.png
│ ├── 011.png
│ ├── 012.png
│ ├── 013.png
│ ├── 014.png
│ ├── 015.png
│ ├── 016.png
│ ├── 017.png
│ ├── 018.png
│ ├── 019.png
│ ├── 020.png
│ ├── 021@2x.png
│ ├── 022@2x.png
│ ├── 023@2x.png
│ ├── 024@2x.png
│ ├── 025@2x.png
│ ├── 026@2x.png
│ ├── 027@2x.png
│ ├── 028@2x.png
│ ├── 029@2x.png
│ ├── 030@2x.png
│ ├── 031@2x.png
│ ├── 032@2x.png
│ ├── 033@2x.png
│ ├── 034@2x.png
│ ├── 035@2x.png
│ ├── 036@2x.png
│ ├── 037@2x.png
│ ├── 038@2x.png
│ ├── 039@2x.png
│ ├── 040@2x.png
│ ├── 041@2x.png
│ ├── 042@2x.png
│ ├── 043@2x.png
│ ├── 044@2x.png
│ ├── 045@2x.png
│ ├── 046@2x.png
│ ├── 047@2x.png
│ ├── 048@2x.png
│ ├── 049@2x.png
│ ├── 050@2x.png
│ ├── 051@2x.png
│ ├── 052@2x.png
│ ├── 053@2x.png
│ ├── 054@2x.png
│ ├── 055@2x.png
│ ├── 056@2x.png
│ ├── 057@2x.png
│ ├── 058@2x.png
│ ├── 059@2x.png
│ ├── 060@2x.png
│ ├── 061@2x.png
│ ├── 062@2x.png
│ ├── 063@2x.png
│ ├── 064@2x.png
│ ├── 065@2x.png
│ ├── 066@2x.png
│ ├── 067@2x.png
│ ├── 068@2x.png
│ ├── 069@2x.png
│ ├── 070@2x.png
│ ├── 071@2x.png
│ ├── 072@2x.png
│ ├── 073@2x.png
│ ├── 074@2x.png
│ ├── 075@2x.png
│ ├── 076@2x.png
│ ├── 077@2x.png
│ ├── 078@2x.png
│ ├── 079@2x.png
│ ├── 080@2x.png
│ ├── 081@2x.png
│ ├── 082@2x.png
│ ├── 083@2x.png
│ ├── 084@2x.png
│ ├── 085@2x.png
│ ├── 086@2x.png
│ ├── 087@2x.png
│ ├── 088@2x.png
│ ├── 089@2x.png
│ ├── 090@2x.png
│ ├── 091@2x.png
│ ├── 092@2x.png
│ ├── 093@2x.png
│ ├── 094@2x.png
│ ├── 095@2x.png
│ ├── 096@2x.png
│ ├── 097@2x.png
│ ├── 098@2x.png
│ ├── 099@2x.png
│ ├── 100@2x.png
│ ├── 101@2x.png
│ ├── 102@2x.png
│ ├── 103@2x.png
│ ├── 104@2x.png
│ ├── 105@2x.png
│ ├── image_01.jpg
│ ├── image_02.jpg
│ ├── image_03.jpg
│ ├── image_04.jpg
│ ├── image_05.jpg
│ ├── image_06.jpg
│ ├── image_07.jpg
│ ├── image_08.jpg
│ ├── image_09.jpg
│ ├── emotion@2x.png
│ ├── ScreenShot1.png
│ ├── ScreenShot2.png
│ └── ScreenShot3.png
├── Images.xcassets
│ ├── image
│ │ ├── tab_oa.imageset
│ │ │ ├── tab_oa@2x.png
│ │ │ ├── tab_oa@3x.png
│ │ │ └── Contents.json
│ │ ├── header_QQ.imageset
│ │ │ ├── AS_QQ@2x.png
│ │ │ └── Contents.json
│ │ ├── dynamic_love.imageset
│ │ │ ├── dynamic_love@2x.png
│ │ │ └── Contents.json
│ │ ├── header_wechat.imageset
│ │ │ ├── AppIcon57x57@2x.png
│ │ │ └── Contents.json
│ │ ├── tab_oa_click.imageset
│ │ │ ├── tab_oa_click@2x.png
│ │ │ ├── tab_oa_click@3x.png
│ │ │ └── Contents.json
│ │ ├── chat_send_nor.imageset
│ │ │ ├── chat_send_nor@2x.png
│ │ │ └── Contents.json
│ │ ├── chat_recive_nor.imageset
│ │ │ ├── chat_recive_nor@2x.png
│ │ │ └── Contents.json
│ │ ├── dynamic_collect.imageset
│ │ │ ├── dynamic_collect@2x.png
│ │ │ └── Contents.json
│ │ ├── dynamic_comment.imageset
│ │ │ ├── dynamic_comment@2x.png
│ │ │ └── Contents.json
│ │ ├── tab_conversation.imageset
│ │ │ ├── tab_conversation@2x.png
│ │ │ ├── tab_conversation@3x.png
│ │ │ └── Contents.json
│ │ ├── dynamic_love_blue.imageset
│ │ │ ├── dynamic_love_blue@2x.png
│ │ │ └── Contents.json
│ │ ├── emotion_btbg.imageset
│ │ │ ├── chatgroup_emotion_btbg@2x.png
│ │ │ └── Contents.json
│ │ ├── chat_send_press_pic.imageset
│ │ │ ├── chat_send_press_pic@2x.png
│ │ │ └── Contents.json
│ │ ├── dynamic_love_select.imageset
│ │ │ ├── dynamic_love_select@2x.png
│ │ │ └── Contents.json
│ │ ├── chat_recive_press_pic.imageset
│ │ │ ├── chat_recive_press_pic@2x.png
│ │ │ └── Contents.json
│ │ ├── dynamic_collect_select.imageset
│ │ │ ├── dynamic_collect_select@2x.png
│ │ │ └── Contents.json
│ │ ├── dynamic_comment_select.imageset
│ │ │ ├── dynamic_comment_select@2x.png
│ │ │ └── Contents.json
│ │ ├── tab_conversation_click.imageset
│ │ │ ├── tab_conversation_click@2x.png
│ │ │ ├── tab_conversation_click@3x.png
│ │ │ └── Contents.json
│ │ └── emoticon_keyboard_magnifier.imageset
│ │ │ ├── emoticon_keyboard_magnifier@2x.png
│ │ │ └── Contents.json
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── OpenSources
│ └── FMDB
│ │ ├── FMDB.h
│ │ ├── FMDatabasePool.h
│ │ ├── FMDatabaseQueue.h
│ │ ├── FMDatabaseQueue.m
│ │ ├── FMDatabaseAdditions.m
│ │ ├── FMDatabasePool.m
│ │ ├── FMDatabaseAdditions.h
│ │ ├── FMResultSet.m
│ │ └── FMResultSet.h
├── Discover
│ ├── Models
│ │ ├── Dynamic.m
│ │ └── Dynamic.h
│ ├── Controllers
│ │ ├── DynamicViewController.h
│ │ └── DynamicViewController.m
│ └── Views
│ │ ├── DynamicView.h
│ │ ├── DynamicCell.h
│ │ ├── DynamicView.m
│ │ └── DynamicCell.m
├── Chat
│ ├── Models
│ │ ├── ChatMessage.m
│ │ └── ChatMessage.h
│ ├── Controllers
│ │ ├── ChatViewController.h
│ │ ├── TextAndPictureViewController.h
│ │ ├── TextAndPictureViewController.m
│ │ └── ChatViewController.m
│ └── Views
│ │ ├── ChatCell.h
│ │ ├── YYFaceView.h
│ │ ├── YYFaceScrollView.h
│ │ ├── YYFaceScrollView.m
│ │ ├── YYFaceView.m
│ │ └── ChatCell.m
├── AppDelegate.h
├── Utils
│ ├── UIImage+Extension.h
│ ├── JKDBHelper.h
│ ├── UIImage+Extension.m
│ ├── UIViewExt.h
│ ├── Utility.h
│ ├── JKDBHelper.m
│ ├── JKDBModel.h
│ ├── UIViewExt.m
│ └── Utility.m
├── main.m
├── AppDelegate.m
├── TextUtil-Prefix.pch
├── Info.plist
├── emoticons.plist
└── Base.lproj
│ └── LaunchScreen.xib
├── TextUtil.xcodeproj
├── xcuserdata
│ └── zx_04.xcuserdatad
│ │ ├── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ ├── xcschememanagement.plist
│ │ └── TextUtil.xcscheme
└── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcuserdata
│ └── zx_04.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
│ └── xcshareddata
│ └── TextUtil.xccheckout
├── README.md
└── TextUtilTests
├── Info.plist
└── TextUtilTests.m
/TextUtil/Images/001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/001.png
--------------------------------------------------------------------------------
/TextUtil/Images/002.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/002.png
--------------------------------------------------------------------------------
/TextUtil/Images/003.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/003.png
--------------------------------------------------------------------------------
/TextUtil/Images/004.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/004.png
--------------------------------------------------------------------------------
/TextUtil/Images/005.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/005.png
--------------------------------------------------------------------------------
/TextUtil/Images/006.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/006.png
--------------------------------------------------------------------------------
/TextUtil/Images/007.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/007.png
--------------------------------------------------------------------------------
/TextUtil/Images/008.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/008.png
--------------------------------------------------------------------------------
/TextUtil/Images/009.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/009.png
--------------------------------------------------------------------------------
/TextUtil/Images/010.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/010.png
--------------------------------------------------------------------------------
/TextUtil/Images/011.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/011.png
--------------------------------------------------------------------------------
/TextUtil/Images/012.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/012.png
--------------------------------------------------------------------------------
/TextUtil/Images/013.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/013.png
--------------------------------------------------------------------------------
/TextUtil/Images/014.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/014.png
--------------------------------------------------------------------------------
/TextUtil/Images/015.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/015.png
--------------------------------------------------------------------------------
/TextUtil/Images/016.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/016.png
--------------------------------------------------------------------------------
/TextUtil/Images/017.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/017.png
--------------------------------------------------------------------------------
/TextUtil/Images/018.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/018.png
--------------------------------------------------------------------------------
/TextUtil/Images/019.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/019.png
--------------------------------------------------------------------------------
/TextUtil/Images/020.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/020.png
--------------------------------------------------------------------------------
/TextUtil/Images/021@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/021@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/022@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/022@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/023@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/023@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/024@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/024@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/025@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/025@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/026@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/026@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/027@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/027@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/028@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/028@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/029@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/029@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/030@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/030@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/031@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/031@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/032@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/032@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/033@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/033@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/034@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/034@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/035@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/035@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/036@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/036@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/037@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/037@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/038@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/038@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/039@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/039@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/040@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/040@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/041@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/041@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/042@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/042@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/043@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/043@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/044@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/044@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/045@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/045@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/046@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/046@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/047@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/047@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/048@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/048@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/049@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/049@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/050@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/050@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/051@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/051@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/052@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/052@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/053@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/053@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/054@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/054@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/055@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/055@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/056@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/056@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/057@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/057@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/058@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/058@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/059@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/059@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/060@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/060@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/061@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/061@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/062@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/062@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/063@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/063@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/064@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/064@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/065@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/065@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/066@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/066@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/067@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/067@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/068@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/068@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/069@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/069@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/070@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/070@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/071@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/071@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/072@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/072@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/073@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/073@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/074@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/074@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/075@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/075@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/076@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/076@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/077@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/077@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/078@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/078@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/079@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/079@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/080@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/080@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/081@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/081@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/082@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/082@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/083@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/083@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/084@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/084@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/085@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/085@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/086@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/086@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/087@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/087@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/088@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/088@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/089@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/089@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/090@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/090@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/091@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/091@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/092@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/092@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/093@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/093@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/094@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/094@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/095@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/095@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/096@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/096@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/097@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/097@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/098@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/098@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/099@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/099@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/100@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/100@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/101@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/101@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/102@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/102@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/103@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/103@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/104@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/104@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/105@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/105@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/image_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/image_01.jpg
--------------------------------------------------------------------------------
/TextUtil/Images/image_02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/image_02.jpg
--------------------------------------------------------------------------------
/TextUtil/Images/image_03.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/image_03.jpg
--------------------------------------------------------------------------------
/TextUtil/Images/image_04.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/image_04.jpg
--------------------------------------------------------------------------------
/TextUtil/Images/image_05.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/image_05.jpg
--------------------------------------------------------------------------------
/TextUtil/Images/image_06.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/image_06.jpg
--------------------------------------------------------------------------------
/TextUtil/Images/image_07.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/image_07.jpg
--------------------------------------------------------------------------------
/TextUtil/Images/image_08.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/image_08.jpg
--------------------------------------------------------------------------------
/TextUtil/Images/image_09.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/image_09.jpg
--------------------------------------------------------------------------------
/TextUtil/Images/emotion@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/emotion@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images/ScreenShot1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/ScreenShot1.png
--------------------------------------------------------------------------------
/TextUtil/Images/ScreenShot2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/ScreenShot2.png
--------------------------------------------------------------------------------
/TextUtil/Images/ScreenShot3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images/ScreenShot3.png
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/tab_oa.imageset/tab_oa@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/tab_oa.imageset/tab_oa@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/tab_oa.imageset/tab_oa@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/tab_oa.imageset/tab_oa@3x.png
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/header_QQ.imageset/AS_QQ@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/header_QQ.imageset/AS_QQ@2x.png
--------------------------------------------------------------------------------
/TextUtil/OpenSources/FMDB/FMDB.h:
--------------------------------------------------------------------------------
1 | #import "FMDatabase.h"
2 | #import "FMResultSet.h"
3 | #import "FMDatabaseAdditions.h"
4 | #import "FMDatabaseQueue.h"
5 | #import "FMDatabasePool.h"
6 |
--------------------------------------------------------------------------------
/TextUtil.xcodeproj/xcuserdata/zx_04.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/dynamic_love.imageset/dynamic_love@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/dynamic_love.imageset/dynamic_love@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/header_wechat.imageset/AppIcon57x57@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/header_wechat.imageset/AppIcon57x57@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/tab_oa_click.imageset/tab_oa_click@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/tab_oa_click.imageset/tab_oa_click@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/tab_oa_click.imageset/tab_oa_click@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/tab_oa_click.imageset/tab_oa_click@3x.png
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/chat_send_nor.imageset/chat_send_nor@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/chat_send_nor.imageset/chat_send_nor@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/chat_recive_nor.imageset/chat_recive_nor@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/chat_recive_nor.imageset/chat_recive_nor@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/dynamic_collect.imageset/dynamic_collect@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/dynamic_collect.imageset/dynamic_collect@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/dynamic_comment.imageset/dynamic_comment@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/dynamic_comment.imageset/dynamic_comment@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/tab_conversation.imageset/tab_conversation@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/tab_conversation.imageset/tab_conversation@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/tab_conversation.imageset/tab_conversation@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/tab_conversation.imageset/tab_conversation@3x.png
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/dynamic_love_blue.imageset/dynamic_love_blue@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/dynamic_love_blue.imageset/dynamic_love_blue@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/emotion_btbg.imageset/chatgroup_emotion_btbg@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/emotion_btbg.imageset/chatgroup_emotion_btbg@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/chat_send_press_pic.imageset/chat_send_press_pic@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/chat_send_press_pic.imageset/chat_send_press_pic@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/dynamic_love_select.imageset/dynamic_love_select@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/dynamic_love_select.imageset/dynamic_love_select@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/chat_recive_press_pic.imageset/chat_recive_press_pic@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/chat_recive_press_pic.imageset/chat_recive_press_pic@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/dynamic_collect_select.imageset/dynamic_collect_select@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/dynamic_collect_select.imageset/dynamic_collect_select@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/dynamic_comment_select.imageset/dynamic_comment_select@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/dynamic_comment_select.imageset/dynamic_comment_select@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/tab_conversation_click.imageset/tab_conversation_click@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/tab_conversation_click.imageset/tab_conversation_click@2x.png
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/tab_conversation_click.imageset/tab_conversation_click@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/tab_conversation_click.imageset/tab_conversation_click@3x.png
--------------------------------------------------------------------------------
/TextUtil.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/TextUtil.xcodeproj/project.xcworkspace/xcuserdata/zx_04.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil.xcodeproj/project.xcworkspace/xcuserdata/zx_04.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/emoticon_keyboard_magnifier.imageset/emoticon_keyboard_magnifier@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xhellohaley/TextUtil/HEAD/TextUtil/Images.xcassets/image/emoticon_keyboard_magnifier.imageset/emoticon_keyboard_magnifier@2x.png
--------------------------------------------------------------------------------
/TextUtil/Discover/Models/Dynamic.m:
--------------------------------------------------------------------------------
1 | //
2 | // Dynamic.m
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/19.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import "Dynamic.h"
10 |
11 | @implementation Dynamic
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/TextUtil/Chat/Models/ChatMessage.m:
--------------------------------------------------------------------------------
1 | //
2 | // ChatMessage.m
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/19.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import "ChatMessage.h"
10 |
11 | @implementation ChatMessage
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/TextUtil/Chat/Controllers/ChatViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ChatViewController.h
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/19.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ChatViewController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/TextUtil/Discover/Controllers/DynamicViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // DynamicViewController.h
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/19.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface DynamicViewController : UITableViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/TextUtil/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/18.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/TextUtil/Utils/UIImage+Extension.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+Extension.h
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/20.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UIImage (Extension)
12 |
13 | // 图片拉伸
14 | + (UIImage *)resizableImageWithName:(NSString *)imageName;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/TextUtil/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/18.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/header_QQ.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "AS_QQ@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/TextUtil/Utils/JKDBHelper.h:
--------------------------------------------------------------------------------
1 | //
2 | // JKDataBase.h
3 | // JKBaseModel
4 | //
5 | // github:https://github.com/Joker-King/JKDBModel
6 | // Created by zx_04 on 15/6/24.
7 | //
8 | //
9 |
10 | #import
11 | #import "FMDB.h"
12 |
13 | @interface JKDBHelper : NSObject
14 |
15 | @property (nonatomic, retain, readonly) FMDatabaseQueue *dbQueue;
16 |
17 | + (JKDBHelper *)shareInstance;
18 |
19 | + (NSString *)dbPath;
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TextUtil
2 | 一个工具类帮你三行代码实现图文混排功能。
3 | # 项目截图
4 | 
5 | 
6 | 
7 |
8 | # 说明
9 | 项目中使用的表情图片是从其他地方拷贝出来的,尺寸大小不是很合适,原本都是@2x的,因为发送出来太小了,所以修改成了1倍图,如果要完整显示所有表情,修改图片名,去掉@2x,然后添加完全plist文件。
10 |
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/chat_send_nor.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "chat_send_nor@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/dynamic_love.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "dynamic_love@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/header_wechat.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "AppIcon57x57@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/TextUtil/Chat/Controllers/TextAndPictureViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // TextAndPictureViewController.h
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/24.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface TextAndPictureViewController : UIViewController
12 |
13 | @property (weak, nonatomic) IBOutlet UILabel *firstLabel;
14 | @property (weak, nonatomic) IBOutlet UILabel *secondLabel;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/chat_recive_nor.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "chat_recive_nor@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/dynamic_collect.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "dynamic_collect@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/dynamic_comment.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "dynamic_comment@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/chat_send_press_pic.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "chat_send_press_pic@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/dynamic_love_blue.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "dynamic_love_blue@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/dynamic_love_select.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "dynamic_love_select@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/emotion_btbg.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "chatgroup_emotion_btbg@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/chat_recive_press_pic.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "chat_recive_press_pic@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/dynamic_collect_select.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "dynamic_collect_select@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/dynamic_comment_select.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "dynamic_comment_select@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/tab_oa.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "tab_oa@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x",
15 | "filename" : "tab_oa@3x.png"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/emoticon_keyboard_magnifier.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "emoticon_keyboard_magnifier@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/tab_oa_click.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "tab_oa_click@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x",
15 | "filename" : "tab_oa_click@3x.png"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/tab_conversation.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "tab_conversation@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x",
15 | "filename" : "tab_conversation@3x.png"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/TextUtil/Chat/Views/ChatCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // ChatCell.h
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/19.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class ChatMessage;
12 | @interface ChatCell : UITableViewCell
13 |
14 | @property (nonatomic, retain) ChatMessage *message;
15 |
16 | + (instancetype)cellWithTableView:(UITableView *)tableView;
17 |
18 | /** 计算cell 的高度 */
19 | + (CGFloat)heightOfCellWithMessage:(ChatMessage *)message;
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/image/tab_conversation_click.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "tab_conversation_click@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x",
15 | "filename" : "tab_conversation_click@3x.png"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/TextUtil/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/18.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @interface AppDelegate ()
12 |
13 | @end
14 |
15 | @implementation AppDelegate
16 |
17 |
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
19 | // Override point for customization after application launch.
20 | return YES;
21 | }
22 |
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/TextUtil/Chat/Views/YYFaceView.h:
--------------------------------------------------------------------------------
1 | //
2 | // YYFaceView.h
3 | //
4 | //
5 | // Created by Joker on 14-1-6.
6 | // Copyright (c) 2014年 Mac. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | typedef void(^SelectBlock) (NSString *faceName);
12 |
13 | @interface YYFaceView : UIView
14 | {
15 | NSMutableArray *items;
16 | UIImageView *magnifierView;
17 | }
18 |
19 | @property (nonatomic,copy) NSString *selectedFaceName;
20 | @property (nonatomic,assign) NSInteger pageNumber;
21 | @property (nonatomic,copy) SelectBlock block;
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/TextUtil/Chat/Models/ChatMessage.h:
--------------------------------------------------------------------------------
1 | //
2 | // ChatMessage.h
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/19.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import "JKDBModel.h"
10 |
11 | typedef enum : NSUInteger {
12 | MessageTypeText,
13 | MessageTypeAudio,
14 | MessageTypePicture,
15 | MessageTypeVideo,
16 | } MessageType;
17 |
18 | @interface ChatMessage : JKDBModel
19 |
20 | @property (nonatomic, copy) NSString *content;
21 | @property (nonatomic, assign) MessageType messageType;
22 | @property (nonatomic, assign) BOOL isSender;
23 |
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/TextUtil/Chat/Views/YYFaceScrollView.h:
--------------------------------------------------------------------------------
1 | //
2 | // YYFaceScrollView.h
3 | // ismarter2.0_sz
4 | //
5 | // Created by zx_04 on 15/6/15.
6 | //
7 | //
8 |
9 | #import
10 | #import "YYFaceView.h"
11 |
12 | typedef void(^SendBtnClickBlock)(void);
13 |
14 | @interface YYFaceScrollView : UIView
15 | {
16 | UIScrollView *scrollView;
17 | YYFaceView *faceView;
18 | UIPageControl *pageControl;
19 | UIView *bottomView;
20 | }
21 |
22 | @property (nonatomic, copy) SendBtnClickBlock sendBlock;
23 |
24 | - (id)initWithSelectBlock:(SelectBlock)block;
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/TextUtil.xcodeproj/xcuserdata/zx_04.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | TextUtil.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 6B40A5731B833B1F00A46C7C
16 |
17 | primary
18 |
19 |
20 | 6B40A58C1B833B1F00A46C7C
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/TextUtil/Discover/Views/DynamicView.h:
--------------------------------------------------------------------------------
1 | //
2 | // DynamicView.h
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/19.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "Dynamic.h"
12 |
13 | #define kContentFont [UIFont systemFontOfSize:15.0] //正文字体
14 | #define kDynamicWidth (kWidth-65-10) //内容视图宽度
15 | #define kImagePadding 5 //图片间距
16 | #define kImageWidth (kDynamicWidth-kImagePadding*2)/3 //图片宽度
17 |
18 | #define kSingleImageWidth 200 //单张图片的宽度
19 |
20 | @interface DynamicView : UIView
21 |
22 | @property (nonatomic, retain) Dynamic *dynamic;
23 |
24 | + (CGFloat)getHeightWithModel:(Dynamic *)dynamic;
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/TextUtil/Discover/Views/DynamicCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // DynamicCell.h
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/19.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #define nameColor RGBColor(50, 85, 140, 1.0) //名字颜色
12 | #define customGrayColor RGBColor(175, 180, 200, 1.0) //灰色
13 | #define kFaceWidth 45 //头像视图的宽、高
14 | #define kOptionHeight 30 //操作视图的高度
15 | #define kPadding 10 //视图之间的间距
16 |
17 | @class Dynamic;
18 | @interface DynamicCell : UITableViewCell
19 |
20 | /** 朋友圈信息实体 */
21 | @property (nonatomic, retain) Dynamic *dynamic;
22 |
23 | + (DynamicCell *)cellWithTableView:(UITableView *)tableView;
24 |
25 | + (CGFloat)heightOfCellWithModel:(Dynamic *)dynamic;
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/TextUtil/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
--------------------------------------------------------------------------------
/TextUtil/Discover/Models/Dynamic.h:
--------------------------------------------------------------------------------
1 | //
2 | // Dynamic.h
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/19.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import "JKDBModel.h"
10 |
11 | @interface Dynamic : JKDBModel
12 |
13 | @property (nonatomic, assign) BOOL isPraise;
14 | @property (nonatomic, assign) int praiseCount;
15 | @property (nonatomic, copy) NSString *location;
16 | @property (nonatomic, copy) NSString *createTime;
17 | /** 类型含义:0:纯文字 1:带图片(文字+图片/纯图片) 2:带视频(文字+视频/纯视频) */
18 | @property (nonatomic, assign) int type;
19 | @property (nonatomic, copy) NSString *text;
20 | @property (nonatomic, assign) int imageCount;
21 | @property (nonatomic, assign) int replyCount;
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/TextUtil/Utils/UIImage+Extension.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+Extension.m
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/20.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import "UIImage+Extension.h"
10 |
11 | @implementation UIImage (Extension)
12 |
13 | + (UIImage *)resizableImageWithName:(NSString *)imageName
14 | {
15 |
16 | // 加载原有图片
17 | UIImage *norImage = [UIImage imageNamed:imageName];
18 | // 获取原有图片的宽高的一半
19 | CGFloat w = norImage.size.width * 0.5;
20 | CGFloat top = norImage.size.height * 0.5;
21 | CGFloat bottom = norImage.size.height-top;
22 | // 生成可以拉伸指定位置的图片
23 | UIImage *newImage = [norImage resizableImageWithCapInsets:UIEdgeInsetsMake(top, w, bottom, w) resizingMode:UIImageResizingModeStretch];
24 |
25 | return newImage;
26 | }
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/TextUtilTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | com.zx.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/TextUtil/Utils/UIViewExt.h:
--------------------------------------------------------------------------------
1 | /*
2 | Erica Sadun, http://ericasadun.com
3 | iPhone Developer's Cookbook, 3.0 Edition
4 | BSD License, Use at your own risk
5 | */
6 |
7 | #import
8 |
9 | CGPoint CGRectGetCenter(CGRect rect);
10 | CGRect CGRectMoveToCenter(CGRect rect, CGPoint center);
11 |
12 | @interface UIView (ViewFrameGeometry)
13 | @property CGPoint origin;
14 | @property CGSize size;
15 |
16 | @property (readonly) CGPoint bottomLeft;
17 | @property (readonly) CGPoint bottomRight;
18 | @property (readonly) CGPoint topRight;
19 |
20 | @property CGFloat height;
21 | @property CGFloat width;
22 |
23 | @property CGFloat top;
24 | @property CGFloat left;
25 |
26 | @property CGFloat bottom;
27 | @property CGFloat right;
28 |
29 | - (void) moveBy: (CGPoint) delta;
30 | - (void) scaleBy: (CGFloat) scaleFactor;
31 | - (void) fitInSize: (CGSize) aSize;
32 | - (UIViewController *)viewController;
33 |
34 |
35 | @end
--------------------------------------------------------------------------------
/TextUtil/Utils/Utility.h:
--------------------------------------------------------------------------------
1 | //
2 | // Utility.h
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/20.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface Utility : NSObject
12 |
13 | //处理表情字符
14 | + (NSMutableAttributedString *)emotionStrWithString:(NSString *)text;
15 |
16 | /**
17 | * 将带有表情符的文字转换为图文混排的文字
18 | *
19 | * @param text 带表情符的文字
20 | * @param plistName 表情符与表情对应的plist文件
21 | * @param y 图片的y偏移值
22 | *
23 | * @return 转换后的文字
24 | */
25 | + (NSMutableAttributedString *)emotionStrWithString:(NSString *)text plistName:(NSString *)plistName y:(CGFloat)y;
26 | /**
27 | * 将个别文字转换为特殊的图片
28 | *
29 | * @param string 原始文字段落
30 | * @param text 特殊的文字
31 | * @param imageName 要替换的图片
32 | *
33 | * @return NSMutableAttributedString
34 | */
35 | + (NSMutableAttributedString *)exchangeString:(NSString *)string withText:(NSString *)text imageName:(NSString *)imageName;
36 |
37 | @end
38 |
--------------------------------------------------------------------------------
/TextUtilTests/TextUtilTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // TextUtilTests.m
3 | // TextUtilTests
4 | //
5 | // Created by zx_04 on 15/8/18.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface TextUtilTests : XCTestCase
13 |
14 | @end
15 |
16 | @implementation TextUtilTests
17 |
18 | - (void)setUp {
19 | [super setUp];
20 | // Put setup code here. This method is called before the invocation of each test method in the class.
21 | }
22 |
23 | - (void)tearDown {
24 | // Put teardown code here. This method is called after the invocation of each test method in the class.
25 | [super tearDown];
26 | }
27 |
28 | - (void)testExample {
29 | // This is an example of a functional test case.
30 | XCTAssert(YES, @"Pass");
31 | }
32 |
33 | - (void)testPerformanceExample {
34 | // This is an example of a performance test case.
35 | [self measureBlock:^{
36 | // Put the code you want to measure the time of here.
37 | }];
38 | }
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/TextUtil/Chat/Controllers/TextAndPictureViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // TextAndPictureViewController.m
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/24.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import "TextAndPictureViewController.h"
10 |
11 | #import "Utility.h"
12 |
13 | @interface TextAndPictureViewController ()
14 |
15 | @end
16 |
17 | @implementation TextAndPictureViewController
18 |
19 | - (void)viewDidLoad {
20 | [super viewDidLoad];
21 | // Do any additional setup after loading the view.
22 |
23 | NSString *content = @"文字加上表情[得意][酷][呲牙]";
24 | NSMutableAttributedString *attrStr = [Utility emotionStrWithString:content];
25 | _firstLabel.attributedText= attrStr;
26 |
27 | NSString *text = @"<微信>腾讯科技讯 微软提供免费升级的Windows 10,在全球获得普遍好评。但微软已经有一段时间没有公布最新升级数据。科技市场研究公司StatCounter发布了有关Windows升级的相关数据,显示出Windows 10的升级节奏开始放缓。<微信>另外,数据显示Windows 8用户是升级的主力军,Windows 7用户升级动力不太足。";
28 | NSMutableAttributedString *attrStr2 = [Utility exchangeString:@"<微信>" withText:text imageName:@"header_wechat"];
29 | _secondLabel.attributedText = attrStr2;
30 |
31 | }
32 |
33 |
34 | @end
35 |
--------------------------------------------------------------------------------
/TextUtil/TextUtil-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // TextUtil-Prefix.pch
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/19.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #ifndef TextUtil_TextUtil_Prefix_pch
10 | #define TextUtil_TextUtil_Prefix_pch
11 |
12 | #ifdef __OBJC__
13 | #import
14 | #import
15 |
16 | #import "JKDBModel.h"
17 | #import "UIViewExt.h"
18 | #endif
19 |
20 | #ifdef DEBUG
21 | #define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
22 | #else
23 | #define DLog(fmt, ...) nil
24 | #endif
25 |
26 | #define kWidth [UIScreen mainScreen].bounds.size.width //获取设备的物理宽度
27 | #define kHeight [UIScreen mainScreen].bounds.size.height //获取设备的物理高度
28 |
29 | /****************************** 颜色 ********************************/
30 | #define RGBColor(r,g,b,a) ([UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:a])
31 | /** tableView 边框颜色 */
32 | #define TABLEVIEW_BORDER_COLOR RGBColor(230, 230, 230, 1)
33 | /**所有控制的背景色 */
34 | #define VIEW_BGCOLOR RGBColor(240, 240, 240, 1)
35 | #define cellBlackColor RGBColor(235, 235, 245, 0.7)
36 |
37 |
38 | #endif
39 |
--------------------------------------------------------------------------------
/TextUtil/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | com.zx.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/TextUtil.xcodeproj/project.xcworkspace/xcshareddata/TextUtil.xccheckout:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDESourceControlProjectFavoriteDictionaryKey
6 |
7 | IDESourceControlProjectIdentifier
8 | 101B3700-9C04-4E75-B857-68F594AEAA53
9 | IDESourceControlProjectName
10 | TextUtil
11 | IDESourceControlProjectOriginsDictionary
12 |
13 | C2A3E10B52AE52188240D6161EBF206ED93970DE
14 | https://github.com/Joker-King/TextUtil.git
15 |
16 | IDESourceControlProjectPath
17 | TextUtil.xcodeproj
18 | IDESourceControlProjectRelativeInstallPathDictionary
19 |
20 | C2A3E10B52AE52188240D6161EBF206ED93970DE
21 | ../..
22 |
23 | IDESourceControlProjectURL
24 | https://github.com/Joker-King/TextUtil.git
25 | IDESourceControlProjectVersion
26 | 111
27 | IDESourceControlProjectWCCIdentifier
28 | C2A3E10B52AE52188240D6161EBF206ED93970DE
29 | IDESourceControlProjectWCConfigurations
30 |
31 |
32 | IDESourceControlRepositoryExtensionIdentifierKey
33 | public.vcs.git
34 | IDESourceControlWCCIdentifierKey
35 | C2A3E10B52AE52188240D6161EBF206ED93970DE
36 | IDESourceControlWCCName
37 | TextUtil
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/TextUtil/Utils/JKDBHelper.m:
--------------------------------------------------------------------------------
1 | //
2 | // JKDataBase.m
3 | // JKBaseModel
4 | //
5 | // github:https://github.com/Joker-King/JKDBModel
6 | // Created by zx_04 on 15/6/24.
7 | //
8 | //
9 |
10 | #import "JKDBHelper.h"
11 |
12 | @interface JKDBHelper ()
13 |
14 | @property (nonatomic, retain) FMDatabaseQueue *dbQueue;
15 |
16 | @end
17 |
18 | @implementation JKDBHelper
19 |
20 | static JKDBHelper *_instance = nil;
21 |
22 | + (instancetype)shareInstance
23 | {
24 | static dispatch_once_t onceToken ;
25 | dispatch_once(&onceToken, ^{
26 | _instance = [[super allocWithZone:NULL] init] ;
27 | }) ;
28 |
29 | return _instance;
30 | }
31 |
32 | + (NSString *)dbPath
33 | {
34 | NSString *docsdir = [NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
35 | NSFileManager *filemanage = [NSFileManager defaultManager];
36 | docsdir = [docsdir stringByAppendingPathComponent:@"JKBD"];
37 | BOOL isDir;
38 | BOOL exit =[filemanage fileExistsAtPath:docsdir isDirectory:&isDir];
39 | if (!exit || !isDir) {
40 | [filemanage createDirectoryAtPath:docsdir withIntermediateDirectories:YES attributes:nil error:nil];
41 | }
42 | NSString *dbpath = [docsdir stringByAppendingPathComponent:@"jkdb.sqlite"];
43 | return dbpath;
44 | }
45 |
46 | - (FMDatabaseQueue *)dbQueue
47 | {
48 | if (_dbQueue == nil) {
49 | _dbQueue = [[FMDatabaseQueue alloc] initWithPath:[self.class dbPath]];
50 | }
51 | return _dbQueue;
52 | }
53 |
54 | + (id)allocWithZone:(struct _NSZone *)zone
55 | {
56 | return [JKDBHelper shareInstance];
57 | }
58 |
59 | - (id)copyWithZone:(struct _NSZone *)zone
60 | {
61 | return [JKDBHelper shareInstance];
62 | }
63 |
64 | #if ! __has_feature(objc_arc)
65 | - (oneway void)release
66 | {
67 |
68 | }
69 |
70 | - (id)autorelease
71 | {
72 | return _instance;
73 | }
74 |
75 | - (NSUInteger)retainCount
76 | {
77 | return 1;
78 | }
79 | #endif
80 |
81 | @end
82 |
--------------------------------------------------------------------------------
/TextUtil/Utils/JKDBModel.h:
--------------------------------------------------------------------------------
1 | //
2 | // JKBaseModel.h
3 | // JKBaseModel
4 | //
5 | // github:https://github.com/Joker-King/JKDBModel
6 | // Created by zx_04 on 15/6/27.
7 | // Copyright (c) 2015年 joker. All rights reserved.
8 | //
9 |
10 | #import
11 |
12 | #import "JKDBHelper.h"
13 |
14 | /** SQLite五种数据类型 */
15 | #define SQLTEXT @"TEXT"
16 | #define SQLINTEGER @"INTEGER"
17 | #define SQLREAL @"REAL"
18 | #define SQLBLOB @"BLOB"
19 | #define SQLNULL @"NULL"
20 | #define PrimaryKey @"primary key"
21 |
22 | #define primaryId @"pk"
23 |
24 | @interface JKDBModel : NSObject
25 |
26 | /** 主键 id */
27 | @property (nonatomic, assign) int pk;
28 | /** 列名 */
29 | @property (retain, readonly, nonatomic) NSMutableArray *columeNames;
30 | /** 列类型 */
31 | @property (retain, readonly, nonatomic) NSMutableArray *columeTypes;
32 |
33 | /**
34 | * 获取该类的所有属性
35 | */
36 | + (NSDictionary *)getPropertys;
37 |
38 | /** 获取所有属性,包括主键 */
39 | + (NSDictionary *)getAllProperties;
40 |
41 | /** 数据库中是否存在表 */
42 | + (BOOL)isExistInTable;
43 |
44 | /** 表中的字段*/
45 | + (NSArray *)getColumns;
46 |
47 | /** 保存或更新
48 | * 如果不存在主键,保存,
49 | * 有主键,则更新
50 | */
51 | - (BOOL)saveOrUpdate;
52 | /** 保存单个数据 */
53 | - (BOOL)save;
54 | /** 批量保存数据 */
55 | + (BOOL)saveObjects:(NSArray *)array;
56 | /** 更新单个数据 */
57 | - (BOOL)update;
58 | /** 批量更新数据*/
59 | + (BOOL)updateObjects:(NSArray *)array;
60 | /** 删除单个数据 */
61 | - (BOOL)deleteObject;
62 | /** 批量删除数据 */
63 | + (BOOL)deleteObjects:(NSArray *)array;
64 | /** 通过条件删除数据 */
65 | + (BOOL)deleteObjectsByCriteria:(NSString *)criteria;
66 | /** 清空表 */
67 | + (BOOL)clearTable;
68 |
69 | /** 查询全部数据 */
70 | + (NSArray *)findAll;
71 |
72 | /** 通过主键查询 */
73 | + (instancetype)findByPK:(int)inPk;
74 |
75 | /** 查找某条数据 */
76 | + (instancetype)findFirstByCriteria:(NSString *)criteria;
77 |
78 | /** 通过条件查找数据
79 | * 这样可以进行分页查询 @" WHERE pk > 5 limit 10"
80 | */
81 | + (NSArray *)findByCriteria:(NSString *)criteria;
82 |
83 | /** 获取最大值 */
84 | + (int)getMaxOf:(NSString *)columeName;
85 |
86 | #pragma mark - must be override method
87 | /**
88 | * 创建表
89 | * 如果已经创建,返回YES
90 | */
91 | + (BOOL)createTable;
92 | /** 如果子类中有一些property不需要创建数据库字段,那么这个方法必须在子类中重写
93 | */
94 | + (NSArray *)transients;
95 |
96 |
97 | @end
98 |
--------------------------------------------------------------------------------
/TextUtil/emoticons.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | cht
7 | [微笑]
8 | png
9 | 001
10 |
11 |
12 | cht
13 | [撇嘴]
14 | png
15 | 002
16 |
17 |
18 | cht
19 | [色]
20 | png
21 | 003
22 |
23 |
24 | cht
25 | [发呆]
26 | png
27 | 004
28 |
29 |
30 | cht
31 | [得意]
32 | png
33 | 005
34 |
35 |
36 | cht
37 | [流泪]
38 | png
39 | 006
40 |
41 |
42 | cht
43 | [害羞]
44 | png
45 | 007
46 |
47 |
48 | cht
49 | [闭嘴]
50 | png
51 | 008
52 |
53 |
54 | cht
55 | [睡]
56 | png
57 | 009
58 |
59 |
60 | cht
61 | [大哭]
62 | png
63 | 010
64 |
65 |
66 | cht
67 | [尴尬]
68 | png
69 | 011
70 |
71 |
72 | cht
73 | [发怒]
74 | png
75 | 012
76 |
77 |
78 | cht
79 | [调皮]
80 | png
81 | 013
82 |
83 |
84 | cht
85 | [呲牙]
86 | png
87 | 014
88 |
89 |
90 | cht
91 | [惊讶]
92 | png
93 | 015
94 |
95 |
96 | cht
97 | [难过]
98 | png
99 | 016
100 |
101 |
102 | cht
103 | [酷]
104 | png
105 | 017
106 |
107 |
108 | cht
109 | [冷汗]
110 | png
111 | 018
112 |
113 |
114 | cht
115 | [抓狂]
116 | png
117 | 019
118 |
119 |
120 | cht
121 | [吐]
122 | png
123 | 020
124 |
125 |
126 | cht
127 | [偷笑]
128 | png
129 | 021
130 |
131 |
132 |
133 |
--------------------------------------------------------------------------------
/TextUtil/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/TextUtil/Chat/Views/YYFaceScrollView.m:
--------------------------------------------------------------------------------
1 | //
2 | // YYFaceScrollView.m
3 | // ismarter2.0_sz
4 | //
5 | // Created by zx_04 on 15/6/15.
6 | //
7 | //
8 |
9 | #import "YYFaceScrollView.h"
10 |
11 | @implementation YYFaceScrollView
12 |
13 | - (id)initWithFrame:(CGRect)frame
14 | {
15 | self = [super initWithFrame:frame];
16 | if (self) {
17 | [self initViews];
18 | }
19 | return self;
20 | }
21 |
22 | - (id)initWithSelectBlock:(SelectBlock)block
23 | {
24 | self = [self initWithFrame:CGRectZero];
25 | if (self != nil) {
26 | faceView.block = block;
27 | }
28 | return self;
29 | }
30 |
31 | - (void)initViews
32 | {
33 | //顶部的分隔线
34 | UIView *topLineView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kWidth, 0.5)];
35 | topLineView.backgroundColor = [UIColor grayColor];
36 | topLineView.alpha = 0.3;
37 | [self addSubview:topLineView];
38 |
39 | faceView = [[YYFaceView alloc] initWithFrame:CGRectZero];
40 |
41 | scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, kWidth, faceView.height)];
42 | scrollView.backgroundColor = [UIColor clearColor];
43 | scrollView.contentSize = CGSizeMake(faceView.width, faceView.height);
44 | scrollView.pagingEnabled = YES;
45 | scrollView.showsHorizontalScrollIndicator = NO;
46 | scrollView.clipsToBounds = NO;
47 | scrollView.delegate = self;
48 |
49 | [scrollView addSubview:faceView];
50 | [self addSubview:scrollView];
51 |
52 | pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, scrollView.bottom, 40, 20)];
53 | pageControl.backgroundColor = [UIColor clearColor];
54 | pageControl.numberOfPages = faceView.pageNumber;
55 | pageControl.currentPage = 0;
56 | [self addSubview:pageControl];
57 |
58 | [self addbottomView];
59 |
60 | self.height = scrollView.height + pageControl.height + 10 +bottomView.height;
61 | self.width = scrollView.width;
62 | }
63 |
64 | - (void)addbottomView
65 | {
66 | // bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, pageControl.bottom+10, 320, 35)];
67 | bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, pageControl.bottom+10, kWidth, 35)];
68 | bottomView.backgroundColor = [UIColor clearColor];
69 | [self addSubview:bottomView];
70 |
71 | UIView *topLine =[[UIView alloc] initWithFrame:CGRectMake(0, 0, bottomView.width, 0.5)];
72 | topLine.backgroundColor = [UIColor grayColor];
73 | [bottomView addSubview:topLine];
74 |
75 | UIButton *smallemoBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, bottomView.height, bottomView.height)];
76 | smallemoBtn.backgroundColor = [UIColor clearColor];
77 | [smallemoBtn setImage:[UIImage imageNamed:@"emotion"] forState:UIControlStateNormal];
78 | [smallemoBtn addTarget:self action:@selector(changeForEmotion) forControlEvents:UIControlEventTouchUpInside];
79 | [bottomView addSubview:smallemoBtn];
80 |
81 | UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(smallemoBtn.right+2, 3, 1, smallemoBtn.height-6)];
82 | lineView.backgroundColor = [UIColor grayColor];
83 | [bottomView addSubview:lineView];
84 |
85 | UIButton *sendBtn = [[UIButton alloc] initWithFrame:CGRectMake(kWidth-60, 0, 60, bottomView.height)];
86 | sendBtn.backgroundColor = RGBColor(0, 122, 255, 1);
87 | [sendBtn setTitle:@"发送" forState:UIControlStateNormal];
88 | [sendBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
89 | [sendBtn addTarget:self action:@selector(sendBtnClick) forControlEvents:UIControlEventTouchUpInside];
90 | [bottomView addSubview:sendBtn];
91 | }
92 |
93 | - (void)scrollViewDidScroll:(UIScrollView *)_scrollView;
94 | {
95 | int pageNumber = _scrollView.contentOffset.x/320;
96 | pageControl.currentPage = pageNumber;
97 | }
98 |
99 | - (void)changeForEmotion
100 | {
101 | NSLog(@"%s",__func__);
102 | }
103 |
104 | - (void)sendBtnClick
105 | {
106 | NSLog(@"%s",__func__);
107 | if (_sendBlock) {
108 | _sendBlock();
109 | }
110 | }
111 |
112 | @end
113 |
--------------------------------------------------------------------------------
/TextUtil.xcodeproj/xcuserdata/zx_04.xcuserdatad/xcschemes/TextUtil.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
47 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
65 |
66 |
75 |
77 |
83 |
84 |
85 |
86 |
87 |
88 |
94 |
96 |
102 |
103 |
104 |
105 |
107 |
108 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/TextUtil/Utils/UIViewExt.m:
--------------------------------------------------------------------------------
1 | /*
2 | Erica Sadun, http://ericasadun.com
3 | iPhone Developer's Cookbook, 3.0 Edition
4 | BSD License, Use at your own risk
5 | */
6 |
7 | #import "UIViewExt.h"
8 |
9 | CGPoint CGRectGetCenter(CGRect rect)
10 | {
11 | CGPoint pt;
12 | pt.x = CGRectGetMidX(rect);
13 | pt.y = CGRectGetMidY(rect);
14 | return pt;
15 | }
16 |
17 | CGRect CGRectMoveToCenter(CGRect rect, CGPoint center)
18 | {
19 | CGRect newrect = CGRectZero;
20 | newrect.origin.x = center.x-CGRectGetMidX(rect);
21 | newrect.origin.y = center.y-CGRectGetMidY(rect);
22 | newrect.size = rect.size;
23 | return newrect;
24 | }
25 |
26 | @implementation UIView (ViewGeometry)
27 |
28 | // Retrieve and set the origin
29 | - (CGPoint) origin
30 | {
31 | return self.frame.origin;
32 | }
33 |
34 | - (void) setOrigin: (CGPoint) aPoint
35 | {
36 | CGRect newframe = self.frame;
37 | newframe.origin = aPoint;
38 | self.frame = newframe;
39 | }
40 |
41 |
42 | // Retrieve and set the size
43 | - (CGSize) size
44 | {
45 | return self.frame.size;
46 | }
47 |
48 | - (void) setSize: (CGSize) aSize
49 | {
50 | CGRect newframe = self.frame;
51 | newframe.size = aSize;
52 | self.frame = newframe;
53 | }
54 |
55 | // Query other frame locations
56 | - (CGPoint) bottomRight
57 | {
58 | CGFloat x = self.frame.origin.x + self.frame.size.width;
59 | CGFloat y = self.frame.origin.y + self.frame.size.height;
60 | return CGPointMake(x, y);
61 | }
62 |
63 | - (CGPoint) bottomLeft
64 | {
65 | CGFloat x = self.frame.origin.x;
66 | CGFloat y = self.frame.origin.y + self.frame.size.height;
67 | return CGPointMake(x, y);
68 | }
69 |
70 | - (CGPoint) topRight
71 | {
72 | CGFloat x = self.frame.origin.x + self.frame.size.width;
73 | CGFloat y = self.frame.origin.y;
74 | return CGPointMake(x, y);
75 | }
76 |
77 |
78 | // Retrieve and set height, width, top, bottom, left, right
79 | - (CGFloat) height
80 | {
81 | return self.frame.size.height;
82 | }
83 |
84 | - (void) setHeight: (CGFloat) newheight
85 | {
86 | CGRect newframe = self.frame;
87 | newframe.size.height = newheight;
88 | self.frame = newframe;
89 | }
90 |
91 | - (CGFloat) width
92 | {
93 | return self.frame.size.width;
94 | }
95 |
96 | - (void) setWidth: (CGFloat) newwidth
97 | {
98 | CGRect newframe = self.frame;
99 | newframe.size.width = newwidth;
100 | self.frame = newframe;
101 | }
102 |
103 | - (CGFloat) top
104 | {
105 | return self.frame.origin.y;
106 | }
107 |
108 | - (void) setTop: (CGFloat) newtop
109 | {
110 | CGRect newframe = self.frame;
111 | newframe.origin.y = newtop;
112 | self.frame = newframe;
113 | }
114 |
115 | - (CGFloat) left
116 | {
117 | return self.frame.origin.x;
118 | }
119 |
120 | - (void) setLeft: (CGFloat) newleft
121 | {
122 | CGRect newframe = self.frame;
123 | newframe.origin.x = newleft;
124 | self.frame = newframe;
125 | }
126 |
127 | - (CGFloat) bottom
128 | {
129 | return self.frame.origin.y + self.frame.size.height;
130 | }
131 |
132 | - (void) setBottom: (CGFloat) newbottom
133 | {
134 | CGRect newframe = self.frame;
135 | newframe.origin.y = newbottom - self.frame.size.height;
136 | self.frame = newframe;
137 | }
138 |
139 | - (CGFloat) right
140 | {
141 | return self.frame.origin.x + self.frame.size.width;
142 | }
143 |
144 | - (void) setRight: (CGFloat) newright
145 | {
146 | CGFloat delta = newright - (self.frame.origin.x + self.frame.size.width);
147 | CGRect newframe = self.frame;
148 | newframe.origin.x += delta ;
149 | self.frame = newframe;
150 | }
151 |
152 | // Move via offset
153 | - (void) moveBy: (CGPoint) delta
154 | {
155 | CGPoint newcenter = self.center;
156 | newcenter.x += delta.x;
157 | newcenter.y += delta.y;
158 | self.center = newcenter;
159 | }
160 |
161 | // Scaling
162 | - (void) scaleBy: (CGFloat) scaleFactor
163 | {
164 | CGRect newframe = self.frame;
165 | newframe.size.width *= scaleFactor;
166 | newframe.size.height *= scaleFactor;
167 | self.frame = newframe;
168 | }
169 |
170 | // Ensure that both dimensions fit within the given size by scaling down
171 | - (void) fitInSize: (CGSize) aSize
172 | {
173 | CGFloat scale;
174 | CGRect newframe = self.frame;
175 |
176 | if (newframe.size.height && (newframe.size.height > aSize.height))
177 | {
178 | scale = aSize.height / newframe.size.height;
179 | newframe.size.width *= scale;
180 | newframe.size.height *= scale;
181 | }
182 |
183 | if (newframe.size.width && (newframe.size.width >= aSize.width))
184 | {
185 | scale = aSize.width / newframe.size.width;
186 | newframe.size.width *= scale;
187 | newframe.size.height *= scale;
188 | }
189 |
190 | self.frame = newframe;
191 | }
192 |
193 | - (UIViewController *)viewController
194 | {
195 | UIResponder *next = [self nextResponder];
196 | do {
197 | if ([next isKindOfClass:[UIViewController class]]) {
198 | return (UIViewController *)next;
199 | }
200 |
201 | next = [next nextResponder];
202 |
203 | } while (next != nil);
204 |
205 |
206 | return nil;
207 | }
208 | @end
--------------------------------------------------------------------------------
/TextUtil/Discover/Controllers/DynamicViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // DynamicViewController.m
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/19.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import "DynamicViewController.h"
10 |
11 | #import "DynamicCell.h"
12 | #import "Dynamic.h"
13 |
14 | @interface DynamicViewController ()
15 |
16 | @property (nonatomic, strong) NSArray *dynamicData;
17 |
18 | @end
19 |
20 | @implementation DynamicViewController
21 |
22 | - (void)viewDidLoad {
23 | [super viewDidLoad];
24 |
25 | [self loadDynamicData];
26 | }
27 |
28 | - (void)loadDynamicData
29 | {
30 |
31 | Dynamic *dynamic = [[Dynamic alloc] init];
32 | dynamic.isPraise = YES;
33 | dynamic.location = @"深圳市";
34 | dynamic.createTime = @"12:50";
35 | dynamic.type = 0;
36 | dynamic.text = @"山不在高,有仙则名。水不在深,有龙则灵。斯是陋室,惟吾德馨。苔痕上阶绿,草色入帘青。谈笑有鸿儒,往来无白丁。可以调素琴,阅金经。无丝竹之乱耳,无案牍之劳形。南阳诸葛庐,西蜀子云亭。孔子云:何陋之有?";
37 | dynamic.imageCount = 0;
38 | dynamic.replyCount = 66;
39 | [dynamic save];
40 |
41 | Dynamic *dynamic2 = [[Dynamic alloc] init];
42 | dynamic2.isPraise = YES;
43 | dynamic2.location = @"上海";
44 | dynamic2.createTime = @"昨天 10:11";
45 | dynamic2.type = 1;
46 | dynamic2.text = nil;
47 | dynamic2.imageCount = 1;
48 | dynamic2.replyCount = 188;
49 | [dynamic2 save];
50 |
51 | Dynamic *dynamic3 = [[Dynamic alloc] init];
52 | dynamic3.isPraise = YES;
53 | dynamic3.location = @"北京市";
54 | dynamic3.createTime = @"前天 10:11";
55 | dynamic3.type = 1;
56 | dynamic3.text = @"人的一生可能燃烧也可能腐朽,我不能腐朽,我愿意燃烧起来!";
57 | dynamic3.imageCount = 3;
58 | dynamic3.replyCount = 66;
59 | [dynamic3 save];
60 |
61 | Dynamic *dynamic4 = [[Dynamic alloc] init];
62 | dynamic4.isPraise = YES;
63 | dynamic4.location = @"北京市";
64 | dynamic4.createTime = @"前天 10:11";
65 | dynamic4.type = 1;
66 | dynamic4.text = @"夫君子之行,静以修身,俭以养德,非淡泊无以明志,非宁静无以致远";
67 | dynamic4.imageCount = 9;
68 | dynamic4.replyCount = 211;
69 | [dynamic4 save];
70 |
71 | dispatch_async(dispatch_get_global_queue(0, 0), ^{
72 | NSArray *data = [Dynamic findAll];
73 | dispatch_async(dispatch_get_main_queue(), ^{
74 | _dynamicData = [[NSMutableArray alloc] initWithArray:data];
75 | [self.tableView reloadData];
76 | });
77 | });
78 | }
79 |
80 | #pragma mark - Table view data source
81 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
82 | // Return the number of rows in the section.
83 | return _dynamicData.count;
84 | }
85 |
86 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
87 | DynamicCell *cell = [DynamicCell cellWithTableView:tableView];
88 | Dynamic *dynamic = [_dynamicData objectAtIndex:indexPath.row];
89 | cell.dynamic = dynamic;
90 |
91 | return cell;
92 | }
93 |
94 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
95 | {
96 | Dynamic *dynamic = [_dynamicData objectAtIndex:indexPath.row];
97 | return [DynamicCell heightOfCellWithModel:dynamic];
98 | }
99 |
100 |
101 | /*
102 | // Override to support conditional editing of the table view.
103 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
104 | // Return NO if you do not want the specified item to be editable.
105 | return YES;
106 | }
107 | */
108 |
109 | /*
110 | // Override to support editing the table view.
111 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
112 | if (editingStyle == UITableViewCellEditingStyleDelete) {
113 | // Delete the row from the data source
114 | [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
115 | } else if (editingStyle == UITableViewCellEditingStyleInsert) {
116 | // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
117 | }
118 | }
119 | */
120 |
121 | /*
122 | // Override to support rearranging the table view.
123 | - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
124 | }
125 | */
126 |
127 | /*
128 | // Override to support conditional rearranging of the table view.
129 | - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
130 | // Return NO if you do not want the item to be re-orderable.
131 | return YES;
132 | }
133 | */
134 |
135 | /*
136 | #pragma mark - Navigation
137 |
138 | // In a storyboard-based application, you will often want to do a little preparation before navigation
139 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
140 | // Get the new view controller using [segue destinationViewController].
141 | // Pass the selected object to the new view controller.
142 | }
143 | */
144 |
145 | @end
146 |
--------------------------------------------------------------------------------
/TextUtil/OpenSources/FMDB/FMDatabasePool.h:
--------------------------------------------------------------------------------
1 | //
2 | // FMDatabasePool.h
3 | // fmdb
4 | //
5 | // Created by August Mueller on 6/22/11.
6 | // Copyright 2011 Flying Meat Inc. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "sqlite3.h"
11 |
12 | @class FMDatabase;
13 |
14 | /** Pool of `` objects.
15 |
16 | ### See also
17 |
18 | - ``
19 | - ``
20 |
21 | @warning Before using `FMDatabasePool`, please consider using `` instead.
22 |
23 | If you really really really know what you're doing and `FMDatabasePool` is what
24 | you really really need (ie, you're using a read only database), OK you can use
25 | it. But just be careful not to deadlock!
26 |
27 | For an example on deadlocking, search for:
28 | `ONLY_USE_THE_POOL_IF_YOU_ARE_DOING_READS_OTHERWISE_YOULL_DEADLOCK_USE_FMDATABASEQUEUE_INSTEAD`
29 | in the main.m file.
30 | */
31 |
32 | @interface FMDatabasePool : NSObject {
33 | NSString *_path;
34 |
35 | dispatch_queue_t _lockQueue;
36 |
37 | NSMutableArray *_databaseInPool;
38 | NSMutableArray *_databaseOutPool;
39 |
40 | __unsafe_unretained id _delegate;
41 |
42 | NSUInteger _maximumNumberOfDatabasesToCreate;
43 | int _openFlags;
44 | }
45 |
46 | /** Database path */
47 |
48 | @property (atomic, retain) NSString *path;
49 |
50 | /** Delegate object */
51 |
52 | @property (atomic, assign) id delegate;
53 |
54 | /** Maximum number of databases to create */
55 |
56 | @property (atomic, assign) NSUInteger maximumNumberOfDatabasesToCreate;
57 |
58 | /** Open flags */
59 |
60 | @property (atomic, readonly) int openFlags;
61 |
62 |
63 | ///---------------------
64 | /// @name Initialization
65 | ///---------------------
66 |
67 | /** Create pool using path.
68 |
69 | @param aPath The file path of the database.
70 |
71 | @return The `FMDatabasePool` object. `nil` on error.
72 | */
73 |
74 | + (instancetype)databasePoolWithPath:(NSString*)aPath;
75 |
76 | /** Create pool using path and specified flags
77 |
78 | @param aPath The file path of the database.
79 | @param openFlags Flags passed to the openWithFlags method of the database
80 |
81 | @return The `FMDatabasePool` object. `nil` on error.
82 | */
83 |
84 | + (instancetype)databasePoolWithPath:(NSString*)aPath flags:(int)openFlags;
85 |
86 | /** Create pool using path.
87 |
88 | @param aPath The file path of the database.
89 |
90 | @return The `FMDatabasePool` object. `nil` on error.
91 | */
92 |
93 | - (instancetype)initWithPath:(NSString*)aPath;
94 |
95 | /** Create pool using path and specified flags.
96 |
97 | @param aPath The file path of the database.
98 | @param openFlags Flags passed to the openWithFlags method of the database
99 |
100 | @return The `FMDatabasePool` object. `nil` on error.
101 | */
102 |
103 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags;
104 |
105 | ///------------------------------------------------
106 | /// @name Keeping track of checked in/out databases
107 | ///------------------------------------------------
108 |
109 | /** Number of checked-in databases in pool
110 |
111 | @returns Number of databases
112 | */
113 |
114 | - (NSUInteger)countOfCheckedInDatabases;
115 |
116 | /** Number of checked-out databases in pool
117 |
118 | @returns Number of databases
119 | */
120 |
121 | - (NSUInteger)countOfCheckedOutDatabases;
122 |
123 | /** Total number of databases in pool
124 |
125 | @returns Number of databases
126 | */
127 |
128 | - (NSUInteger)countOfOpenDatabases;
129 |
130 | /** Release all databases in pool */
131 |
132 | - (void)releaseAllDatabases;
133 |
134 | ///------------------------------------------
135 | /// @name Perform database operations in pool
136 | ///------------------------------------------
137 |
138 | /** Synchronously perform database operations in pool.
139 |
140 | @param block The code to be run on the `FMDatabasePool` pool.
141 | */
142 |
143 | - (void)inDatabase:(void (^)(FMDatabase *db))block;
144 |
145 | /** Synchronously perform database operations in pool using transaction.
146 |
147 | @param block The code to be run on the `FMDatabasePool` pool.
148 | */
149 |
150 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
151 |
152 | /** Synchronously perform database operations in pool using deferred transaction.
153 |
154 | @param block The code to be run on the `FMDatabasePool` pool.
155 | */
156 |
157 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
158 |
159 | #if SQLITE_VERSION_NUMBER >= 3007000
160 |
161 | /** Synchronously perform database operations in pool using save point.
162 |
163 | @param block The code to be run on the `FMDatabasePool` pool.
164 |
165 | @return `NSError` object if error; `nil` if successful.
166 |
167 | @warning You can not nest these, since calling it will pull another database out of the pool and you'll get a deadlock. If you need to nest, use `<[FMDatabase startSavePointWithName:error:]>` instead.
168 | */
169 |
170 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block;
171 | #endif
172 |
173 | @end
174 |
175 |
176 | /** FMDatabasePool delegate category
177 |
178 | This is a category that defines the protocol for the FMDatabasePool delegate
179 | */
180 |
181 | @interface NSObject (FMDatabasePoolDelegate)
182 |
183 | /** Asks the delegate whether database should be added to the pool.
184 |
185 | @param pool The `FMDatabasePool` object.
186 | @param database The `FMDatabase` object.
187 |
188 | @return `YES` if it should add database to pool; `NO` if not.
189 |
190 | */
191 |
192 | - (BOOL)databasePool:(FMDatabasePool*)pool shouldAddDatabaseToPool:(FMDatabase*)database;
193 |
194 | /** Tells the delegate that database was added to the pool.
195 |
196 | @param pool The `FMDatabasePool` object.
197 | @param database The `FMDatabase` object.
198 |
199 | */
200 |
201 | - (void)databasePool:(FMDatabasePool*)pool didAddDatabase:(FMDatabase*)database;
202 |
203 | @end
204 |
205 |
--------------------------------------------------------------------------------
/TextUtil/Chat/Views/YYFaceView.m:
--------------------------------------------------------------------------------
1 | //
2 | // YYFaceView.m
3 | //
4 | //
5 | // Created by Joker on 14-1-6.
6 | // Copyright (c) 2014年 Mac. All rights reserved.
7 | //
8 |
9 | #import "YYFaceView.h"
10 |
11 | #define item_width 42
12 | #define item_height 45
13 |
14 | @implementation YYFaceView
15 |
16 | - (id)initWithFrame:(CGRect)frame
17 | {
18 | self = [super initWithFrame:frame];
19 | if (self) {
20 | [self initData];
21 | self.backgroundColor = [UIColor clearColor];
22 | }
23 | return self;
24 | }
25 |
26 | /**
27 | * 行 row:3
28 | * 列 colum:7
29 | * 表情尺寸 30*30 pixels
30 | */
31 | /*
32 | *
33 | items = [
34 | ["表情1",“表情2”,“表情3”,......“表情28”],
35 | ["表情1",“表情2”,“表情3”,......“表情28”],
36 | ["表情1",“表情2”,“表情3”,......“表情28”]
37 | ];
38 |
39 | */
40 |
41 | - (void)initData
42 | {
43 | items = [[NSMutableArray alloc] init];
44 |
45 | //---------------整理表情,整理成一个二维数组---------------
46 | NSString *filePath = [[NSBundle mainBundle] pathForResource:@"emoticons" ofType:@"plist"];
47 | NSArray *fileArray = [NSArray arrayWithContentsOfFile:filePath];
48 |
49 | NSMutableArray *items2D = nil;
50 | for (int i=0; i 6) {
130 | colum = 6;
131 | }
132 | if (colum < 0) {
133 | colum = 0;
134 | }
135 |
136 | if (row > 2) {
137 | row = 1;
138 | }
139 | if (row < 0) {
140 | row = 0;
141 | }
142 |
143 | //计算选中表情的索引
144 | int index = colum + (row * 7);
145 | NSArray *item2D = [items objectAtIndex:page];
146 | if (index >= item2D.count) {
147 | return;
148 | }
149 | NSDictionary *item = [item2D objectAtIndex:index];
150 | NSString *faceName = [item objectForKey:@"cht"];
151 |
152 | if (![self.selectedFaceName isEqualToString:faceName]) {
153 | //给放大镜添加上表情
154 | NSString *imageName = [item objectForKey:@"png"];
155 | UIImage *image = [UIImage imageNamed:imageName];
156 |
157 | UIImageView *faceItem = (UIImageView *)[magnifierView viewWithTag:2013];
158 | faceItem.image = image;
159 |
160 | magnifierView.left = (page * 320) + colum *item_width;
161 | magnifierView.bottom = row *item_height + 30;
162 |
163 | self.selectedFaceName = faceName;
164 | }
165 |
166 | }
167 |
168 | #pragma mark - touch事件
169 | //touch 触摸开始
170 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
171 | {
172 | magnifierView.hidden = NO;
173 | UITouch *touch = [touches anyObject];
174 | CGPoint point = [touch locationInView:self];
175 | [self touchFace:point];
176 |
177 | if ([self.superview isKindOfClass:[UIScrollView class]]) {
178 | UIScrollView *scrollView = (UIScrollView *)self.superview;
179 | scrollView.scrollEnabled = NO;
180 | }
181 |
182 | }
183 |
184 | //touch 触摸移动
185 | - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
186 | {
187 | UITouch *touch = [touches anyObject];
188 | CGPoint point = [touch locationInView:self];
189 | [self touchFace:point];
190 | }
191 |
192 | //touch 触摸结束
193 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
194 | {
195 | magnifierView.hidden = YES;
196 | if ([self.superview isKindOfClass:[UIScrollView class]]) {
197 | UIScrollView *scrollView = (UIScrollView *)self.superview;
198 | scrollView.scrollEnabled = YES;
199 | }
200 |
201 | if (self.block != nil) {
202 | _block(_selectedFaceName);
203 | }
204 | }
205 |
206 | - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
207 | {
208 | magnifierView.hidden = YES;
209 | if ([self.superview isKindOfClass:[UIScrollView class]]) {
210 | UIScrollView *scrollView = (UIScrollView *)self.superview;
211 | scrollView.scrollEnabled = YES;
212 | }
213 | }
214 |
215 | @end
216 |
--------------------------------------------------------------------------------
/TextUtil/OpenSources/FMDB/FMDatabaseQueue.h:
--------------------------------------------------------------------------------
1 | //
2 | // FMDatabaseQueue.h
3 | // fmdb
4 | //
5 | // Created by August Mueller on 6/22/11.
6 | // Copyright 2011 Flying Meat Inc. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "sqlite3.h"
11 |
12 | @class FMDatabase;
13 |
14 | /** To perform queries and updates on multiple threads, you'll want to use `FMDatabaseQueue`.
15 |
16 | Using a single instance of `` from multiple threads at once is a bad idea. It has always been OK to make a `` object *per thread*. Just don't share a single instance across threads, and definitely not across multiple threads at the same time.
17 |
18 | Instead, use `FMDatabaseQueue`. Here's how to use it:
19 |
20 | First, make your queue.
21 |
22 | FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];
23 |
24 | Then use it like so:
25 |
26 | [queue inDatabase:^(FMDatabase *db) {
27 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];
28 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];
29 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];
30 |
31 | FMResultSet *rs = [db executeQuery:@"select * from foo"];
32 | while ([rs next]) {
33 | //…
34 | }
35 | }];
36 |
37 | An easy way to wrap things up in a transaction can be done like this:
38 |
39 | [queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
40 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];
41 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];
42 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];
43 |
44 | if (whoopsSomethingWrongHappened) {
45 | *rollback = YES;
46 | return;
47 | }
48 | // etc…
49 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]];
50 | }];
51 |
52 | `FMDatabaseQueue` will run the blocks on a serialized queue (hence the name of the class). So if you call `FMDatabaseQueue`'s methods from multiple threads at the same time, they will be executed in the order they are received. This way queries and updates won't step on each other's toes, and every one is happy.
53 |
54 | ### See also
55 |
56 | - ``
57 |
58 | @warning Do not instantiate a single `` object and use it across multiple threads. Use `FMDatabaseQueue` instead.
59 |
60 | @warning The calls to `FMDatabaseQueue`'s methods are blocking. So even though you are passing along blocks, they will **not** be run on another thread.
61 |
62 | */
63 |
64 | @interface FMDatabaseQueue : NSObject {
65 | NSString *_path;
66 | dispatch_queue_t _queue;
67 | FMDatabase *_db;
68 | int _openFlags;
69 | }
70 |
71 | /** Path of database */
72 |
73 | @property (atomic, retain) NSString *path;
74 |
75 | /** Open flags */
76 |
77 | @property (atomic, readonly) int openFlags;
78 |
79 | ///----------------------------------------------------
80 | /// @name Initialization, opening, and closing of queue
81 | ///----------------------------------------------------
82 |
83 | /** Create queue using path.
84 |
85 | @param aPath The file path of the database.
86 |
87 | @return The `FMDatabaseQueue` object. `nil` on error.
88 | */
89 |
90 | + (instancetype)databaseQueueWithPath:(NSString*)aPath;
91 |
92 | /** Create queue using path and specified flags.
93 |
94 | @param aPath The file path of the database.
95 | @param openFlags Flags passed to the openWithFlags method of the database
96 |
97 | @return The `FMDatabaseQueue` object. `nil` on error.
98 | */
99 | + (instancetype)databaseQueueWithPath:(NSString*)aPath flags:(int)openFlags;
100 |
101 | /** Create queue using path.
102 |
103 | @param aPath The file path of the database.
104 |
105 | @return The `FMDatabaseQueue` object. `nil` on error.
106 | */
107 |
108 | - (instancetype)initWithPath:(NSString*)aPath;
109 |
110 | /** Create queue using path and specified flags.
111 |
112 | @param aPath The file path of the database.
113 | @param openFlags Flags passed to the openWithFlags method of the database
114 |
115 | @return The `FMDatabaseQueue` object. `nil` on error.
116 | */
117 |
118 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags;
119 |
120 | /** Returns the Class of 'FMDatabase' subclass, that will be used to instantiate database object.
121 |
122 | Subclasses can override this method to return specified Class of 'FMDatabase' subclass.
123 |
124 | @return The Class of 'FMDatabase' subclass, that will be used to instantiate database object.
125 | */
126 |
127 | + (Class)databaseClass;
128 |
129 | /** Close database used by queue. */
130 |
131 | - (void)close;
132 |
133 | ///-----------------------------------------------
134 | /// @name Dispatching database operations to queue
135 | ///-----------------------------------------------
136 |
137 | /** Synchronously perform database operations on queue.
138 |
139 | @param block The code to be run on the queue of `FMDatabaseQueue`
140 | */
141 |
142 | - (void)inDatabase:(void (^)(FMDatabase *db))block;
143 |
144 | /** Synchronously perform database operations on queue, using transactions.
145 |
146 | @param block The code to be run on the queue of `FMDatabaseQueue`
147 | */
148 |
149 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
150 |
151 | /** Synchronously perform database operations on queue, using deferred transactions.
152 |
153 | @param block The code to be run on the queue of `FMDatabaseQueue`
154 | */
155 |
156 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
157 |
158 | ///-----------------------------------------------
159 | /// @name Dispatching database operations to queue
160 | ///-----------------------------------------------
161 |
162 | /** Synchronously perform database operations using save point.
163 |
164 | @param block The code to be run on the queue of `FMDatabaseQueue`
165 | */
166 |
167 | #if SQLITE_VERSION_NUMBER >= 3007000
168 | // NOTE: you can not nest these, since calling it will pull another database out of the pool and you'll get a deadlock.
169 | // If you need to nest, use FMDatabase's startSavePointWithName:error: instead.
170 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block;
171 | #endif
172 |
173 | @end
174 |
175 |
--------------------------------------------------------------------------------
/TextUtil/Chat/Views/ChatCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // ChatCell.m
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/19.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import "ChatCell.h"
10 | #import "ChatMessage.h"
11 | #import "Utility.h"
12 | #import "UIImage+Extension.h"
13 |
14 | #define kContentFontSize 16.0f //内容字体大小
15 | #define kPadding 5.0f //控件间隙
16 | #define kEdgeInsetsWidth 20.0f //内容内边距宽度
17 |
18 | @interface ChatCell ()
19 |
20 | /** 头像视图 */
21 | @property (nonatomic, retain) UIImageView *faceImageView;
22 | /** 背景图 */
23 | @property (nonatomic, retain) UIButton *bgButton;
24 | /** 文字内容视图 */
25 | @property (nonatomic, retain) UILabel *contentLabel;
26 |
27 | @end
28 |
29 | @implementation ChatCell
30 |
31 | #pragma mark - life cirle method
32 | - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
33 | {
34 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
35 | if (self) {
36 | [self initSubViews];
37 | }
38 | return self;
39 | }
40 |
41 | - (void)initSubViews
42 | {
43 | // 初始化头像视图
44 | _faceImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
45 | _faceImageView.layer.cornerRadius = 5;
46 | _faceImageView.layer.masksToBounds = YES;
47 | _faceImageView.backgroundColor = [UIColor clearColor];
48 | [self.contentView addSubview:_faceImageView];
49 |
50 | //初始化正文视图
51 | _bgButton = [[UIButton alloc] initWithFrame:CGRectZero];
52 | [self.contentView addSubview:_bgButton];
53 |
54 | //初始化正文视图
55 | _contentLabel = [[UILabel alloc] initWithFrame:CGRectZero];
56 | _contentLabel.font = [UIFont systemFontOfSize:kContentFontSize];
57 | _contentLabel.numberOfLines = 0;
58 | [_bgButton addSubview:_contentLabel];
59 | }
60 |
61 | #pragma mark - set subViews frame
62 | /** 设置头像的frame和内容 */
63 | - (void)setFaceFrame
64 | {
65 | CGFloat width = 40;
66 | CGFloat height = 40;
67 | if (_message.isSender) {//如果是自己发送
68 | _faceImageView.frame = CGRectMake(kWidth-width-kPadding, 10, width, height);
69 | } else {
70 | _faceImageView.frame = CGRectMake(kPadding, 10, width, height);
71 | }
72 | if (_message.isSender) {
73 | _faceImageView.image = [UIImage imageNamed:@"header_QQ"];
74 | } else {
75 | _faceImageView.image = [UIImage imageNamed:@"header_wechat"];
76 | }
77 | }
78 |
79 | /** 设置文字类型message的cellframe */
80 | - (void)setMessageFrame
81 | {
82 | // 1、计算文字的宽高
83 | float textMaxWidth = kWidth-40-kPadding *2-60; //60是消息框体距离右侧或者左侧的距离
84 |
85 | // NSMutableAttributedString *attrStr = [Utility emotionStrWithString:_message.content];
86 | NSMutableAttributedString *attrStr = [Utility emotionStrWithString:_message.content plistName:@"emoticons.plist" y:-8];
87 | [attrStr addAttribute:NSFontAttributeName
88 | value:[UIFont systemFontOfSize:kContentFontSize]
89 | range:NSMakeRange(0, attrStr.length)];
90 | CGSize textSize = [attrStr boundingRectWithSize:CGSizeMake(textMaxWidth, CGFLOAT_MAX)
91 | options:NSStringDrawingUsesLineFragmentOrigin
92 | context:nil].size;
93 |
94 | _contentLabel.attributedText = attrStr;
95 |
96 | _contentLabel.frame = CGRectMake(kEdgeInsetsWidth, kEdgeInsetsWidth, textSize.width, textSize.height);
97 | // 2、计算背景图片的frame,X坐标发送和接收计算方式不一样
98 | CGFloat bgY = CGRectGetMinY(_faceImageView.frame);
99 | CGFloat width = textSize.width + kEdgeInsetsWidth*2;
100 | CGFloat height = textSize.height + kEdgeInsetsWidth*2;
101 | UIImage *bgImage; //声明一个背景图片对象
102 | UIImage *bgHighImage;
103 | // 3、判断是否为自己发送,来设置frame以及背景图片
104 | if (_message.isSender) { //如果是自己发送的
105 | CGFloat bgX = kWidth-kPadding*2-CGRectGetWidth(_faceImageView.frame)-width;
106 | _bgButton.frame = CGRectMake(bgX,bgY, width, height);
107 | [_bgButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
108 | bgImage = [UIImage resizableImageWithName:@"chat_send_nor"];
109 | bgHighImage = [UIImage resizableImageWithName:@"chat_send_press_pic"];
110 | } else {
111 | CGFloat bgX = CGRectGetMaxX(_faceImageView.frame)+5;
112 | _bgButton.frame = CGRectMake(bgX, bgY, width, height);
113 | [_bgButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
114 | bgImage = [UIImage resizableImageWithName:@"chat_recive_nor"];
115 | bgHighImage = [UIImage resizableImageWithName:@"chat_recive_press_pic"];
116 | }
117 | [_bgButton setBackgroundImage:bgImage forState:UIControlStateNormal];
118 | [_bgButton setBackgroundImage:bgHighImage forState:UIControlStateHighlighted];
119 | }
120 |
121 |
122 | #pragma mark - class method
123 | + (instancetype)cellWithTableView:(UITableView *)tableView
124 | {
125 | static NSString *identifier = @"chatCell";
126 | ChatCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
127 | if (cell == nil) {
128 | cell = [[ChatCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
129 | cell.backgroundColor = [UIColor clearColor];
130 | cell.contentView.backgroundColor = [UIColor clearColor];
131 | }
132 | return cell;
133 | }
134 |
135 | /** 计算cell 的高度 */
136 | + (CGFloat)heightOfCellWithMessage:(ChatMessage *)message
137 | {
138 | CGFloat height = 0;
139 |
140 | float textMaxWidth = kWidth-40-kPadding *2-60; //60是消息框体距离右侧或者左侧的距离
141 |
142 | // NSMutableAttributedString *attrStr = [Utility emotionStrWithString:message.content];
143 | NSMutableAttributedString *attrStr = [Utility emotionStrWithString:message.content plistName:@"emoticons.plist" y:-8];
144 | [attrStr addAttribute:NSFontAttributeName
145 | value:[UIFont systemFontOfSize:kContentFontSize]
146 | range:NSMakeRange(0, attrStr.length)];
147 | CGSize textSize = [attrStr boundingRectWithSize:CGSizeMake(textMaxWidth, CGFLOAT_MAX)
148 | options:NSStringDrawingUsesLineFragmentOrigin
149 | context:nil].size;
150 | height += (textSize.height+kEdgeInsetsWidth*2);
151 |
152 | if (height < 60) {
153 | height = 60;
154 | }
155 | return height;
156 | }
157 |
158 | #pragma mark - setter and getter
159 | - (void)setMessage:(ChatMessage *)message
160 | {
161 | if (_message != message) {
162 | _message = message;
163 | }
164 |
165 | //设置头像
166 | [self setFaceFrame];
167 |
168 | //设置内容
169 | [self setMessageFrame];
170 | }
171 |
172 | @end
173 |
--------------------------------------------------------------------------------
/TextUtil/Chat/Controllers/ChatViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ChatViewController.m
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/19.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import "ChatViewController.h"
10 |
11 | #import "ChatCell.h"
12 | #import "ChatMessage.h"
13 | #import "YYFaceScrollView.h"
14 |
15 | @interface ChatViewController ()
16 |
17 | @property (weak, nonatomic) IBOutlet UITableView *tableView;
18 | @property (weak, nonatomic) IBOutlet UIView *bottomView;
19 | @property (weak, nonatomic) IBOutlet UITextField *textField;
20 | /** 表情视图 */
21 | @property (nonatomic, strong) YYFaceScrollView *faceView;
22 |
23 | @property (nonatomic, strong) NSMutableArray *messages;
24 |
25 | @end
26 |
27 | @implementation ChatViewController
28 |
29 | - (void)viewDidLoad {
30 | [super viewDidLoad];
31 | // Do any additional setup after loading the view.
32 |
33 | self.view.backgroundColor = VIEW_BGCOLOR;
34 |
35 | _tableView.tableFooterView = [UIView new];
36 | _tableView.showsVerticalScrollIndicator = NO;
37 | _tableView.backgroundColor = [UIColor clearColor];
38 |
39 | UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(cancelFocus)];
40 | [self.tableView addGestureRecognizer:tapGesture];
41 |
42 | //加载历史聊天记录
43 | [self loadChatRecords];
44 |
45 | }
46 |
47 | - (void)viewWillAppear:(BOOL)animated
48 | {
49 | [super viewWillAppear:animated];
50 |
51 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
52 | }
53 |
54 | - (void)viewWillDisappear:(BOOL)animated
55 | {
56 | [super viewWillDisappear:animated];
57 |
58 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
59 | }
60 |
61 | - (void)loadChatRecords
62 | {
63 | dispatch_async(dispatch_get_global_queue(0, 0), ^{
64 | NSArray *data = [ChatMessage findAll];
65 | dispatch_async(dispatch_get_main_queue(), ^{
66 | _messages = [[NSMutableArray alloc] initWithArray:data];
67 | [_tableView reloadData];
68 | });
69 | });
70 | }
71 |
72 | /** 取消事件的焦点 */
73 | - (void)cancelFocus
74 | {
75 | self.textField.text = nil;
76 | [self.textField resignFirstResponder];
77 |
78 | [UIView animateWithDuration:0.3f animations:^{
79 | // 1、修改输入框视图的位置
80 | _bottomView.bottom = kHeight-64;
81 | // 修改表情视图的位置
82 | _faceView.top = kHeight-64;
83 | // 2、修改表格的高度
84 | _tableView.height = _bottomView.top;
85 | }];
86 | }
87 |
88 | - (void)sendMessage:(NSString *)text
89 | {
90 | text = [text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
91 | if (text.length == 0) {
92 | return;
93 | }
94 | ChatMessage *chatMessage = [[ChatMessage alloc] init];
95 | chatMessage.isSender = YES;
96 | chatMessage.content = text;
97 | [chatMessage save];
98 | self.textField.text = nil;
99 | [_messages addObject:chatMessage];
100 | [_tableView reloadData];
101 |
102 | [self tableViewScrollToBottom];
103 | }
104 |
105 | - (void)tableViewScrollToBottom
106 | {
107 | if (_messages.count > 0) {
108 | NSIndexPath *indexPath = [NSIndexPath indexPathForRow:(_messages.count-1) inSection:0];
109 | [_tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
110 | }
111 | }
112 |
113 | - (IBAction)emtionClick:(id)sender {
114 | NSLog(@"%s--emtionClick",__func__);
115 | [self.textField resignFirstResponder];
116 | if (_faceView == nil) {
117 | __block __weak ChatViewController *this = self;
118 |
119 | _faceView = [[YYFaceScrollView alloc] initWithSelectBlock:^(NSString *faceName) {
120 | NSString *text = this.textField.text;
121 | NSString *appendText = [text stringByAppendingString:faceName];
122 | this.textField.text = appendText;
123 | }];
124 | _faceView.backgroundColor = RGBColor(220, 220, 220, 1);
125 | _faceView.top = kHeight - 20 - 44;
126 | _faceView.clipsToBounds = NO;
127 | _faceView.sendBlock = ^{
128 | NSString* fullText = this.textField.text;
129 | [this sendMessage:fullText];
130 | [this cancelFocus];
131 | };
132 | [self.view addSubview:_faceView];
133 | }
134 | float height = _faceView.height;
135 | //设置键盘动画
136 | __block CGRect frame;
137 | [UIView animateWithDuration:0.3 animations:^{
138 | _faceView.top = kHeight - 20 - 44 - height;
139 | //调整bottomView的高度
140 | self.bottomView.bottom = _faceView.top;
141 | frame = _bottomView.frame;
142 | self.inputView.frame = frame;
143 | }];
144 | }
145 |
146 | #pragma mark - UITextFieldDelegate
147 | - (BOOL)textFieldShouldReturn:(UITextField *)textField
148 | {
149 | [self sendMessage:_textField.text];
150 | return YES;
151 | }
152 |
153 | #pragma mark - Notification event
154 | - (void)keyboardWillShow:(NSNotification *)notification
155 | {
156 | NSDictionary *userInfo = [notification userInfo];
157 | NSValue *value = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
158 | CGRect frame = value.CGRectValue;
159 |
160 | NSNumber *duration = [userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];
161 | NSNumber *curve = [userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey];
162 |
163 | // 添加移动动画,使视图跟随键盘移动
164 | [UIView animateWithDuration:duration.doubleValue animations:^{
165 | [UIView setAnimationBeginsFromCurrentState:YES];
166 | [UIView setAnimationCurve:[curve intValue]];
167 | CGFloat bottom = kHeight-frame.size.height-64;
168 | //1.修改输入框View的位置
169 | _bottomView.bottom = bottom;
170 | //2.修改tableView的高度
171 | _tableView.height = _bottomView.top;
172 | } completion:^(BOOL finished) {
173 | [self tableViewScrollToBottom];
174 | }];
175 | }
176 |
177 | #pragma mark - UITableViewDataSource
178 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
179 | {
180 | return _messages.count;
181 | }
182 |
183 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
184 | {
185 | ChatCell *cell = [ChatCell cellWithTableView:tableView];
186 | cell.message = [_messages objectAtIndex:indexPath.row];
187 |
188 | return cell;
189 | }
190 |
191 | -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
192 | {
193 | ChatMessage *message = [_messages objectAtIndex:indexPath.row];
194 |
195 | return [ChatCell heightOfCellWithMessage:message];
196 | }
197 |
198 | @end
199 |
--------------------------------------------------------------------------------
/TextUtil/OpenSources/FMDB/FMDatabaseQueue.m:
--------------------------------------------------------------------------------
1 | //
2 | // FMDatabaseQueue.m
3 | // fmdb
4 | //
5 | // Created by August Mueller on 6/22/11.
6 | // Copyright 2011 Flying Meat Inc. All rights reserved.
7 | //
8 |
9 | #import "FMDatabaseQueue.h"
10 | #import "FMDatabase.h"
11 |
12 | /*
13 |
14 | Note: we call [self retain]; before using dispatch_sync, just incase
15 | FMDatabaseQueue is released on another thread and we're in the middle of doing
16 | something in dispatch_sync
17 |
18 | */
19 |
20 | /*
21 | * A key used to associate the FMDatabaseQueue object with the dispatch_queue_t it uses.
22 | * This in turn is used for deadlock detection by seeing if inDatabase: is called on
23 | * the queue's dispatch queue, which should not happen and causes a deadlock.
24 | */
25 | static const void * const kDispatchQueueSpecificKey = &kDispatchQueueSpecificKey;
26 |
27 | @implementation FMDatabaseQueue
28 |
29 | @synthesize path = _path;
30 | @synthesize openFlags = _openFlags;
31 |
32 | + (instancetype)databaseQueueWithPath:(NSString*)aPath {
33 |
34 | FMDatabaseQueue *q = [[self alloc] initWithPath:aPath];
35 |
36 | FMDBAutorelease(q);
37 |
38 | return q;
39 | }
40 |
41 | + (instancetype)databaseQueueWithPath:(NSString*)aPath flags:(int)openFlags {
42 |
43 | FMDatabaseQueue *q = [[self alloc] initWithPath:aPath flags:openFlags];
44 |
45 | FMDBAutorelease(q);
46 |
47 | return q;
48 | }
49 |
50 | + (Class)databaseClass {
51 | return [FMDatabase class];
52 | }
53 |
54 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags {
55 |
56 | self = [super init];
57 |
58 | if (self != nil) {
59 |
60 | _db = [[[self class] databaseClass] databaseWithPath:aPath];
61 | FMDBRetain(_db);
62 |
63 | #if SQLITE_VERSION_NUMBER >= 3005000
64 | BOOL success = [_db openWithFlags:openFlags];
65 | #else
66 | BOOL success = [_db open];
67 | #endif
68 | if (!success) {
69 | NSLog(@"Could not create database queue for path %@", aPath);
70 | FMDBRelease(self);
71 | return 0x00;
72 | }
73 |
74 | _path = FMDBReturnRetained(aPath);
75 |
76 | _queue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL);
77 | dispatch_queue_set_specific(_queue, kDispatchQueueSpecificKey, (__bridge void *)self, NULL);
78 | _openFlags = openFlags;
79 | }
80 |
81 | return self;
82 | }
83 |
84 | - (instancetype)initWithPath:(NSString*)aPath {
85 |
86 | // default flags for sqlite3_open
87 | return [self initWithPath:aPath flags:SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE];
88 | }
89 |
90 | - (instancetype)init {
91 | return [self initWithPath:nil];
92 | }
93 |
94 |
95 | - (void)dealloc {
96 |
97 | FMDBRelease(_db);
98 | FMDBRelease(_path);
99 |
100 | if (_queue) {
101 | FMDBDispatchQueueRelease(_queue);
102 | _queue = 0x00;
103 | }
104 | #if ! __has_feature(objc_arc)
105 | [super dealloc];
106 | #endif
107 | }
108 |
109 | - (void)close {
110 | FMDBRetain(self);
111 | dispatch_sync(_queue, ^() {
112 | [self->_db close];
113 | FMDBRelease(_db);
114 | self->_db = 0x00;
115 | });
116 | FMDBRelease(self);
117 | }
118 |
119 | - (FMDatabase*)database {
120 | if (!_db) {
121 | _db = FMDBReturnRetained([FMDatabase databaseWithPath:_path]);
122 |
123 | #if SQLITE_VERSION_NUMBER >= 3005000
124 | BOOL success = [_db openWithFlags:_openFlags];
125 | #else
126 | BOOL success = [_db open];
127 | #endif
128 | if (!success) {
129 | NSLog(@"FMDatabaseQueue could not reopen database for path %@", _path);
130 | FMDBRelease(_db);
131 | _db = 0x00;
132 | return 0x00;
133 | }
134 | }
135 |
136 | return _db;
137 | }
138 |
139 | - (void)inDatabase:(void (^)(FMDatabase *db))block {
140 | /* Get the currently executing queue (which should probably be nil, but in theory could be another DB queue
141 | * and then check it against self to make sure we're not about to deadlock. */
142 | FMDatabaseQueue *currentSyncQueue = (__bridge id)dispatch_get_specific(kDispatchQueueSpecificKey);
143 | assert(currentSyncQueue != self && "inDatabase: was called reentrantly on the same queue, which would lead to a deadlock");
144 |
145 | FMDBRetain(self);
146 |
147 | dispatch_sync(_queue, ^() {
148 |
149 | FMDatabase *db = [self database];
150 | block(db);
151 |
152 | if ([db hasOpenResultSets]) {
153 | NSLog(@"Warning: there is at least one open result set around after performing [FMDatabaseQueue inDatabase:]");
154 |
155 | #if defined(DEBUG) && DEBUG
156 | NSSet *openSetCopy = FMDBReturnAutoreleased([[db valueForKey:@"_openResultSets"] copy]);
157 | for (NSValue *rsInWrappedInATastyValueMeal in openSetCopy) {
158 | FMResultSet *rs = (FMResultSet *)[rsInWrappedInATastyValueMeal pointerValue];
159 | NSLog(@"query: '%@'", [rs query]);
160 | }
161 | #endif
162 | }
163 | });
164 |
165 | FMDBRelease(self);
166 | }
167 |
168 |
169 | - (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block {
170 | FMDBRetain(self);
171 | dispatch_sync(_queue, ^() {
172 |
173 | BOOL shouldRollback = NO;
174 |
175 | if (useDeferred) {
176 | [[self database] beginDeferredTransaction];
177 | }
178 | else {
179 | [[self database] beginTransaction];
180 | }
181 |
182 | block([self database], &shouldRollback);
183 |
184 | if (shouldRollback) {
185 | [[self database] rollback];
186 | }
187 | else {
188 | [[self database] commit];
189 | }
190 | });
191 |
192 | FMDBRelease(self);
193 | }
194 |
195 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
196 | [self beginTransaction:YES withBlock:block];
197 | }
198 |
199 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
200 | [self beginTransaction:NO withBlock:block];
201 | }
202 |
203 | #if SQLITE_VERSION_NUMBER >= 3007000
204 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block {
205 |
206 | static unsigned long savePointIdx = 0;
207 | __block NSError *err = 0x00;
208 | FMDBRetain(self);
209 | dispatch_sync(_queue, ^() {
210 |
211 | NSString *name = [NSString stringWithFormat:@"savePoint%ld", savePointIdx++];
212 |
213 | BOOL shouldRollback = NO;
214 |
215 | if ([[self database] startSavePointWithName:name error:&err]) {
216 |
217 | block([self database], &shouldRollback);
218 |
219 | if (shouldRollback) {
220 | // We need to rollback and release this savepoint to remove it
221 | [[self database] rollbackToSavePointWithName:name error:&err];
222 | }
223 | [[self database] releaseSavePointWithName:name error:&err];
224 |
225 | }
226 | });
227 | FMDBRelease(self);
228 | return err;
229 | }
230 | #endif
231 |
232 | @end
233 |
--------------------------------------------------------------------------------
/TextUtil/OpenSources/FMDB/FMDatabaseAdditions.m:
--------------------------------------------------------------------------------
1 | //
2 | // FMDatabaseAdditions.m
3 | // fmdb
4 | //
5 | // Created by August Mueller on 10/30/05.
6 | // Copyright 2005 Flying Meat Inc.. All rights reserved.
7 | //
8 |
9 | #import "FMDatabase.h"
10 | #import "FMDatabaseAdditions.h"
11 | #import "TargetConditionals.h"
12 |
13 | @interface FMDatabase (PrivateStuff)
14 | - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args;
15 | @end
16 |
17 | @implementation FMDatabase (FMDatabaseAdditions)
18 |
19 | #define RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(type, sel) \
20 | va_list args; \
21 | va_start(args, query); \
22 | FMResultSet *resultSet = [self executeQuery:query withArgumentsInArray:0x00 orDictionary:0x00 orVAList:args]; \
23 | va_end(args); \
24 | if (![resultSet next]) { return (type)0; } \
25 | type ret = [resultSet sel:0]; \
26 | [resultSet close]; \
27 | [resultSet setParentDB:nil]; \
28 | return ret;
29 |
30 |
31 | - (NSString*)stringForQuery:(NSString*)query, ... {
32 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSString *, stringForColumnIndex);
33 | }
34 |
35 | - (int)intForQuery:(NSString*)query, ... {
36 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(int, intForColumnIndex);
37 | }
38 |
39 | - (long)longForQuery:(NSString*)query, ... {
40 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(long, longForColumnIndex);
41 | }
42 |
43 | - (BOOL)boolForQuery:(NSString*)query, ... {
44 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(BOOL, boolForColumnIndex);
45 | }
46 |
47 | - (double)doubleForQuery:(NSString*)query, ... {
48 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(double, doubleForColumnIndex);
49 | }
50 |
51 | - (NSData*)dataForQuery:(NSString*)query, ... {
52 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSData *, dataForColumnIndex);
53 | }
54 |
55 | - (NSDate*)dateForQuery:(NSString*)query, ... {
56 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSDate *, dateForColumnIndex);
57 | }
58 |
59 |
60 | - (BOOL)tableExists:(NSString*)tableName {
61 |
62 | tableName = [tableName lowercaseString];
63 |
64 | FMResultSet *rs = [self executeQuery:@"select [sql] from sqlite_master where [type] = 'table' and lower(name) = ?", tableName];
65 |
66 | //if at least one next exists, table exists
67 | BOOL returnBool = [rs next];
68 |
69 | //close and free object
70 | [rs close];
71 |
72 | return returnBool;
73 | }
74 |
75 | /*
76 | get table with list of tables: result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING]
77 | check if table exist in database (patch from OZLB)
78 | */
79 | - (FMResultSet*)getSchema {
80 |
81 | //result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING]
82 | FMResultSet *rs = [self executeQuery:@"SELECT type, name, tbl_name, rootpage, sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type != 'meta' AND name NOT LIKE 'sqlite_%' ORDER BY tbl_name, type DESC, name"];
83 |
84 | return rs;
85 | }
86 |
87 | /*
88 | get table schema: result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER]
89 | */
90 | - (FMResultSet*)getTableSchema:(NSString*)tableName {
91 |
92 | //result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER]
93 | FMResultSet *rs = [self executeQuery:[NSString stringWithFormat: @"pragma table_info('%@')", tableName]];
94 |
95 | return rs;
96 | }
97 |
98 | - (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName {
99 |
100 | BOOL returnBool = NO;
101 |
102 | tableName = [tableName lowercaseString];
103 | columnName = [columnName lowercaseString];
104 |
105 | FMResultSet *rs = [self getTableSchema:tableName];
106 |
107 | //check if column is present in table schema
108 | while ([rs next]) {
109 | if ([[[rs stringForColumn:@"name"] lowercaseString] isEqualToString:columnName]) {
110 | returnBool = YES;
111 | break;
112 | }
113 | }
114 |
115 | //If this is not done FMDatabase instance stays out of pool
116 | [rs close];
117 |
118 | return returnBool;
119 | }
120 |
121 |
122 | #if SQLITE_VERSION_NUMBER >= 3007017
123 |
124 | - (uint32_t)applicationID {
125 |
126 | uint32_t r = 0;
127 |
128 | FMResultSet *rs = [self executeQuery:@"pragma application_id"];
129 |
130 | if ([rs next]) {
131 | r = (uint32_t)[rs longLongIntForColumnIndex:0];
132 | }
133 |
134 | [rs close];
135 |
136 | return r;
137 | }
138 |
139 | - (void)setApplicationID:(uint32_t)appID {
140 | NSString *query = [NSString stringWithFormat:@"pragma application_id=%d", appID];
141 | FMResultSet *rs = [self executeQuery:query];
142 | [rs next];
143 | [rs close];
144 | }
145 |
146 |
147 | #if TARGET_OS_MAC && !TARGET_OS_IPHONE
148 | - (NSString*)applicationIDString {
149 | NSString *s = NSFileTypeForHFSTypeCode([self applicationID]);
150 |
151 | assert([s length] == 6);
152 |
153 | s = [s substringWithRange:NSMakeRange(1, 4)];
154 |
155 |
156 | return s;
157 |
158 | }
159 |
160 | - (void)setApplicationIDString:(NSString*)s {
161 |
162 | if ([s length] != 4) {
163 | NSLog(@"setApplicationIDString: string passed is not exactly 4 chars long. (was %ld)", [s length]);
164 | }
165 |
166 | [self setApplicationID:NSHFSTypeCodeFromFileType([NSString stringWithFormat:@"'%@'", s])];
167 | }
168 |
169 |
170 | #endif
171 |
172 | #endif
173 |
174 | - (uint32_t)userVersion {
175 | uint32_t r = 0;
176 |
177 | FMResultSet *rs = [self executeQuery:@"pragma user_version"];
178 |
179 | if ([rs next]) {
180 | r = (uint32_t)[rs longLongIntForColumnIndex:0];
181 | }
182 |
183 | [rs close];
184 | return r;
185 | }
186 |
187 | - (void)setUserVersion:(uint32_t)version {
188 | NSString *query = [NSString stringWithFormat:@"pragma user_version = %d", version];
189 | FMResultSet *rs = [self executeQuery:query];
190 | [rs next];
191 | [rs close];
192 | }
193 |
194 | #pragma clang diagnostic push
195 | #pragma clang diagnostic ignored "-Wdeprecated-implementations"
196 |
197 | - (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __attribute__ ((deprecated)) {
198 | return [self columnExists:columnName inTableWithName:tableName];
199 | }
200 |
201 | #pragma clang diagnostic pop
202 |
203 |
204 | - (BOOL)validateSQL:(NSString*)sql error:(NSError**)error {
205 | sqlite3_stmt *pStmt = NULL;
206 | BOOL validationSucceeded = YES;
207 |
208 | int rc = sqlite3_prepare_v2(_db, [sql UTF8String], -1, &pStmt, 0);
209 | if (rc != SQLITE_OK) {
210 | validationSucceeded = NO;
211 | if (error) {
212 | *error = [NSError errorWithDomain:NSCocoaErrorDomain
213 | code:[self lastErrorCode]
214 | userInfo:[NSDictionary dictionaryWithObject:[self lastErrorMessage]
215 | forKey:NSLocalizedDescriptionKey]];
216 | }
217 | }
218 |
219 | sqlite3_finalize(pStmt);
220 |
221 | return validationSucceeded;
222 | }
223 |
224 | @end
225 |
--------------------------------------------------------------------------------
/TextUtil/OpenSources/FMDB/FMDatabasePool.m:
--------------------------------------------------------------------------------
1 | //
2 | // FMDatabasePool.m
3 | // fmdb
4 | //
5 | // Created by August Mueller on 6/22/11.
6 | // Copyright 2011 Flying Meat Inc. All rights reserved.
7 | //
8 |
9 | #import "FMDatabasePool.h"
10 | #import "FMDatabase.h"
11 |
12 | @interface FMDatabasePool()
13 |
14 | - (void)pushDatabaseBackInPool:(FMDatabase*)db;
15 | - (FMDatabase*)db;
16 |
17 | @end
18 |
19 |
20 | @implementation FMDatabasePool
21 | @synthesize path=_path;
22 | @synthesize delegate=_delegate;
23 | @synthesize maximumNumberOfDatabasesToCreate=_maximumNumberOfDatabasesToCreate;
24 | @synthesize openFlags=_openFlags;
25 |
26 |
27 | + (instancetype)databasePoolWithPath:(NSString*)aPath {
28 | return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath]);
29 | }
30 |
31 | + (instancetype)databasePoolWithPath:(NSString*)aPath flags:(int)openFlags {
32 | return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath flags:openFlags]);
33 | }
34 |
35 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags {
36 |
37 | self = [super init];
38 |
39 | if (self != nil) {
40 | _path = [aPath copy];
41 | _lockQueue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL);
42 | _databaseInPool = FMDBReturnRetained([NSMutableArray array]);
43 | _databaseOutPool = FMDBReturnRetained([NSMutableArray array]);
44 | _openFlags = openFlags;
45 | }
46 |
47 | return self;
48 | }
49 |
50 | - (instancetype)initWithPath:(NSString*)aPath
51 | {
52 | // default flags for sqlite3_open
53 | return [self initWithPath:aPath flags:SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE];
54 | }
55 |
56 | - (instancetype)init {
57 | return [self initWithPath:nil];
58 | }
59 |
60 |
61 | - (void)dealloc {
62 |
63 | _delegate = 0x00;
64 | FMDBRelease(_path);
65 | FMDBRelease(_databaseInPool);
66 | FMDBRelease(_databaseOutPool);
67 |
68 | if (_lockQueue) {
69 | FMDBDispatchQueueRelease(_lockQueue);
70 | _lockQueue = 0x00;
71 | }
72 | #if ! __has_feature(objc_arc)
73 | [super dealloc];
74 | #endif
75 | }
76 |
77 |
78 | - (void)executeLocked:(void (^)(void))aBlock {
79 | dispatch_sync(_lockQueue, aBlock);
80 | }
81 |
82 | - (void)pushDatabaseBackInPool:(FMDatabase*)db {
83 |
84 | if (!db) { // db can be null if we set an upper bound on the # of databases to create.
85 | return;
86 | }
87 |
88 | [self executeLocked:^() {
89 |
90 | if ([self->_databaseInPool containsObject:db]) {
91 | [[NSException exceptionWithName:@"Database already in pool" reason:@"The FMDatabase being put back into the pool is already present in the pool" userInfo:nil] raise];
92 | }
93 |
94 | [self->_databaseInPool addObject:db];
95 | [self->_databaseOutPool removeObject:db];
96 |
97 | }];
98 | }
99 |
100 | - (FMDatabase*)db {
101 |
102 | __block FMDatabase *db;
103 |
104 |
105 | [self executeLocked:^() {
106 | db = [self->_databaseInPool lastObject];
107 |
108 | BOOL shouldNotifyDelegate = NO;
109 |
110 | if (db) {
111 | [self->_databaseOutPool addObject:db];
112 | [self->_databaseInPool removeLastObject];
113 | }
114 | else {
115 |
116 | if (self->_maximumNumberOfDatabasesToCreate) {
117 | NSUInteger currentCount = [self->_databaseOutPool count] + [self->_databaseInPool count];
118 |
119 | if (currentCount >= self->_maximumNumberOfDatabasesToCreate) {
120 | NSLog(@"Maximum number of databases (%ld) has already been reached!", (long)currentCount);
121 | return;
122 | }
123 | }
124 |
125 | db = [FMDatabase databaseWithPath:self->_path];
126 | shouldNotifyDelegate = YES;
127 | }
128 |
129 | //This ensures that the db is opened before returning
130 | #if SQLITE_VERSION_NUMBER >= 3005000
131 | BOOL success = [db openWithFlags:self->_openFlags];
132 | #else
133 | BOOL success = [db open];
134 | #endif
135 | if (success) {
136 | if ([self->_delegate respondsToSelector:@selector(databasePool:shouldAddDatabaseToPool:)] && ![self->_delegate databasePool:self shouldAddDatabaseToPool:db]) {
137 | [db close];
138 | db = 0x00;
139 | }
140 | else {
141 | //It should not get added in the pool twice if lastObject was found
142 | if (![self->_databaseOutPool containsObject:db]) {
143 | [self->_databaseOutPool addObject:db];
144 |
145 | if (shouldNotifyDelegate && [self->_delegate respondsToSelector:@selector(databasePool:didAddDatabase:)]) {
146 | [self->_delegate databasePool:self didAddDatabase:db];
147 | }
148 | }
149 | }
150 | }
151 | else {
152 | NSLog(@"Could not open up the database at path %@", self->_path);
153 | db = 0x00;
154 | }
155 | }];
156 |
157 | return db;
158 | }
159 |
160 | - (NSUInteger)countOfCheckedInDatabases {
161 |
162 | __block NSUInteger count;
163 |
164 | [self executeLocked:^() {
165 | count = [self->_databaseInPool count];
166 | }];
167 |
168 | return count;
169 | }
170 |
171 | - (NSUInteger)countOfCheckedOutDatabases {
172 |
173 | __block NSUInteger count;
174 |
175 | [self executeLocked:^() {
176 | count = [self->_databaseOutPool count];
177 | }];
178 |
179 | return count;
180 | }
181 |
182 | - (NSUInteger)countOfOpenDatabases {
183 | __block NSUInteger count;
184 |
185 | [self executeLocked:^() {
186 | count = [self->_databaseOutPool count] + [self->_databaseInPool count];
187 | }];
188 |
189 | return count;
190 | }
191 |
192 | - (void)releaseAllDatabases {
193 | [self executeLocked:^() {
194 | [self->_databaseOutPool removeAllObjects];
195 | [self->_databaseInPool removeAllObjects];
196 | }];
197 | }
198 |
199 | - (void)inDatabase:(void (^)(FMDatabase *db))block {
200 |
201 | FMDatabase *db = [self db];
202 |
203 | block(db);
204 |
205 | [self pushDatabaseBackInPool:db];
206 | }
207 |
208 | - (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block {
209 |
210 | BOOL shouldRollback = NO;
211 |
212 | FMDatabase *db = [self db];
213 |
214 | if (useDeferred) {
215 | [db beginDeferredTransaction];
216 | }
217 | else {
218 | [db beginTransaction];
219 | }
220 |
221 |
222 | block(db, &shouldRollback);
223 |
224 | if (shouldRollback) {
225 | [db rollback];
226 | }
227 | else {
228 | [db commit];
229 | }
230 |
231 | [self pushDatabaseBackInPool:db];
232 | }
233 |
234 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
235 | [self beginTransaction:YES withBlock:block];
236 | }
237 |
238 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
239 | [self beginTransaction:NO withBlock:block];
240 | }
241 | #if SQLITE_VERSION_NUMBER >= 3007000
242 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block {
243 |
244 | static unsigned long savePointIdx = 0;
245 |
246 | NSString *name = [NSString stringWithFormat:@"savePoint%ld", savePointIdx++];
247 |
248 | BOOL shouldRollback = NO;
249 |
250 | FMDatabase *db = [self db];
251 |
252 | NSError *err = 0x00;
253 |
254 | if (![db startSavePointWithName:name error:&err]) {
255 | [self pushDatabaseBackInPool:db];
256 | return err;
257 | }
258 |
259 | block(db, &shouldRollback);
260 |
261 | if (shouldRollback) {
262 | // We need to rollback and release this savepoint to remove it
263 | [db rollbackToSavePointWithName:name error:&err];
264 | }
265 | [db releaseSavePointWithName:name error:&err];
266 |
267 | [self pushDatabaseBackInPool:db];
268 |
269 | return err;
270 | }
271 | #endif
272 |
273 | @end
274 |
--------------------------------------------------------------------------------
/TextUtil/Utils/Utility.m:
--------------------------------------------------------------------------------
1 | //
2 | // Utility.m
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/20.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import "Utility.h"
10 |
11 | @implementation Utility
12 |
13 | + (NSMutableAttributedString *)emotionStrWithString:(NSString *)text
14 | {
15 | NSString *filePath = [[NSBundle mainBundle] pathForResource:@"emoticons" ofType:@"plist"];
16 | NSArray *face = [NSArray arrayWithContentsOfFile:filePath];
17 | //1、创建一个可变的属性字符串
18 | NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:text];
19 | //2、通过正则表达式来匹配字符串
20 | NSString *regex_emoji = @"\\[[a-zA-Z0-9\\/\\u4e00-\\u9fa5]+\\]"; //匹配表情
21 |
22 | NSError *error = nil;
23 | NSRegularExpression *re = [NSRegularExpression regularExpressionWithPattern:regex_emoji options:NSRegularExpressionCaseInsensitive error:&error];
24 | if (!re) {
25 | NSLog(@"%@", [error localizedDescription]);
26 | return attributeString;
27 | }
28 |
29 | NSArray *resultArray = [re matchesInString:text options:0 range:NSMakeRange(0, text.length)];
30 | //3、获取所有的表情以及位置
31 | //用来存放字典,字典中存储的是图片和图片对应的位置
32 | NSMutableArray *imageArray = [NSMutableArray arrayWithCapacity:resultArray.count];
33 | //根据匹配范围来用图片进行相应的替换
34 | for(NSTextCheckingResult *match in resultArray) {
35 | //获取数组元素中得到range
36 | NSRange range = [match range];
37 | //获取原字符串中对应的值
38 | NSString *subStr = [text substringWithRange:range];
39 | for (int i = 0; i < face.count; i ++) {
40 | if ([face[i][@"cht"] isEqualToString:subStr]) {
41 | //face[i][@"png"]就是我们要加载的图片
42 | //新建文字附件来存放我们的图片,iOS7才新加的对象
43 | NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];
44 | //给附件添加图片
45 | textAttachment.image = [UIImage imageNamed:face[i][@"png"]];
46 | //调整一下图片的位置,如果你的图片偏上或者偏下,调整一下bounds的y值即可
47 | textAttachment.bounds = CGRectMake(0, -8, textAttachment.image.size.width, textAttachment.image.size.height);
48 | //把附件转换成可变字符串,用于替换掉源字符串中的表情文字
49 | NSAttributedString *imageStr = [NSAttributedString attributedStringWithAttachment:textAttachment];
50 | //把图片和图片对应的位置存入字典中
51 | NSMutableDictionary *imageDic = [NSMutableDictionary dictionaryWithCapacity:2];
52 | [imageDic setObject:imageStr forKey:@"image"];
53 | [imageDic setObject:[NSValue valueWithRange:range] forKey:@"range"];
54 | //把字典存入数组中
55 | [imageArray addObject:imageDic];
56 | }
57 | }
58 | }
59 |
60 | //4、从后往前替换,否则会引起位置问题
61 | for (int i = (int)imageArray.count -1; i >= 0; i--) {
62 | NSRange range;
63 | [imageArray[i][@"range"] getValue:&range];
64 | //进行替换
65 | [attributeString replaceCharactersInRange:range withAttributedString:imageArray[i][@"image"]];
66 | }
67 | return attributeString;
68 | }
69 |
70 | /**
71 | * 将带有表情符的文字转换为图文混排的文字
72 | *
73 | * @param text 带表情符的文字
74 | * @param plistName 表情符与表情对应的plist文件
75 | * @param y 图片的y偏移值
76 | *
77 | * @return 转换后的文字
78 | */
79 | + (NSMutableAttributedString *)emotionStrWithString:(NSString *)text plistName:(NSString *)plistName y:(CGFloat)y
80 | {
81 | NSString *filePath = [[NSBundle mainBundle] pathForResource:plistName ofType:nil];
82 | NSArray *face = [NSArray arrayWithContentsOfFile:filePath];
83 | //1、创建一个可变的属性字符串
84 | NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:text];
85 | //2、通过正则表达式来匹配字符串
86 | NSString *regex_emoji = @"\\[[a-zA-Z0-9\\/\\u4e00-\\u9fa5]+\\]"; //匹配表情
87 |
88 | NSError *error = nil;
89 | NSRegularExpression *re = [NSRegularExpression regularExpressionWithPattern:regex_emoji options:NSRegularExpressionCaseInsensitive error:&error];
90 | if (!re) {
91 | NSLog(@"%@", [error localizedDescription]);
92 | return attributeString;
93 | }
94 |
95 | NSArray *resultArray = [re matchesInString:text options:0 range:NSMakeRange(0, text.length)];
96 | //3、获取所有的表情以及位置
97 | //用来存放字典,字典中存储的是图片和图片对应的位置
98 | NSMutableArray *imageArray = [NSMutableArray arrayWithCapacity:resultArray.count];
99 | //根据匹配范围来用图片进行相应的替换
100 | for(NSTextCheckingResult *match in resultArray) {
101 | //获取数组元素中得到range
102 | NSRange range = [match range];
103 | //获取原字符串中对应的值
104 | NSString *subStr = [text substringWithRange:range];
105 | for (int i = 0; i < face.count; i ++) {
106 | if ([face[i][@"cht"] isEqualToString:subStr]) {
107 | //face[i][@"png"]就是我们要加载的图片
108 | //新建文字附件来存放我们的图片,iOS7才新加的对象
109 | NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];
110 | //给附件添加图片
111 | textAttachment.image = [UIImage imageNamed:face[i][@"png"]];
112 | //调整一下图片的位置,如果你的图片偏上或者偏下,调整一下bounds的y值即可
113 | textAttachment.bounds = CGRectMake(0, y, textAttachment.image.size.width, textAttachment.image.size.height);
114 | //把附件转换成可变字符串,用于替换掉源字符串中的表情文字
115 | NSAttributedString *imageStr = [NSAttributedString attributedStringWithAttachment:textAttachment];
116 | //把图片和图片对应的位置存入字典中
117 | NSMutableDictionary *imageDic = [NSMutableDictionary dictionaryWithCapacity:2];
118 | [imageDic setObject:imageStr forKey:@"image"];
119 | [imageDic setObject:[NSValue valueWithRange:range] forKey:@"range"];
120 | //把字典存入数组中
121 | [imageArray addObject:imageDic];
122 | }
123 | }
124 | }
125 |
126 | //4、从后往前替换,否则会引起位置问题
127 | for (int i = (int)imageArray.count -1; i >= 0; i--) {
128 | NSRange range;
129 | [imageArray[i][@"range"] getValue:&range];
130 | //进行替换
131 | [attributeString replaceCharactersInRange:range withAttributedString:imageArray[i][@"image"]];
132 | }
133 | return attributeString;
134 | }
135 |
136 | + (NSMutableAttributedString *)exchangeString:(NSString *)string withText:(NSString *)text imageName:(NSString *)imageName
137 | {
138 | //1、创建一个可变的属性字符串
139 | NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:text];
140 |
141 | //2、匹配字符串
142 | NSError *error = nil;
143 | NSRegularExpression *re = [NSRegularExpression regularExpressionWithPattern:string options:NSRegularExpressionCaseInsensitive error:&error];
144 | if (!re) {
145 | NSLog(@"%@", [error localizedDescription]);
146 | return attributeString;
147 | }
148 |
149 | NSArray *resultArray = [re matchesInString:text options:0 range:NSMakeRange(0, text.length)];
150 | //3、获取所有的图片以及位置
151 | //用来存放字典,字典中存储的是图片和图片对应的位置
152 | NSMutableArray *imageArray = [NSMutableArray arrayWithCapacity:resultArray.count];
153 | //根据匹配范围来用图片进行相应的替换
154 | for(NSTextCheckingResult *match in resultArray) {
155 | //获取数组元素中得到range
156 | NSRange range = [match range];
157 | //新建文字附件来存放我们的图片(iOS7才新加的对象)
158 | NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];
159 | //给附件添加图片
160 | textAttachment.image = [UIImage imageNamed:imageName];
161 | //修改一下图片的位置,y为负值,表示向下移动
162 | textAttachment.bounds = CGRectMake(0, -2, textAttachment.image.size.width, textAttachment.image.size.height);
163 | //把附件转换成可变字符串,用于替换掉源字符串中的表情文字
164 | NSAttributedString *imageStr = [NSAttributedString attributedStringWithAttachment:textAttachment];
165 | //把图片和图片对应的位置存入字典中
166 | NSMutableDictionary *imageDic = [NSMutableDictionary dictionaryWithCapacity:2];
167 | [imageDic setObject:imageStr forKey:@"image"];
168 | [imageDic setObject:[NSValue valueWithRange:range] forKey:@"range"];
169 | //把字典存入数组中
170 | [imageArray addObject:imageDic];
171 | }
172 |
173 | //4、从后往前替换,否则会引起位置问题
174 | for (int i = (int)imageArray.count -1; i >= 0; i--) {
175 | NSRange range;
176 | [imageArray[i][@"range"] getValue:&range];
177 | //进行替换
178 | [attributeString replaceCharactersInRange:range withAttributedString:imageArray[i][@"image"]];
179 | }
180 |
181 | return attributeString;
182 | }
183 |
184 | @end
185 |
--------------------------------------------------------------------------------
/TextUtil/Discover/Views/DynamicView.m:
--------------------------------------------------------------------------------
1 | //
2 | // DynamicView.m
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/19.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import "DynamicView.h"
10 | #import "Utility.h"
11 |
12 | @interface DynamicView ()
13 |
14 | /** 正文的文字 */
15 | @property (nonatomic, retain) UILabel *contentLabel;
16 | /** 图片视图数组 */
17 | @property (nonatomic, retain) NSMutableArray *imageViews;
18 |
19 | @property (nonatomic, retain) UIButton *videoBtn;
20 |
21 | @end
22 |
23 | @implementation DynamicView
24 |
25 | - (instancetype)initWithFrame:(CGRect)frame
26 | {
27 | self = [super initWithFrame:frame];
28 | if (self) {
29 | [self initSubViews];
30 | }
31 | return self;
32 | }
33 |
34 | /** 初始化子控件 */
35 | - (void)initSubViews
36 | {
37 | //添加正文
38 | _contentLabel = [[UILabel alloc] initWithFrame:CGRectZero];
39 | _contentLabel.font = kContentFont;
40 | _contentLabel.textColor = [UIColor blackColor];
41 | _contentLabel.numberOfLines = 0;
42 | [self addSubview:_contentLabel];
43 |
44 | _imageViews = [[NSMutableArray alloc] initWithCapacity:10];
45 | for (int i = 0; i < 9; i++) {
46 | UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectZero];
47 | imageView.contentMode = UIViewContentModeScaleAspectFill;
48 | imageView.clipsToBounds = YES;
49 | imageView.tag = 2015 + i;
50 | [self addSubview:imageView];
51 | [_imageViews addObject:imageView];
52 | }
53 |
54 | _videoBtn = [[UIButton alloc] initWithFrame:CGRectZero];
55 | [_videoBtn setImage:[UIImage imageNamed:@"chatgroup_video_play_btbg"] forState:UIControlStateNormal];
56 | // [_videoBtn addTarget:self action:@selector(videoClick:) forControlEvents:UIControlEventTouchUpInside];
57 |
58 | [self addSubview:_videoBtn];
59 | }
60 |
61 | - (void)setDynamic:(Dynamic *)dynamic
62 | {
63 | if (_dynamic != dynamic) {
64 | _dynamic = dynamic;
65 | }
66 |
67 | _contentLabel.hidden = YES;
68 | for (UIImageView *imageView in _imageViews) {
69 | imageView.hidden = YES;
70 | }
71 | _videoBtn.hidden = YES;
72 |
73 | if (_dynamic.type == 0) { //纯文字
74 | NSMutableAttributedString *content = [Utility emotionStrWithString:_dynamic.text];
75 | [content addAttribute:NSFontAttributeName value:kContentFont range:NSMakeRange(0, content.length)];
76 | CGSize maxSize = CGSizeMake(kDynamicWidth, MAXFLOAT);
77 | CGSize attrStrSize = [content boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin context:nil].size;
78 | _contentLabel.frame = CGRectMake(0, 0, attrStrSize.width, attrStrSize.height);
79 | _contentLabel.attributedText = content;
80 | _contentLabel.hidden = NO;
81 | } else if (_dynamic.type == 1) { //带图片
82 | CGFloat contentHeight = 0;
83 | if (_dynamic.text.length <= 0) {//不存在文字,肯定是纯图片
84 | _contentLabel.frame = CGRectZero;
85 | _contentLabel.hidden = YES;
86 | } else { //文字+图片
87 | NSMutableAttributedString *content = [Utility emotionStrWithString:_dynamic.text];
88 | [content addAttribute:NSFontAttributeName value:kContentFont range:NSMakeRange(0, content.length)];
89 | CGSize maxSize = CGSizeMake(kDynamicWidth, MAXFLOAT);
90 | CGSize attrStrSize = [content boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin context:nil].size;
91 | _contentLabel.frame = CGRectMake(0, 0, attrStrSize.width, attrStrSize.height);
92 | _contentLabel.attributedText = content;
93 | _contentLabel.hidden = NO;
94 | contentHeight = attrStrSize.height+10;
95 | }
96 |
97 | for (int i = 0; i < _dynamic.imageCount; i++) {
98 | if (i > 8) {
99 | break;
100 | }
101 | int rowNum = i/3;
102 | int colNum = i%3;
103 | CGFloat imageX = colNum*(kImageWidth+kImagePadding);
104 | CGFloat imageY = contentHeight + rowNum*(kImageWidth+kImagePadding);
105 | CGRect frame = CGRectMake(imageX,imageY, kImageWidth, kImageWidth);
106 | if (_dynamic.imageCount == 1) {
107 | frame = CGRectMake(0, contentHeight, kSingleImageWidth, kSingleImageWidth-40);
108 | }
109 | UIImageView *imageView = [_imageViews objectAtIndex:i];
110 | imageView.hidden = NO;
111 | imageView.frame = frame;
112 | NSString *imageName = [NSString stringWithFormat:@"image_0%d.jpg",i+1];
113 | imageView.image = [UIImage imageNamed:imageName];
114 | }
115 |
116 | } else if (_dynamic.type == 2) { //小视频
117 | CGFloat contentHeight = 0;
118 | if (_dynamic.text.length <= 0) {//不存在文字,肯定是纯图片
119 | _contentLabel.frame = CGRectZero;
120 | _contentLabel.hidden = YES;
121 | } else { //文字+图片
122 | NSMutableAttributedString *content = [Utility emotionStrWithString:_dynamic.text];
123 | [content addAttribute:NSFontAttributeName value:kContentFont range:NSMakeRange(0, content.length)];
124 | CGSize maxSize = CGSizeMake(kDynamicWidth, MAXFLOAT);
125 | CGSize attrStrSize = [content boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin context:nil].size;
126 | _contentLabel.frame = CGRectMake(0, 0, attrStrSize.width, attrStrSize.height);
127 | _contentLabel.attributedText = content;
128 | _contentLabel.hidden = NO;
129 | contentHeight = attrStrSize.height+10;
130 | }
131 |
132 | _videoBtn.hidden = NO;
133 | _videoBtn.frame = CGRectMake(0, contentHeight, kSingleImageWidth, kSingleImageWidth-40);
134 | [_videoBtn setBackgroundImage:[UIImage imageNamed:@"bb_default_picture_bg.png"] forState:UIControlStateNormal];
135 | }
136 | }
137 |
138 |
139 | + (CGFloat)getHeightWithModel:(Dynamic *)dynamic
140 | {
141 | if (dynamic.type == 0) { //纯文字
142 | NSMutableAttributedString *content = [Utility emotionStrWithString:dynamic.text];
143 | [content addAttribute:NSFontAttributeName value:kContentFont range:NSMakeRange(0, content.length)];
144 | CGSize maxSize = CGSizeMake(kDynamicWidth, MAXFLOAT);
145 | CGSize attrStrSize = [content boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin context:nil].size;
146 | return attrStrSize.height;
147 | } else if (dynamic.type == 1) { //附带图片
148 | CGFloat height = 0;
149 | if (dynamic.text.length > 0) {//文字
150 | NSMutableAttributedString *content = [Utility emotionStrWithString:dynamic.text];
151 | [content addAttribute:NSFontAttributeName value:kContentFont range:NSMakeRange(0, content.length)];
152 | CGSize maxSize = CGSizeMake(kDynamicWidth, MAXFLOAT);
153 | CGSize attrStrSize = [content boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin context:nil].size;
154 | height += attrStrSize.height;
155 | }
156 | int imageCount = dynamic.imageCount;
157 | if (imageCount == 0) {
158 |
159 | } else if (imageCount == 1) {
160 | height += kSingleImageWidth-40+10;
161 | } else if (imageCount < 4) {
162 | height += (kImageWidth+10);
163 | } else if (imageCount < 7) {
164 | height += (kImageWidth*2 + kImagePadding+10);
165 | } else {
166 | height += (kImageWidth*3 + kImagePadding*2+10);
167 | }
168 | return height;
169 | } else if (dynamic.type == 3){
170 | CGFloat height = 0;
171 | if (dynamic.text.length <= 0) {//不存在文字,肯定是纯视频
172 |
173 | } else { //文字+视频
174 | NSMutableAttributedString *content = [Utility emotionStrWithString:dynamic.text];
175 | [content addAttribute:NSFontAttributeName value:kContentFont range:NSMakeRange(0, content.length)];
176 | CGSize maxSize = CGSizeMake(kDynamicWidth, MAXFLOAT);
177 | CGSize attrStrSize = [content boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin context:nil].size;
178 | height += (attrStrSize.height+10);
179 | }
180 |
181 | height += (kSingleImageWidth-40);
182 | return height;
183 | }
184 |
185 | return 0;
186 | }
187 |
188 | @end
189 |
--------------------------------------------------------------------------------
/TextUtil/OpenSources/FMDB/FMDatabaseAdditions.h:
--------------------------------------------------------------------------------
1 | //
2 | // FMDatabaseAdditions.h
3 | // fmdb
4 | //
5 | // Created by August Mueller on 10/30/05.
6 | // Copyright 2005 Flying Meat Inc.. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "FMDatabase.h"
11 |
12 |
13 | /** Category of additions for `` class.
14 |
15 | ### See also
16 |
17 | - ``
18 | */
19 |
20 | @interface FMDatabase (FMDatabaseAdditions)
21 |
22 | ///----------------------------------------
23 | /// @name Return results of SQL to variable
24 | ///----------------------------------------
25 |
26 | /** Return `int` value for query
27 |
28 | @param query The SQL query to be performed.
29 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query.
30 |
31 | @return `int` value.
32 |
33 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
34 | */
35 |
36 | - (int)intForQuery:(NSString*)query, ...;
37 |
38 | /** Return `long` value for query
39 |
40 | @param query The SQL query to be performed.
41 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query.
42 |
43 | @return `long` value.
44 |
45 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
46 | */
47 |
48 | - (long)longForQuery:(NSString*)query, ...;
49 |
50 | /** Return `BOOL` value for query
51 |
52 | @param query The SQL query to be performed.
53 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query.
54 |
55 | @return `BOOL` value.
56 |
57 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
58 | */
59 |
60 | - (BOOL)boolForQuery:(NSString*)query, ...;
61 |
62 | /** Return `double` value for query
63 |
64 | @param query The SQL query to be performed.
65 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query.
66 |
67 | @return `double` value.
68 |
69 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
70 | */
71 |
72 | - (double)doubleForQuery:(NSString*)query, ...;
73 |
74 | /** Return `NSString` value for query
75 |
76 | @param query The SQL query to be performed.
77 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query.
78 |
79 | @return `NSString` value.
80 |
81 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
82 | */
83 |
84 | - (NSString*)stringForQuery:(NSString*)query, ...;
85 |
86 | /** Return `NSData` value for query
87 |
88 | @param query The SQL query to be performed.
89 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query.
90 |
91 | @return `NSData` value.
92 |
93 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
94 | */
95 |
96 | - (NSData*)dataForQuery:(NSString*)query, ...;
97 |
98 | /** Return `NSDate` value for query
99 |
100 | @param query The SQL query to be performed.
101 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query.
102 |
103 | @return `NSDate` value.
104 |
105 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
106 | */
107 |
108 | - (NSDate*)dateForQuery:(NSString*)query, ...;
109 |
110 |
111 | // Notice that there's no dataNoCopyForQuery:.
112 | // That would be a bad idea, because we close out the result set, and then what
113 | // happens to the data that we just didn't copy? Who knows, not I.
114 |
115 |
116 | ///--------------------------------
117 | /// @name Schema related operations
118 | ///--------------------------------
119 |
120 | /** Does table exist in database?
121 |
122 | @param tableName The name of the table being looked for.
123 |
124 | @return `YES` if table found; `NO` if not found.
125 | */
126 |
127 | - (BOOL)tableExists:(NSString*)tableName;
128 |
129 | /** The schema of the database.
130 |
131 | This will be the schema for the entire database. For each entity, each row of the result set will include the following fields:
132 |
133 | - `type` - The type of entity (e.g. table, index, view, or trigger)
134 | - `name` - The name of the object
135 | - `tbl_name` - The name of the table to which the object references
136 | - `rootpage` - The page number of the root b-tree page for tables and indices
137 | - `sql` - The SQL that created the entity
138 |
139 | @return `FMResultSet` of schema; `nil` on error.
140 |
141 | @see [SQLite File Format](http://www.sqlite.org/fileformat.html)
142 | */
143 |
144 | - (FMResultSet*)getSchema;
145 |
146 | /** The schema of the database.
147 |
148 | This will be the schema for a particular table as report by SQLite `PRAGMA`, for example:
149 |
150 | PRAGMA table_info('employees')
151 |
152 | This will report:
153 |
154 | - `cid` - The column ID number
155 | - `name` - The name of the column
156 | - `type` - The data type specified for the column
157 | - `notnull` - whether the field is defined as NOT NULL (i.e. values required)
158 | - `dflt_value` - The default value for the column
159 | - `pk` - Whether the field is part of the primary key of the table
160 |
161 | @param tableName The name of the table for whom the schema will be returned.
162 |
163 | @return `FMResultSet` of schema; `nil` on error.
164 |
165 | @see [table_info](http://www.sqlite.org/pragma.html#pragma_table_info)
166 | */
167 |
168 | - (FMResultSet*)getTableSchema:(NSString*)tableName;
169 |
170 | /** Test to see if particular column exists for particular table in database
171 |
172 | @param columnName The name of the column.
173 |
174 | @param tableName The name of the table.
175 |
176 | @return `YES` if column exists in table in question; `NO` otherwise.
177 | */
178 |
179 | - (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName;
180 |
181 | /** Test to see if particular column exists for particular table in database
182 |
183 | @param columnName The name of the column.
184 |
185 | @param tableName The name of the table.
186 |
187 | @return `YES` if column exists in table in question; `NO` otherwise.
188 |
189 | @see columnExists:inTableWithName:
190 |
191 | @warning Deprecated - use `` instead.
192 | */
193 |
194 | - (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __attribute__ ((deprecated));
195 |
196 |
197 | /** Validate SQL statement
198 |
199 | This validates SQL statement by performing `sqlite3_prepare_v2`, but not returning the results, but instead immediately calling `sqlite3_finalize`.
200 |
201 | @param sql The SQL statement being validated.
202 |
203 | @param error This is a pointer to a `NSError` object that will receive the autoreleased `NSError` object if there was any error. If this is `nil`, no `NSError` result will be returned.
204 |
205 | @return `YES` if validation succeeded without incident; `NO` otherwise.
206 |
207 | */
208 |
209 | - (BOOL)validateSQL:(NSString*)sql error:(NSError**)error;
210 |
211 |
212 | #if SQLITE_VERSION_NUMBER >= 3007017
213 |
214 | ///-----------------------------------
215 | /// @name Application identifier tasks
216 | ///-----------------------------------
217 |
218 | /** Retrieve application ID
219 |
220 | @return The `uint32_t` numeric value of the application ID.
221 |
222 | @see setApplicationID:
223 | */
224 |
225 | - (uint32_t)applicationID;
226 |
227 | /** Set the application ID
228 |
229 | @param appID The `uint32_t` numeric value of the application ID.
230 |
231 | @see applicationID
232 | */
233 |
234 | - (void)setApplicationID:(uint32_t)appID;
235 |
236 | #if TARGET_OS_MAC && !TARGET_OS_IPHONE
237 | /** Retrieve application ID string
238 |
239 | @return The `NSString` value of the application ID.
240 |
241 | @see setApplicationIDString:
242 | */
243 |
244 |
245 | - (NSString*)applicationIDString;
246 |
247 | /** Set the application ID string
248 |
249 | @param string The `NSString` value of the application ID.
250 |
251 | @see applicationIDString
252 | */
253 |
254 | - (void)setApplicationIDString:(NSString*)string;
255 | #endif
256 |
257 | #endif
258 |
259 | ///-----------------------------------
260 | /// @name user version identifier tasks
261 | ///-----------------------------------
262 |
263 | /** Retrieve user version
264 |
265 | @return The `uint32_t` numeric value of the user version.
266 |
267 | @see setUserVersion:
268 | */
269 |
270 | - (uint32_t)userVersion;
271 |
272 | /** Set the user-version
273 |
274 | @param version The `uint32_t` numeric value of the user version.
275 |
276 | @see userVersion
277 | */
278 |
279 | - (void)setUserVersion:(uint32_t)version;
280 |
281 | @end
282 |
--------------------------------------------------------------------------------
/TextUtil/Discover/Views/DynamicCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // DynamicCell.m
3 | // TextUtil
4 | //
5 | // Created by zx_04 on 15/8/19.
6 | // Copyright (c) 2015年 joker. All rights reserved.
7 | //
8 |
9 | #import "DynamicCell.h"
10 | #import "DynamicView.h"
11 |
12 | #import "Dynamic.h"
13 | #import "Utility.h"
14 |
15 | @interface DynamicCell ()
16 |
17 | @property (nonatomic, retain) UIImageView *faceImageView;
18 | @property (nonatomic, retain) UILabel *nameLabel;
19 | @property (nonatomic, retain) UILabel *locationLabel;
20 | /** 板报内容视图 */
21 | @property (nonatomic, retain) DynamicView *dynamicView;
22 | /** 操作视图 */
23 | @property (nonatomic, retain) UIView *optionView;
24 | /** 分隔线 */
25 | @property (nonatomic, retain) UIView *lineView;
26 | /** 点赞视图 */
27 | @property (nonatomic, retain) UILabel *praiseLabel;
28 |
29 | @end
30 |
31 | @implementation DynamicCell
32 |
33 | - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
34 | {
35 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
36 | if (self) {
37 | [self setUpSubViews];
38 | }
39 | return self;
40 | }
41 |
42 | - (void)setUpSubViews
43 | {
44 | //头像视图
45 | _faceImageView = [[UIImageView alloc] init];
46 | _faceImageView.layer.cornerRadius = kFaceWidth/2;
47 | _faceImageView.layer.masksToBounds = YES;
48 | _faceImageView.userInteractionEnabled = YES;
49 | UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(faceClick)];
50 | [_faceImageView addGestureRecognizer:tapGesture];
51 |
52 | [self.contentView addSubview:_faceImageView];
53 | //名字视图
54 | _nameLabel = [[UILabel alloc] init];
55 | _nameLabel.textColor = nameColor;
56 | [self.contentView addSubview:_nameLabel];
57 |
58 | //位置视图
59 | _locationLabel = [[UILabel alloc] init];
60 | _locationLabel.textColor = customGrayColor;
61 | _locationLabel.font = [UIFont systemFontOfSize:13.0f];
62 | [self.contentView addSubview:_locationLabel];
63 |
64 | //板报正文视图
65 | _dynamicView = [[DynamicView alloc] initWithFrame:CGRectZero];
66 | // _dynamicView.delegate = self;
67 | [self.contentView addSubview:_dynamicView];
68 |
69 | //操作控件视图
70 | [self initOptionView];
71 |
72 | //分隔线
73 | _lineView = [[UIView alloc] initWithFrame:CGRectZero];
74 | _lineView.backgroundColor = TABLEVIEW_BORDER_COLOR;
75 | [self.contentView addSubview:_lineView];
76 |
77 | //点赞人员视图
78 | _praiseLabel = [[UILabel alloc] init];
79 | _praiseLabel.textColor = customGrayColor;
80 | _praiseLabel.font = [UIFont systemFontOfSize:14.0f];
81 | _praiseLabel.numberOfLines = 0;
82 | [self.contentView addSubview:_praiseLabel];
83 | }
84 |
85 | /** 初始化操作控件视图 */
86 | - (void)initOptionView
87 | {
88 | _optionView = [[UIView alloc] initWithFrame:CGRectZero];
89 | [self.contentView addSubview:_optionView];
90 |
91 | CGFloat btnWidth = 70;
92 | //点赞按钮
93 | UIButton *praiseBtn = [[UIButton alloc] initWithFrame:CGRectMake(kWidth-65-btnWidth*3, 0, btnWidth, kOptionHeight)];
94 | praiseBtn.tag = 110;
95 | [praiseBtn setImage:[UIImage imageNamed:@"dynamic_love"] forState:UIControlStateNormal];
96 | praiseBtn.titleLabel.font =[UIFont systemFontOfSize:14.0];
97 | [praiseBtn setTitleColor:customGrayColor forState:UIControlStateNormal];
98 | [praiseBtn addTarget:self action:@selector(praiseClick:) forControlEvents:UIControlEventTouchUpInside];
99 | [_optionView addSubview:praiseBtn];
100 |
101 | UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMaxX(praiseBtn.frame), kPadding*0.75, 1, kOptionHeight-kPadding*1.5)];
102 | lineView.backgroundColor = [UIColor lightGrayColor];
103 | [_optionView addSubview:lineView];
104 |
105 | //评论按钮
106 | UIButton *cmdBtn = [[UIButton alloc] initWithFrame:CGRectMake(kWidth-65-btnWidth*2, 0, btnWidth, kOptionHeight)];
107 | cmdBtn.tag = 111;
108 | [cmdBtn setImage:[UIImage imageNamed:@"dynamic_comment"] forState:UIControlStateNormal];
109 | [cmdBtn setTitleColor:customGrayColor forState:UIControlStateNormal];
110 | [cmdBtn setTitle:@" 评论" forState:UIControlStateNormal];
111 | cmdBtn.titleLabel.font =[UIFont systemFontOfSize:14.0];
112 | // [cmdBtn addTarget:self action:@selector(cmtClick:) forControlEvents:UIControlEventTouchUpInside];
113 |
114 | [_optionView addSubview:cmdBtn];
115 |
116 | _lineView = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMaxX(cmdBtn.frame), kPadding*0.75, 1, kOptionHeight-kPadding*1.5)];
117 | _lineView.backgroundColor = [UIColor lightGrayColor];
118 | [_optionView addSubview:_lineView];
119 |
120 | //收藏按钮
121 | UIButton *collectBtn = [[UIButton alloc] initWithFrame:CGRectMake(kWidth-65-btnWidth, 0, btnWidth, kOptionHeight)];
122 | collectBtn.tag = 112;
123 | [collectBtn setImage:[UIImage imageNamed:@"dynamic_collect"] forState:UIControlStateNormal];
124 | [collectBtn setTitleColor:customGrayColor forState:UIControlStateNormal];
125 | [collectBtn setTitle:@" 收藏" forState:UIControlStateNormal];
126 | collectBtn.titleLabel.font =[UIFont systemFontOfSize:14.0];
127 | // [collectBtn addTarget:self action:@selector(collectClick:) forControlEvents:UIControlEventTouchUpInside];
128 | [_optionView addSubview:collectBtn];
129 |
130 | }
131 |
132 | - (void)faceClick
133 | {
134 | NSLog(@"%s",__func__);
135 | }
136 |
137 | - (void)praiseClick:(UIButton *)btn
138 | {
139 |
140 | }
141 |
142 | - (void)setDynamic:(Dynamic *)dynamic
143 | {
144 | if (_dynamic != dynamic) {
145 | _dynamic = dynamic;
146 | }
147 |
148 | _faceImageView.frame = CGRectMake(kPadding, kPadding, kFaceWidth, kFaceWidth);
149 | _faceImageView.image = [UIImage imageNamed:@"header_wechat"];
150 |
151 | _nameLabel.frame = CGRectMake(_faceImageView.right+kPadding, _faceImageView.top, kWidth-kFaceWidth-kPadding*3, 20);
152 | _nameLabel.text = @"路人甲";
153 | NSString *location = [NSString stringWithFormat:@"%@ | %@",_dynamic.location,_dynamic.createTime];
154 |
155 | _locationLabel.frame = CGRectMake(_nameLabel.left, _nameLabel.bottom+kPadding, _nameLabel.width, 15);
156 | _locationLabel.text = location;
157 |
158 | CGFloat height = [DynamicView getHeightWithModel:_dynamic];
159 | _dynamicView.frame = CGRectMake(_nameLabel.left, _faceImageView.bottom+kPadding, kDynamicWidth, height);
160 | _dynamicView.dynamic = _dynamic;
161 |
162 | _optionView.frame = CGRectMake(_nameLabel.left, _dynamicView.bottom+kPadding, kWidth-65, kOptionHeight);
163 | //赞
164 | UIButton *praiseBtn = (UIButton *)[_optionView viewWithTag:110];
165 | NSString *praiseCount = [NSString stringWithFormat:@" %d",_dynamic.praiseCount];
166 | [praiseBtn setTitle:praiseCount forState:UIControlStateNormal];
167 |
168 | // NSDictionary *attributes = @{NSFontAttributeName:[UIFont systemFontOfSize:14.0],NSForegroundColorAttributeName:nameColor};
169 | NSDictionary *attributes = @{NSFontAttributeName:[UIFont systemFontOfSize:14.0]};
170 | NSString *praiseStr = @"路人甲、路人乙";
171 | NSString *praiseInfo = [NSString stringWithFormat:@"<点赞> %@",praiseStr];
172 | NSDictionary *attributesForAll = @{NSFontAttributeName:[UIFont systemFontOfSize:14.0],NSForegroundColorAttributeName:[UIColor grayColor]};
173 | NSMutableAttributedString *attrStr = [Utility exchangeString:@"<点赞>" withText:praiseInfo imageName:@"dynamic_love_blue"]; //dynamic_love_blue
174 | [attrStr addAttributes:attributesForAll range:NSMakeRange(0, attrStr.length)];
175 | NSRange darkRange =[attrStr.string rangeOfString:praiseStr];
176 | [attrStr addAttributes:attributes range:darkRange];
177 |
178 | CGSize labelSize = [attrStr boundingRectWithSize:CGSizeMake(kWidth-65-kPadding, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin context:nil].size;
179 | _praiseLabel.attributedText = attrStr;
180 | _praiseLabel.frame = CGRectMake(_nameLabel.left, _optionView.bottom + kPadding, labelSize.width, labelSize.height);
181 |
182 | }
183 |
184 |
185 | #pragma mark - Class method
186 | + (instancetype)cellWithTableView:(UITableView *)tableView
187 | {
188 | static NSString *identifier = @"dynamicCell";
189 | DynamicCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
190 | if (cell == nil) {
191 | cell = [[DynamicCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
192 | cell.selectionStyle = UITableViewCellSelectionStyleNone;
193 | }
194 | return cell;
195 | }
196 |
197 | + (CGFloat)heightOfCellWithModel:(Dynamic *)dynamic
198 | {
199 | CGFloat height = 0;
200 | //头像高度
201 | height += (kPadding+kFaceWidth);
202 | //计算正文高度
203 | height += (kPadding +[DynamicView getHeightWithModel:dynamic]);
204 | //控件视图高度
205 | height += (kPadding+kOptionHeight);
206 | //点赞视图高度
207 | CGSize praiseSize = [self getHeightOfPraiseView:dynamic];
208 | height += (kPadding + praiseSize.height);
209 |
210 | height += kPadding+7;
211 |
212 | return height;
213 | }
214 |
215 | + (CGSize)getHeightOfPraiseView:(Dynamic *)dynamic
216 | {
217 | NSString *praiseStr = @"路人ABC";
218 | NSDictionary *attributes = @{NSFontAttributeName:[UIFont systemFontOfSize:14.0],NSForegroundColorAttributeName:nameColor};
219 |
220 | NSString *praiseInfo = [NSString stringWithFormat:@"<点赞> %@",praiseStr];
221 | NSDictionary *attributesForAll = @{NSFontAttributeName:[UIFont systemFontOfSize:14.0],NSForegroundColorAttributeName:[UIColor grayColor]};
222 | NSMutableAttributedString *attrStr = [Utility exchangeString:@"<点赞>" withText:praiseInfo imageName:@"dynamic_love_blue"];
223 | [attrStr addAttributes:attributesForAll range:NSMakeRange(0, attrStr.length)];
224 | NSRange darkRange =[attrStr.string rangeOfString:praiseStr];
225 | [attrStr addAttributes:attributes range:darkRange];
226 |
227 | CGSize labelSize = [attrStr boundingRectWithSize:CGSizeMake(kWidth-65-kPadding, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin context:nil].size;
228 | return labelSize;
229 | }
230 |
231 | @end
232 |
--------------------------------------------------------------------------------
/TextUtil/OpenSources/FMDB/FMResultSet.m:
--------------------------------------------------------------------------------
1 | #import "FMResultSet.h"
2 | #import "FMDatabase.h"
3 | #import "unistd.h"
4 |
5 | @interface FMDatabase ()
6 | - (void)resultSetDidClose:(FMResultSet *)resultSet;
7 | @end
8 |
9 |
10 | @implementation FMResultSet
11 | @synthesize query=_query;
12 | @synthesize statement=_statement;
13 |
14 | + (instancetype)resultSetWithStatement:(FMStatement *)statement usingParentDatabase:(FMDatabase*)aDB {
15 |
16 | FMResultSet *rs = [[FMResultSet alloc] init];
17 |
18 | [rs setStatement:statement];
19 | [rs setParentDB:aDB];
20 |
21 | NSParameterAssert(![statement inUse]);
22 | [statement setInUse:YES]; // weak reference
23 |
24 | return FMDBReturnAutoreleased(rs);
25 | }
26 |
27 | - (void)finalize {
28 | [self close];
29 | [super finalize];
30 | }
31 |
32 | - (void)dealloc {
33 | [self close];
34 |
35 | FMDBRelease(_query);
36 | _query = nil;
37 |
38 | FMDBRelease(_columnNameToIndexMap);
39 | _columnNameToIndexMap = nil;
40 |
41 | #if ! __has_feature(objc_arc)
42 | [super dealloc];
43 | #endif
44 | }
45 |
46 | - (void)close {
47 | [_statement reset];
48 | FMDBRelease(_statement);
49 | _statement = nil;
50 |
51 | // we don't need this anymore... (i think)
52 | //[_parentDB setInUse:NO];
53 | [_parentDB resultSetDidClose:self];
54 | _parentDB = nil;
55 | }
56 |
57 | - (int)columnCount {
58 | return sqlite3_column_count([_statement statement]);
59 | }
60 |
61 | - (NSMutableDictionary *)columnNameToIndexMap {
62 | if (!_columnNameToIndexMap) {
63 | int columnCount = sqlite3_column_count([_statement statement]);
64 | _columnNameToIndexMap = [[NSMutableDictionary alloc] initWithCapacity:(NSUInteger)columnCount];
65 | int columnIdx = 0;
66 | for (columnIdx = 0; columnIdx < columnCount; columnIdx++) {
67 | [_columnNameToIndexMap setObject:[NSNumber numberWithInt:columnIdx]
68 | forKey:[[NSString stringWithUTF8String:sqlite3_column_name([_statement statement], columnIdx)] lowercaseString]];
69 | }
70 | }
71 | return _columnNameToIndexMap;
72 | }
73 |
74 | - (void)kvcMagic:(id)object {
75 |
76 | int columnCount = sqlite3_column_count([_statement statement]);
77 |
78 | int columnIdx = 0;
79 | for (columnIdx = 0; columnIdx < columnCount; columnIdx++) {
80 |
81 | const char *c = (const char *)sqlite3_column_text([_statement statement], columnIdx);
82 |
83 | // check for a null row
84 | if (c) {
85 | NSString *s = [NSString stringWithUTF8String:c];
86 |
87 | [object setValue:s forKey:[NSString stringWithUTF8String:sqlite3_column_name([_statement statement], columnIdx)]];
88 | }
89 | }
90 | }
91 |
92 | #pragma clang diagnostic push
93 | #pragma clang diagnostic ignored "-Wdeprecated-implementations"
94 |
95 | - (NSDictionary*)resultDict {
96 |
97 | NSUInteger num_cols = (NSUInteger)sqlite3_data_count([_statement statement]);
98 |
99 | if (num_cols > 0) {
100 | NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:num_cols];
101 |
102 | NSEnumerator *columnNames = [[self columnNameToIndexMap] keyEnumerator];
103 | NSString *columnName = nil;
104 | while ((columnName = [columnNames nextObject])) {
105 | id objectValue = [self objectForColumnName:columnName];
106 | [dict setObject:objectValue forKey:columnName];
107 | }
108 |
109 | return FMDBReturnAutoreleased([dict copy]);
110 | }
111 | else {
112 | NSLog(@"Warning: There seem to be no columns in this set.");
113 | }
114 |
115 | return nil;
116 | }
117 |
118 | #pragma clang diagnostic pop
119 |
120 | - (NSDictionary*)resultDictionary {
121 |
122 | NSUInteger num_cols = (NSUInteger)sqlite3_data_count([_statement statement]);
123 |
124 | if (num_cols > 0) {
125 | NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:num_cols];
126 |
127 | int columnCount = sqlite3_column_count([_statement statement]);
128 |
129 | int columnIdx = 0;
130 | for (columnIdx = 0; columnIdx < columnCount; columnIdx++) {
131 |
132 | NSString *columnName = [NSString stringWithUTF8String:sqlite3_column_name([_statement statement], columnIdx)];
133 | id objectValue = [self objectForColumnIndex:columnIdx];
134 | [dict setObject:objectValue forKey:columnName];
135 | }
136 |
137 | return dict;
138 | }
139 | else {
140 | NSLog(@"Warning: There seem to be no columns in this set.");
141 | }
142 |
143 | return nil;
144 | }
145 |
146 |
147 |
148 |
149 | - (BOOL)next {
150 | return [self nextWithError:nil];
151 | }
152 |
153 | - (BOOL)nextWithError:(NSError **)outErr {
154 |
155 | int rc = sqlite3_step([_statement statement]);
156 |
157 | if (SQLITE_BUSY == rc || SQLITE_LOCKED == rc) {
158 | NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [_parentDB databasePath]);
159 | NSLog(@"Database busy");
160 | if (outErr) {
161 | *outErr = [_parentDB lastError];
162 | }
163 | }
164 | else if (SQLITE_DONE == rc || SQLITE_ROW == rc) {
165 | // all is well, let's return.
166 | }
167 | else if (SQLITE_ERROR == rc) {
168 | NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([_parentDB sqliteHandle]));
169 | if (outErr) {
170 | *outErr = [_parentDB lastError];
171 | }
172 | }
173 | else if (SQLITE_MISUSE == rc) {
174 | // uh oh.
175 | NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([_parentDB sqliteHandle]));
176 | if (outErr) {
177 | if (_parentDB) {
178 | *outErr = [_parentDB lastError];
179 | }
180 | else {
181 | // If 'next' or 'nextWithError' is called after the result set is closed,
182 | // we need to return the appropriate error.
183 | NSDictionary* errorMessage = [NSDictionary dictionaryWithObject:@"parentDB does not exist" forKey:NSLocalizedDescriptionKey];
184 | *outErr = [NSError errorWithDomain:@"FMDatabase" code:SQLITE_MISUSE userInfo:errorMessage];
185 | }
186 |
187 | }
188 | }
189 | else {
190 | // wtf?
191 | NSLog(@"Unknown error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([_parentDB sqliteHandle]));
192 | if (outErr) {
193 | *outErr = [_parentDB lastError];
194 | }
195 | }
196 |
197 |
198 | if (rc != SQLITE_ROW) {
199 | [self close];
200 | }
201 |
202 | return (rc == SQLITE_ROW);
203 | }
204 |
205 | - (BOOL)hasAnotherRow {
206 | return sqlite3_errcode([_parentDB sqliteHandle]) == SQLITE_ROW;
207 | }
208 |
209 | - (int)columnIndexForName:(NSString*)columnName {
210 | columnName = [columnName lowercaseString];
211 |
212 | NSNumber *n = [[self columnNameToIndexMap] objectForKey:columnName];
213 |
214 | if (n) {
215 | return [n intValue];
216 | }
217 |
218 | NSLog(@"Warning: I could not find the column named '%@'.", columnName);
219 |
220 | return -1;
221 | }
222 |
223 |
224 |
225 | - (int)intForColumn:(NSString*)columnName {
226 | return [self intForColumnIndex:[self columnIndexForName:columnName]];
227 | }
228 |
229 | - (int)intForColumnIndex:(int)columnIdx {
230 | return sqlite3_column_int([_statement statement], columnIdx);
231 | }
232 |
233 | - (long)longForColumn:(NSString*)columnName {
234 | return [self longForColumnIndex:[self columnIndexForName:columnName]];
235 | }
236 |
237 | - (long)longForColumnIndex:(int)columnIdx {
238 | return (long)sqlite3_column_int64([_statement statement], columnIdx);
239 | }
240 |
241 | - (long long int)longLongIntForColumn:(NSString*)columnName {
242 | return [self longLongIntForColumnIndex:[self columnIndexForName:columnName]];
243 | }
244 |
245 | - (long long int)longLongIntForColumnIndex:(int)columnIdx {
246 | return sqlite3_column_int64([_statement statement], columnIdx);
247 | }
248 |
249 | - (unsigned long long int)unsignedLongLongIntForColumn:(NSString*)columnName {
250 | return [self unsignedLongLongIntForColumnIndex:[self columnIndexForName:columnName]];
251 | }
252 |
253 | - (unsigned long long int)unsignedLongLongIntForColumnIndex:(int)columnIdx {
254 | return (unsigned long long int)[self longLongIntForColumnIndex:columnIdx];
255 | }
256 |
257 | - (BOOL)boolForColumn:(NSString*)columnName {
258 | return [self boolForColumnIndex:[self columnIndexForName:columnName]];
259 | }
260 |
261 | - (BOOL)boolForColumnIndex:(int)columnIdx {
262 | return ([self intForColumnIndex:columnIdx] != 0);
263 | }
264 |
265 | - (double)doubleForColumn:(NSString*)columnName {
266 | return [self doubleForColumnIndex:[self columnIndexForName:columnName]];
267 | }
268 |
269 | - (double)doubleForColumnIndex:(int)columnIdx {
270 | return sqlite3_column_double([_statement statement], columnIdx);
271 | }
272 |
273 | - (NSString*)stringForColumnIndex:(int)columnIdx {
274 |
275 | if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
276 | return nil;
277 | }
278 |
279 | const char *c = (const char *)sqlite3_column_text([_statement statement], columnIdx);
280 |
281 | if (!c) {
282 | // null row.
283 | return nil;
284 | }
285 |
286 | return [NSString stringWithUTF8String:c];
287 | }
288 |
289 | - (NSString*)stringForColumn:(NSString*)columnName {
290 | return [self stringForColumnIndex:[self columnIndexForName:columnName]];
291 | }
292 |
293 | - (NSDate*)dateForColumn:(NSString*)columnName {
294 | return [self dateForColumnIndex:[self columnIndexForName:columnName]];
295 | }
296 |
297 | - (NSDate*)dateForColumnIndex:(int)columnIdx {
298 |
299 | if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
300 | return nil;
301 | }
302 |
303 | return [_parentDB hasDateFormatter] ? [_parentDB dateFromString:[self stringForColumnIndex:columnIdx]] : [NSDate dateWithTimeIntervalSince1970:[self doubleForColumnIndex:columnIdx]];
304 | }
305 |
306 |
307 | - (NSData*)dataForColumn:(NSString*)columnName {
308 | return [self dataForColumnIndex:[self columnIndexForName:columnName]];
309 | }
310 |
311 | - (NSData*)dataForColumnIndex:(int)columnIdx {
312 |
313 | if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
314 | return nil;
315 | }
316 |
317 | const char *dataBuffer = sqlite3_column_blob([_statement statement], columnIdx);
318 | int dataSize = sqlite3_column_bytes([_statement statement], columnIdx);
319 |
320 | if (dataBuffer == NULL) {
321 | return nil;
322 | }
323 |
324 | return [NSData dataWithBytes:(const void *)dataBuffer length:(NSUInteger)dataSize];
325 | }
326 |
327 |
328 | - (NSData*)dataNoCopyForColumn:(NSString*)columnName {
329 | return [self dataNoCopyForColumnIndex:[self columnIndexForName:columnName]];
330 | }
331 |
332 | - (NSData*)dataNoCopyForColumnIndex:(int)columnIdx {
333 |
334 | if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
335 | return nil;
336 | }
337 |
338 | const char *dataBuffer = sqlite3_column_blob([_statement statement], columnIdx);
339 | int dataSize = sqlite3_column_bytes([_statement statement], columnIdx);
340 |
341 | NSData *data = [NSData dataWithBytesNoCopy:(void *)dataBuffer length:(NSUInteger)dataSize freeWhenDone:NO];
342 |
343 | return data;
344 | }
345 |
346 |
347 | - (BOOL)columnIndexIsNull:(int)columnIdx {
348 | return sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL;
349 | }
350 |
351 | - (BOOL)columnIsNull:(NSString*)columnName {
352 | return [self columnIndexIsNull:[self columnIndexForName:columnName]];
353 | }
354 |
355 | - (const unsigned char *)UTF8StringForColumnIndex:(int)columnIdx {
356 |
357 | if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
358 | return nil;
359 | }
360 |
361 | return sqlite3_column_text([_statement statement], columnIdx);
362 | }
363 |
364 | - (const unsigned char *)UTF8StringForColumnName:(NSString*)columnName {
365 | return [self UTF8StringForColumnIndex:[self columnIndexForName:columnName]];
366 | }
367 |
368 | - (id)objectForColumnIndex:(int)columnIdx {
369 | int columnType = sqlite3_column_type([_statement statement], columnIdx);
370 |
371 | id returnValue = nil;
372 |
373 | if (columnType == SQLITE_INTEGER) {
374 | returnValue = [NSNumber numberWithLongLong:[self longLongIntForColumnIndex:columnIdx]];
375 | }
376 | else if (columnType == SQLITE_FLOAT) {
377 | returnValue = [NSNumber numberWithDouble:[self doubleForColumnIndex:columnIdx]];
378 | }
379 | else if (columnType == SQLITE_BLOB) {
380 | returnValue = [self dataForColumnIndex:columnIdx];
381 | }
382 | else {
383 | //default to a string for everything else
384 | returnValue = [self stringForColumnIndex:columnIdx];
385 | }
386 |
387 | if (returnValue == nil) {
388 | returnValue = [NSNull null];
389 | }
390 |
391 | return returnValue;
392 | }
393 |
394 | - (id)objectForColumnName:(NSString*)columnName {
395 | return [self objectForColumnIndex:[self columnIndexForName:columnName]];
396 | }
397 |
398 | // returns autoreleased NSString containing the name of the column in the result set
399 | - (NSString*)columnNameForIndex:(int)columnIdx {
400 | return [NSString stringWithUTF8String: sqlite3_column_name([_statement statement], columnIdx)];
401 | }
402 |
403 | - (void)setParentDB:(FMDatabase *)newDb {
404 | _parentDB = newDb;
405 | }
406 |
407 | - (id)objectAtIndexedSubscript:(int)columnIdx {
408 | return [self objectForColumnIndex:columnIdx];
409 | }
410 |
411 | - (id)objectForKeyedSubscript:(NSString *)columnName {
412 | return [self objectForColumnName:columnName];
413 | }
414 |
415 |
416 | @end
417 |
--------------------------------------------------------------------------------
/TextUtil/OpenSources/FMDB/FMResultSet.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import "sqlite3.h"
3 |
4 | #ifndef __has_feature // Optional.
5 | #define __has_feature(x) 0 // Compatibility with non-clang compilers.
6 | #endif
7 |
8 | #ifndef NS_RETURNS_NOT_RETAINED
9 | #if __has_feature(attribute_ns_returns_not_retained)
10 | #define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))
11 | #else
12 | #define NS_RETURNS_NOT_RETAINED
13 | #endif
14 | #endif
15 |
16 | @class FMDatabase;
17 | @class FMStatement;
18 |
19 | /** Represents the results of executing a query on an ``.
20 |
21 | ### See also
22 |
23 | - ``
24 | */
25 |
26 | @interface FMResultSet : NSObject {
27 | FMDatabase *_parentDB;
28 | FMStatement *_statement;
29 |
30 | NSString *_query;
31 | NSMutableDictionary *_columnNameToIndexMap;
32 | }
33 |
34 | ///-----------------
35 | /// @name Properties
36 | ///-----------------
37 |
38 | /** Executed query */
39 |
40 | @property (atomic, retain) NSString *query;
41 |
42 | /** `NSMutableDictionary` mapping column names to numeric index */
43 |
44 | @property (readonly) NSMutableDictionary *columnNameToIndexMap;
45 |
46 | /** `FMStatement` used by result set. */
47 |
48 | @property (atomic, retain) FMStatement *statement;
49 |
50 | ///------------------------------------
51 | /// @name Creating and closing database
52 | ///------------------------------------
53 |
54 | /** Create result set from ``
55 |
56 | @param statement A `` to be performed
57 |
58 | @param aDB A `` to be used
59 |
60 | @return A `FMResultSet` on success; `nil` on failure
61 | */
62 |
63 | + (instancetype)resultSetWithStatement:(FMStatement *)statement usingParentDatabase:(FMDatabase*)aDB;
64 |
65 | /** Close result set */
66 |
67 | - (void)close;
68 |
69 | - (void)setParentDB:(FMDatabase *)newDb;
70 |
71 | ///---------------------------------------
72 | /// @name Iterating through the result set
73 | ///---------------------------------------
74 |
75 | /** Retrieve next row for result set.
76 |
77 | You must always invoke `next` or `nextWithError` before attempting to access the values returned in a query, even if you're only expecting one.
78 |
79 | @return `YES` if row successfully retrieved; `NO` if end of result set reached
80 |
81 | @see hasAnotherRow
82 | */
83 |
84 | - (BOOL)next;
85 |
86 | /** Retrieve next row for result set.
87 |
88 | You must always invoke `next` or `nextWithError` before attempting to access the values returned in a query, even if you're only expecting one.
89 |
90 | @param outErr A 'NSError' object to receive any error object (if any).
91 |
92 | @return 'YES' if row successfully retrieved; 'NO' if end of result set reached
93 |
94 | @see hasAnotherRow
95 | */
96 |
97 | - (BOOL)nextWithError:(NSError **)outErr;
98 |
99 | /** Did the last call to `` succeed in retrieving another row?
100 |
101 | @return `YES` if the last call to `` succeeded in retrieving another record; `NO` if not.
102 |
103 | @see next
104 |
105 | @warning The `hasAnotherRow` method must follow a call to ``. If the previous database interaction was something other than a call to `next`, then this method may return `NO`, whether there is another row of data or not.
106 | */
107 |
108 | - (BOOL)hasAnotherRow;
109 |
110 | ///---------------------------------------------
111 | /// @name Retrieving information from result set
112 | ///---------------------------------------------
113 |
114 | /** How many columns in result set
115 |
116 | @return Integer value of the number of columns.
117 | */
118 |
119 | - (int)columnCount;
120 |
121 | /** Column index for column name
122 |
123 | @param columnName `NSString` value of the name of the column.
124 |
125 | @return Zero-based index for column.
126 | */
127 |
128 | - (int)columnIndexForName:(NSString*)columnName;
129 |
130 | /** Column name for column index
131 |
132 | @param columnIdx Zero-based index for column.
133 |
134 | @return columnName `NSString` value of the name of the column.
135 | */
136 |
137 | - (NSString*)columnNameForIndex:(int)columnIdx;
138 |
139 | /** Result set integer value for column.
140 |
141 | @param columnName `NSString` value of the name of the column.
142 |
143 | @return `int` value of the result set's column.
144 | */
145 |
146 | - (int)intForColumn:(NSString*)columnName;
147 |
148 | /** Result set integer value for column.
149 |
150 | @param columnIdx Zero-based index for column.
151 |
152 | @return `int` value of the result set's column.
153 | */
154 |
155 | - (int)intForColumnIndex:(int)columnIdx;
156 |
157 | /** Result set `long` value for column.
158 |
159 | @param columnName `NSString` value of the name of the column.
160 |
161 | @return `long` value of the result set's column.
162 | */
163 |
164 | - (long)longForColumn:(NSString*)columnName;
165 |
166 | /** Result set long value for column.
167 |
168 | @param columnIdx Zero-based index for column.
169 |
170 | @return `long` value of the result set's column.
171 | */
172 |
173 | - (long)longForColumnIndex:(int)columnIdx;
174 |
175 | /** Result set `long long int` value for column.
176 |
177 | @param columnName `NSString` value of the name of the column.
178 |
179 | @return `long long int` value of the result set's column.
180 | */
181 |
182 | - (long long int)longLongIntForColumn:(NSString*)columnName;
183 |
184 | /** Result set `long long int` value for column.
185 |
186 | @param columnIdx Zero-based index for column.
187 |
188 | @return `long long int` value of the result set's column.
189 | */
190 |
191 | - (long long int)longLongIntForColumnIndex:(int)columnIdx;
192 |
193 | /** Result set `unsigned long long int` value for column.
194 |
195 | @param columnName `NSString` value of the name of the column.
196 |
197 | @return `unsigned long long int` value of the result set's column.
198 | */
199 |
200 | - (unsigned long long int)unsignedLongLongIntForColumn:(NSString*)columnName;
201 |
202 | /** Result set `unsigned long long int` value for column.
203 |
204 | @param columnIdx Zero-based index for column.
205 |
206 | @return `unsigned long long int` value of the result set's column.
207 | */
208 |
209 | - (unsigned long long int)unsignedLongLongIntForColumnIndex:(int)columnIdx;
210 |
211 | /** Result set `BOOL` value for column.
212 |
213 | @param columnName `NSString` value of the name of the column.
214 |
215 | @return `BOOL` value of the result set's column.
216 | */
217 |
218 | - (BOOL)boolForColumn:(NSString*)columnName;
219 |
220 | /** Result set `BOOL` value for column.
221 |
222 | @param columnIdx Zero-based index for column.
223 |
224 | @return `BOOL` value of the result set's column.
225 | */
226 |
227 | - (BOOL)boolForColumnIndex:(int)columnIdx;
228 |
229 | /** Result set `double` value for column.
230 |
231 | @param columnName `NSString` value of the name of the column.
232 |
233 | @return `double` value of the result set's column.
234 |
235 | */
236 |
237 | - (double)doubleForColumn:(NSString*)columnName;
238 |
239 | /** Result set `double` value for column.
240 |
241 | @param columnIdx Zero-based index for column.
242 |
243 | @return `double` value of the result set's column.
244 |
245 | */
246 |
247 | - (double)doubleForColumnIndex:(int)columnIdx;
248 |
249 | /** Result set `NSString` value for column.
250 |
251 | @param columnName `NSString` value of the name of the column.
252 |
253 | @return `NSString` value of the result set's column.
254 |
255 | */
256 |
257 | - (NSString*)stringForColumn:(NSString*)columnName;
258 |
259 | /** Result set `NSString` value for column.
260 |
261 | @param columnIdx Zero-based index for column.
262 |
263 | @return `NSString` value of the result set's column.
264 | */
265 |
266 | - (NSString*)stringForColumnIndex:(int)columnIdx;
267 |
268 | /** Result set `NSDate` value for column.
269 |
270 | @param columnName `NSString` value of the name of the column.
271 |
272 | @return `NSDate` value of the result set's column.
273 | */
274 |
275 | - (NSDate*)dateForColumn:(NSString*)columnName;
276 |
277 | /** Result set `NSDate` value for column.
278 |
279 | @param columnIdx Zero-based index for column.
280 |
281 | @return `NSDate` value of the result set's column.
282 |
283 | */
284 |
285 | - (NSDate*)dateForColumnIndex:(int)columnIdx;
286 |
287 | /** Result set `NSData` value for column.
288 |
289 | This is useful when storing binary data in table (such as image or the like).
290 |
291 | @param columnName `NSString` value of the name of the column.
292 |
293 | @return `NSData` value of the result set's column.
294 |
295 | */
296 |
297 | - (NSData*)dataForColumn:(NSString*)columnName;
298 |
299 | /** Result set `NSData` value for column.
300 |
301 | @param columnIdx Zero-based index for column.
302 |
303 | @return `NSData` value of the result set's column.
304 | */
305 |
306 | - (NSData*)dataForColumnIndex:(int)columnIdx;
307 |
308 | /** Result set `(const unsigned char *)` value for column.
309 |
310 | @param columnName `NSString` value of the name of the column.
311 |
312 | @return `(const unsigned char *)` value of the result set's column.
313 | */
314 |
315 | - (const unsigned char *)UTF8StringForColumnName:(NSString*)columnName;
316 |
317 | /** Result set `(const unsigned char *)` value for column.
318 |
319 | @param columnIdx Zero-based index for column.
320 |
321 | @return `(const unsigned char *)` value of the result set's column.
322 | */
323 |
324 | - (const unsigned char *)UTF8StringForColumnIndex:(int)columnIdx;
325 |
326 | /** Result set object for column.
327 |
328 | @param columnName `NSString` value of the name of the column.
329 |
330 | @return Either `NSNumber`, `NSString`, `NSData`, or `NSNull`. If the column was `NULL`, this returns `[NSNull null]` object.
331 |
332 | @see objectForKeyedSubscript:
333 | */
334 |
335 | - (id)objectForColumnName:(NSString*)columnName;
336 |
337 | /** Result set object for column.
338 |
339 | @param columnIdx Zero-based index for column.
340 |
341 | @return Either `NSNumber`, `NSString`, `NSData`, or `NSNull`. If the column was `NULL`, this returns `[NSNull null]` object.
342 |
343 | @see objectAtIndexedSubscript:
344 | */
345 |
346 | - (id)objectForColumnIndex:(int)columnIdx;
347 |
348 | /** Result set object for column.
349 |
350 | This method allows the use of the "boxed" syntax supported in Modern Objective-C. For example, by defining this method, the following syntax is now supported:
351 |
352 | id result = rs[@"employee_name"];
353 |
354 | This simplified syntax is equivalent to calling:
355 |
356 | id result = [rs objectForKeyedSubscript:@"employee_name"];
357 |
358 | which is, it turns out, equivalent to calling:
359 |
360 | id result = [rs objectForColumnName:@"employee_name"];
361 |
362 | @param columnName `NSString` value of the name of the column.
363 |
364 | @return Either `NSNumber`, `NSString`, `NSData`, or `NSNull`. If the column was `NULL`, this returns `[NSNull null]` object.
365 | */
366 |
367 | - (id)objectForKeyedSubscript:(NSString *)columnName;
368 |
369 | /** Result set object for column.
370 |
371 | This method allows the use of the "boxed" syntax supported in Modern Objective-C. For example, by defining this method, the following syntax is now supported:
372 |
373 | id result = rs[0];
374 |
375 | This simplified syntax is equivalent to calling:
376 |
377 | id result = [rs objectForKeyedSubscript:0];
378 |
379 | which is, it turns out, equivalent to calling:
380 |
381 | id result = [rs objectForColumnName:0];
382 |
383 | @param columnIdx Zero-based index for column.
384 |
385 | @return Either `NSNumber`, `NSString`, `NSData`, or `NSNull`. If the column was `NULL`, this returns `[NSNull null]` object.
386 | */
387 |
388 | - (id)objectAtIndexedSubscript:(int)columnIdx;
389 |
390 | /** Result set `NSData` value for column.
391 |
392 | @param columnName `NSString` value of the name of the column.
393 |
394 | @return `NSData` value of the result set's column.
395 |
396 | @warning If you are going to use this data after you iterate over the next row, or after you close the
397 | result set, make sure to make a copy of the data first (or just use ``/``)
398 | If you don't, you're going to be in a world of hurt when you try and use the data.
399 |
400 | */
401 |
402 | - (NSData*)dataNoCopyForColumn:(NSString*)columnName NS_RETURNS_NOT_RETAINED;
403 |
404 | /** Result set `NSData` value for column.
405 |
406 | @param columnIdx Zero-based index for column.
407 |
408 | @return `NSData` value of the result set's column.
409 |
410 | @warning If you are going to use this data after you iterate over the next row, or after you close the
411 | result set, make sure to make a copy of the data first (or just use ``/``)
412 | If you don't, you're going to be in a world of hurt when you try and use the data.
413 |
414 | */
415 |
416 | - (NSData*)dataNoCopyForColumnIndex:(int)columnIdx NS_RETURNS_NOT_RETAINED;
417 |
418 | /** Is the column `NULL`?
419 |
420 | @param columnIdx Zero-based index for column.
421 |
422 | @return `YES` if column is `NULL`; `NO` if not `NULL`.
423 | */
424 |
425 | - (BOOL)columnIndexIsNull:(int)columnIdx;
426 |
427 | /** Is the column `NULL`?
428 |
429 | @param columnName `NSString` value of the name of the column.
430 |
431 | @return `YES` if column is `NULL`; `NO` if not `NULL`.
432 | */
433 |
434 | - (BOOL)columnIsNull:(NSString*)columnName;
435 |
436 |
437 | /** Returns a dictionary of the row results mapped to case sensitive keys of the column names.
438 |
439 | @returns `NSDictionary` of the row results.
440 |
441 | @warning The keys to the dictionary are case sensitive of the column names.
442 | */
443 |
444 | - (NSDictionary*)resultDictionary;
445 |
446 | /** Returns a dictionary of the row results
447 |
448 | @see resultDictionary
449 |
450 | @warning **Deprecated**: Please use `` instead. Also, beware that `` is case sensitive!
451 | */
452 |
453 | - (NSDictionary*)resultDict __attribute__ ((deprecated));
454 |
455 | ///-----------------------------
456 | /// @name Key value coding magic
457 | ///-----------------------------
458 |
459 | /** Performs `setValue` to yield support for key value observing.
460 |
461 | @param object The object for which the values will be set. This is the key-value-coding compliant object that you might, for example, observe.
462 |
463 | */
464 |
465 | - (void)kvcMagic:(id)object;
466 |
467 |
468 | @end
469 |
470 |
--------------------------------------------------------------------------------