diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7697b30 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +# Xcode +.DS_Store +*/build/* +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +*.xcworkspace +!default.xcworkspace +xcuserdata +profile +*.moved-aside +DerivedData +.idea/ +*.hmap diff --git a/Default-568h@2x.png b/Default-568h@2x.png new file mode 100644 index 0000000..0891b7a Binary files /dev/null and b/Default-568h@2x.png differ diff --git a/HabraReader.xcodeproj/project.pbxproj b/HabraReader.xcodeproj/project.pbxproj new file mode 100644 index 0000000..3a1d1eb --- /dev/null +++ b/HabraReader.xcodeproj/project.pbxproj @@ -0,0 +1,719 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + A503CE8A16678ABB004E626E /* HRPostLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = A503CE8916678ABB004E626E /* HRPostLoader.m */; }; + A503CE8D16679E02004E626E /* load.html in Resources */ = {isa = PBXBuildFile; fileRef = A503CE8C16679E02004E626E /* load.html */; }; + A51689A6162B58630045EFDB /* Post.m in Sources */ = {isa = PBXBuildFile; fileRef = A51689A5162B58630045EFDB /* Post.m */; }; + A51689A8162B5BC20045EFDB /* habrahabr_02.png in Resources */ = {isa = PBXBuildFile; fileRef = A51689A7162B5BC20045EFDB /* habrahabr_02.png */; }; + A51689AB162B61540045EFDB /* HRPostViewer.m in Sources */ = {isa = PBXBuildFile; fileRef = A51689AA162B61530045EFDB /* HRPostViewer.m */; }; + A5329BA21635EA980065CE4D /* habrahabr_01.png in Resources */ = {isa = PBXBuildFile; fileRef = A5329BA11635EA980065CE4D /* habrahabr_01.png */; }; + A5329BA51635EACE0065CE4D /* habrahabr-iphone_02.png in Resources */ = {isa = PBXBuildFile; fileRef = A5329BA41635EACE0065CE4D /* habrahabr-iphone_02.png */; }; + A53F8B56168626DD0043E244 /* Message+Count.m in Sources */ = {isa = PBXBuildFile; fileRef = A53F8B55168626DD0043E244 /* Message+Count.m */; }; + A53F8B5C168627770043E244 /* Comment+Description.m in Sources */ = {isa = PBXBuildFile; fileRef = A53F8B5B168627770043E244 /* Comment+Description.m */; }; + A54480151680A912002D570A /* HRCommentsParser.m in Sources */ = {isa = PBXBuildFile; fileRef = A54480141680A912002D570A /* HRCommentsParser.m */; }; + A56D8132162467AE00BD2159 /* HabraReader_Prototype.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = A56D8130162467AE00BD2159 /* HabraReader_Prototype.xcdatamodeld */; }; + A56D8135162468F000BD2159 /* GenericHub.m in Sources */ = {isa = PBXBuildFile; fileRef = A56D8134162468F000BD2159 /* GenericHub.m */; }; + A56D813B162468F000BD2159 /* Company.m in Sources */ = {isa = PBXBuildFile; fileRef = A56D813A162468F000BD2159 /* Company.m */; }; + A56D813E162468F000BD2159 /* Tag.m in Sources */ = {isa = PBXBuildFile; fileRef = A56D813D162468F000BD2159 /* Tag.m */; }; + A56D8141162468F000BD2159 /* Message.m in Sources */ = {isa = PBXBuildFile; fileRef = A56D8140162468F000BD2159 /* Message.m */; }; + A56D8144162468F100BD2159 /* Hub.m in Sources */ = {isa = PBXBuildFile; fileRef = A56D8143162468F100BD2159 /* Hub.m */; }; + A56D814A162468F100BD2159 /* Author.m in Sources */ = {isa = PBXBuildFile; fileRef = A56D8149162468F100BD2159 /* Author.m */; }; + A56D814D1624693800BD2159 /* Comment.m in Sources */ = {isa = PBXBuildFile; fileRef = A56D814C1624693800BD2159 /* Comment.m */; }; + A56D815E16246AEF00BD2159 /* Author+Create.m in Sources */ = {isa = PBXBuildFile; fileRef = A56D815716246AEF00BD2159 /* Author+Create.m */; }; + A56D815F16246AEF00BD2159 /* Company+Create.m in Sources */ = {isa = PBXBuildFile; fileRef = A56D815916246AEF00BD2159 /* Company+Create.m */; }; + A56D816016246AEF00BD2159 /* Hub+Create.m in Sources */ = {isa = PBXBuildFile; fileRef = A56D815B16246AEF00BD2159 /* Hub+Create.m */; }; + A56D816116246AEF00BD2159 /* Post+Create.m in Sources */ = {isa = PBXBuildFile; fileRef = A56D815D16246AEF00BD2159 /* Post+Create.m */; }; + A56D816416246B2600BD2159 /* HRPDataLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = A56D816316246B2600BD2159 /* HRPDataLoader.m */; }; + A56D816B1624721200BD2159 /* HRHubTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A56D816A1624721200BD2159 /* HRHubTableViewController.m */; }; + A588919E165BA41C005C5FB0 /* HTMLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = A588919D165BA41C005C5FB0 /* HTMLParser.m */; }; + A5921FFF16774BD000E9A3DE /* HRMultiFetchTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A5921FFE16774BD000E9A3DE /* HRMultiFetchTableViewController.m */; }; + A592200216775AC200E9A3DE /* HRGlagne.m in Sources */ = {isa = PBXBuildFile; fileRef = A592200116775AC200E9A3DE /* HRGlagne.m */; }; + A5A4BE7C15F90ADB0043F896 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A5A4BE7B15F90ADB0043F896 /* UIKit.framework */; }; + A5A4BE7E15F90ADB0043F896 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A5A4BE7D15F90ADB0043F896 /* Foundation.framework */; }; + A5A4BE8015F90ADB0043F896 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A5A4BE7F15F90ADB0043F896 /* CoreGraphics.framework */; }; + A5A4BE8615F90ADB0043F896 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A5A4BE8415F90ADB0043F896 /* InfoPlist.strings */; }; + A5A4BE8815F90ADB0043F896 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = A5A4BE8715F90ADB0043F896 /* main.m */; }; + A5A4BE8C15F90ADB0043F896 /* HRAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A5A4BE8B15F90ADB0043F896 /* HRAppDelegate.m */; }; + A5A4BE8F15F90ADB0043F896 /* MainStoryboard_iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A5A4BE8D15F90ADB0043F896 /* MainStoryboard_iPhone.storyboard */; }; + A5A4BE9215F90ADB0043F896 /* MainStoryboard_iPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A5A4BE9015F90ADB0043F896 /* MainStoryboard_iPad.storyboard */; }; + A5A4BE9D15F90ADB0043F896 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A5A4BE9C15F90ADB0043F896 /* SenTestingKit.framework */; }; + A5A4BE9E15F90ADB0043F896 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A5A4BE7B15F90ADB0043F896 /* UIKit.framework */; }; + A5A4BE9F15F90ADB0043F896 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A5A4BE7D15F90ADB0043F896 /* Foundation.framework */; }; + A5A4BEA715F90ADB0043F896 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A5A4BEA515F90ADB0043F896 /* InfoPlist.strings */; }; + A5A4BEAA15F90ADB0043F896 /* HabraReaderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A5A4BEA915F90ADB0043F896 /* HabraReaderTests.m */; }; + A5A4BEB515F911EC0043F896 /* NSMutableString+RemoveTag.m in Sources */ = {isa = PBXBuildFile; fileRef = A5A4BEB415F911EC0043F896 /* NSMutableString+RemoveTag.m */; }; + A5B1656E1624911D008302C3 /* HRCompanyTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A5B1656D1624911D008302C3 /* HRCompanyTableViewController.m */; }; + A5B165791624AD39008302C3 /* HRPostsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A5B165781624AD39008302C3 /* HRPostsTableViewController.m */; }; + A5BF3E001626026800754747 /* HRListOfGenericHubs.m in Sources */ = {isa = PBXBuildFile; fileRef = A5BF3DFF1626026800754747 /* HRListOfGenericHubs.m */; }; + A5D6D83B16833B1200B2DE2E /* HRCommentsTableController.m in Sources */ = {isa = PBXBuildFile; fileRef = A5D6D83A16833B1200B2DE2E /* HRCommentsTableController.m */; }; + A5E0FBFA167B073300A72897 /* HRModel.m in Sources */ = {isa = PBXBuildFile; fileRef = A5E0FBF9167B073300A72897 /* HRModel.m */; }; + A5E47767162CA2E3002CF89C /* HRStartupLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = A5E47766162CA2E3002CF89C /* HRStartupLoader.m */; }; + A5E4BFF0164FCC4C00B04847 /* HRRSSParser.m in Sources */ = {isa = PBXBuildFile; fileRef = A5E4BFEF164FCC4C00B04847 /* HRRSSParser.m */; }; + A5E755A41652E237008C8D57 /* NSString+Tags.m in Sources */ = {isa = PBXBuildFile; fileRef = A5E755A31652E237008C8D57 /* NSString+Tags.m */; }; + A5E75C17162443D30024C3C0 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A5E75C16162443D30024C3C0 /* Default-568h@2x.png */; }; + A5E75C191624443B0024C3C0 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A5E75C181624443B0024C3C0 /* CoreData.framework */; }; + A5E75C1C1624651F0024C3C0 /* CoreDataTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A5E75C1B1624651F0024C3C0 /* CoreDataTableViewController.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + A5A4BEA015F90ADB0043F896 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A5A4BE6E15F90ADB0043F896 /* Project object */; + proxyType = 1; + remoteGlobalIDString = A5A4BE7615F90ADB0043F896; + remoteInfo = HabraReader; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + A503CE8816678ABB004E626E /* HRPostLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HRPostLoader.h; sourceTree = ""; }; + A503CE8916678ABB004E626E /* HRPostLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HRPostLoader.m; sourceTree = ""; }; + A503CE8C16679E02004E626E /* load.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = load.html; sourceTree = ""; }; + A51689A4162B58630045EFDB /* Post.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Post.h; sourceTree = ""; }; + A51689A5162B58630045EFDB /* Post.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Post.m; sourceTree = ""; }; + A51689A7162B5BC20045EFDB /* habrahabr_02.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = habrahabr_02.png; sourceTree = ""; }; + A51689A9162B61520045EFDB /* HRPostViewer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HRPostViewer.h; sourceTree = ""; }; + A51689AA162B61530045EFDB /* HRPostViewer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HRPostViewer.m; sourceTree = ""; }; + A5329BA11635EA980065CE4D /* habrahabr_01.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = habrahabr_01.png; sourceTree = ""; }; + A5329BA41635EACE0065CE4D /* habrahabr-iphone_02.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "habrahabr-iphone_02.png"; sourceTree = ""; }; + A53F8B54168626DD0043E244 /* Message+Count.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Message+Count.h"; sourceTree = ""; }; + A53F8B55168626DD0043E244 /* Message+Count.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "Message+Count.m"; sourceTree = ""; }; + A53F8B5A168627770043E244 /* Comment+Description.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Comment+Description.h"; sourceTree = ""; }; + A53F8B5B168627770043E244 /* Comment+Description.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "Comment+Description.m"; sourceTree = ""; }; + A54480131680A912002D570A /* HRCommentsParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HRCommentsParser.h; sourceTree = ""; }; + A54480141680A912002D570A /* HRCommentsParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HRCommentsParser.m; sourceTree = ""; }; + A56D8131162467AE00BD2159 /* HabraReader_Prototype.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = HabraReader_Prototype.xcdatamodel; sourceTree = ""; }; + A56D8133162468F000BD2159 /* GenericHub.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenericHub.h; sourceTree = ""; }; + A56D8134162468F000BD2159 /* GenericHub.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GenericHub.m; sourceTree = ""; }; + A56D8139162468F000BD2159 /* Company.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Company.h; sourceTree = ""; }; + A56D813A162468F000BD2159 /* Company.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Company.m; sourceTree = ""; }; + A56D813C162468F000BD2159 /* Tag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Tag.h; sourceTree = ""; }; + A56D813D162468F000BD2159 /* Tag.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Tag.m; sourceTree = ""; }; + A56D813F162468F000BD2159 /* Message.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Message.h; sourceTree = ""; }; + A56D8140162468F000BD2159 /* Message.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Message.m; sourceTree = ""; }; + A56D8142162468F000BD2159 /* Hub.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Hub.h; sourceTree = ""; }; + A56D8143162468F100BD2159 /* Hub.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Hub.m; sourceTree = ""; }; + A56D8148162468F100BD2159 /* Author.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Author.h; sourceTree = ""; }; + A56D8149162468F100BD2159 /* Author.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Author.m; sourceTree = ""; }; + A56D814B1624693800BD2159 /* Comment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Comment.h; sourceTree = ""; }; + A56D814C1624693800BD2159 /* Comment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Comment.m; sourceTree = ""; }; + A56D815616246AEF00BD2159 /* Author+Create.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Author+Create.h"; sourceTree = ""; }; + A56D815716246AEF00BD2159 /* Author+Create.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "Author+Create.m"; sourceTree = ""; }; + A56D815816246AEF00BD2159 /* Company+Create.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Company+Create.h"; sourceTree = ""; }; + A56D815916246AEF00BD2159 /* Company+Create.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "Company+Create.m"; sourceTree = ""; }; + A56D815A16246AEF00BD2159 /* Hub+Create.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Hub+Create.h"; sourceTree = ""; }; + A56D815B16246AEF00BD2159 /* Hub+Create.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "Hub+Create.m"; sourceTree = ""; }; + A56D815C16246AEF00BD2159 /* Post+Create.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Post+Create.h"; sourceTree = ""; }; + A56D815D16246AEF00BD2159 /* Post+Create.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "Post+Create.m"; sourceTree = ""; }; + A56D816216246B2600BD2159 /* HRPDataLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HRPDataLoader.h; sourceTree = ""; }; + A56D816316246B2600BD2159 /* HRPDataLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HRPDataLoader.m; sourceTree = ""; }; + A56D81691624721100BD2159 /* HRHubTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HRHubTableViewController.h; sourceTree = ""; }; + A56D816A1624721200BD2159 /* HRHubTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HRHubTableViewController.m; sourceTree = ""; }; + A588919C165BA41C005C5FB0 /* HTMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLParser.h; sourceTree = ""; }; + A588919D165BA41C005C5FB0 /* HTMLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLParser.m; sourceTree = ""; }; + A5921FFD16774BD000E9A3DE /* HRMultiFetchTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HRMultiFetchTableViewController.h; sourceTree = ""; }; + A5921FFE16774BD000E9A3DE /* HRMultiFetchTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HRMultiFetchTableViewController.m; sourceTree = ""; }; + A592200016775AC200E9A3DE /* HRGlagne.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HRGlagne.h; sourceTree = ""; }; + A592200116775AC200E9A3DE /* HRGlagne.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HRGlagne.m; sourceTree = ""; }; + A5A4BE7715F90ADB0043F896 /* HabraReader.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HabraReader.app; sourceTree = BUILT_PRODUCTS_DIR; }; + A5A4BE7B15F90ADB0043F896 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + A5A4BE7D15F90ADB0043F896 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + A5A4BE7F15F90ADB0043F896 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + A5A4BE8315F90ADB0043F896 /* HabraReader-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "HabraReader-Info.plist"; sourceTree = ""; }; + A5A4BE8515F90ADB0043F896 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + A5A4BE8715F90ADB0043F896 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + A5A4BE8915F90ADB0043F896 /* HabraReader-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "HabraReader-Prefix.pch"; sourceTree = ""; }; + A5A4BE8A15F90ADB0043F896 /* HRAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HRAppDelegate.h; sourceTree = ""; }; + A5A4BE8B15F90ADB0043F896 /* HRAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HRAppDelegate.m; sourceTree = ""; }; + A5A4BE8E15F90ADB0043F896 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/MainStoryboard_iPhone.storyboard; sourceTree = ""; }; + A5A4BE9115F90ADB0043F896 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/MainStoryboard_iPad.storyboard; sourceTree = ""; }; + A5A4BE9B15F90ADB0043F896 /* HabraReaderTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HabraReaderTests.octest; sourceTree = BUILT_PRODUCTS_DIR; }; + A5A4BE9C15F90ADB0043F896 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; + A5A4BEA415F90ADB0043F896 /* HabraReaderTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "HabraReaderTests-Info.plist"; sourceTree = ""; }; + A5A4BEA615F90ADB0043F896 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + A5A4BEA815F90ADB0043F896 /* HabraReaderTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HabraReaderTests.h; sourceTree = ""; }; + A5A4BEA915F90ADB0043F896 /* HabraReaderTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HabraReaderTests.m; sourceTree = ""; }; + A5A4BEB315F911EC0043F896 /* NSMutableString+RemoveTag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableString+RemoveTag.h"; sourceTree = ""; }; + A5A4BEB415F911EC0043F896 /* NSMutableString+RemoveTag.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableString+RemoveTag.m"; sourceTree = ""; }; + A5B1656C1624911D008302C3 /* HRCompanyTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HRCompanyTableViewController.h; sourceTree = ""; }; + A5B1656D1624911D008302C3 /* HRCompanyTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HRCompanyTableViewController.m; sourceTree = ""; }; + A5B165771624AD39008302C3 /* HRPostsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HRPostsTableViewController.h; sourceTree = ""; }; + A5B165781624AD39008302C3 /* HRPostsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HRPostsTableViewController.m; sourceTree = ""; }; + A5BF3DFE1626026800754747 /* HRListOfGenericHubs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HRListOfGenericHubs.h; sourceTree = ""; }; + A5BF3DFF1626026800754747 /* HRListOfGenericHubs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HRListOfGenericHubs.m; sourceTree = ""; }; + A5D6D83916833B1200B2DE2E /* HRCommentsTableController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HRCommentsTableController.h; sourceTree = ""; }; + A5D6D83A16833B1200B2DE2E /* HRCommentsTableController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HRCommentsTableController.m; sourceTree = ""; }; + A5E0FBF8167B073300A72897 /* HRModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HRModel.h; sourceTree = ""; }; + A5E0FBF9167B073300A72897 /* HRModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HRModel.m; sourceTree = ""; }; + A5E47765162CA2E3002CF89C /* HRStartupLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HRStartupLoader.h; sourceTree = ""; }; + A5E47766162CA2E3002CF89C /* HRStartupLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HRStartupLoader.m; sourceTree = ""; }; + A5E4BFEE164FCC4C00B04847 /* HRRSSParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HRRSSParser.h; sourceTree = ""; }; + A5E4BFEF164FCC4C00B04847 /* HRRSSParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HRRSSParser.m; sourceTree = ""; }; + A5E755A21652E237008C8D57 /* NSString+Tags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+Tags.h"; sourceTree = ""; }; + A5E755A31652E237008C8D57 /* NSString+Tags.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+Tags.m"; sourceTree = ""; }; + A5E75C16162443D30024C3C0 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "../Default-568h@2x.png"; sourceTree = ""; }; + A5E75C181624443B0024C3C0 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; + A5E75C1A1624651F0024C3C0 /* CoreDataTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoreDataTableViewController.h; sourceTree = ""; }; + A5E75C1B1624651F0024C3C0 /* CoreDataTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CoreDataTableViewController.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + A5A4BE7415F90ADB0043F896 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A5E75C191624443B0024C3C0 /* CoreData.framework in Frameworks */, + A5A4BE7C15F90ADB0043F896 /* UIKit.framework in Frameworks */, + A5A4BE7E15F90ADB0043F896 /* Foundation.framework in Frameworks */, + A5A4BE8015F90ADB0043F896 /* CoreGraphics.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A5A4BE9715F90ADB0043F896 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A5A4BE9D15F90ADB0043F896 /* SenTestingKit.framework in Frameworks */, + A5A4BE9E15F90ADB0043F896 /* UIKit.framework in Frameworks */, + A5A4BE9F15F90ADB0043F896 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + A56D815416246A7900BD2159 /* CoreData Classes */ = { + isa = PBXGroup; + children = ( + A51689A4162B58630045EFDB /* Post.h */, + A51689A5162B58630045EFDB /* Post.m */, + A56D814B1624693800BD2159 /* Comment.h */, + A56D814C1624693800BD2159 /* Comment.m */, + A56D8148162468F100BD2159 /* Author.h */, + A56D8149162468F100BD2159 /* Author.m */, + A56D8142162468F000BD2159 /* Hub.h */, + A56D8143162468F100BD2159 /* Hub.m */, + A56D813F162468F000BD2159 /* Message.h */, + A56D8140162468F000BD2159 /* Message.m */, + A56D813C162468F000BD2159 /* Tag.h */, + A56D813D162468F000BD2159 /* Tag.m */, + A56D8139162468F000BD2159 /* Company.h */, + A56D813A162468F000BD2159 /* Company.m */, + A56D8133162468F000BD2159 /* GenericHub.h */, + A56D8134162468F000BD2159 /* GenericHub.m */, + ); + name = "CoreData Classes"; + sourceTree = ""; + }; + A56D815516246A9500BD2159 /* CoreData Categories */ = { + isa = PBXGroup; + children = ( + A56D815616246AEF00BD2159 /* Author+Create.h */, + A56D815716246AEF00BD2159 /* Author+Create.m */, + A56D815816246AEF00BD2159 /* Company+Create.h */, + A56D815916246AEF00BD2159 /* Company+Create.m */, + A56D815A16246AEF00BD2159 /* Hub+Create.h */, + A56D815B16246AEF00BD2159 /* Hub+Create.m */, + A56D815C16246AEF00BD2159 /* Post+Create.h */, + A56D815D16246AEF00BD2159 /* Post+Create.m */, + A53F8B54168626DD0043E244 /* Message+Count.h */, + A53F8B55168626DD0043E244 /* Message+Count.m */, + A53F8B5A168627770043E244 /* Comment+Description.h */, + A53F8B5B168627770043E244 /* Comment+Description.m */, + ); + name = "CoreData Categories"; + sourceTree = ""; + }; + A5A4BE6C15F90ADB0043F896 = { + isa = PBXGroup; + children = ( + A5A4BE8115F90ADB0043F896 /* HabraReader */, + A5A4BEA215F90ADB0043F896 /* HabraReaderTests */, + A5A4BE7A15F90ADB0043F896 /* Frameworks */, + A5A4BE7815F90ADB0043F896 /* Products */, + ); + sourceTree = ""; + }; + A5A4BE7815F90ADB0043F896 /* Products */ = { + isa = PBXGroup; + children = ( + A5A4BE7715F90ADB0043F896 /* HabraReader.app */, + A5A4BE9B15F90ADB0043F896 /* HabraReaderTests.octest */, + ); + name = Products; + sourceTree = ""; + }; + A5A4BE7A15F90ADB0043F896 /* Frameworks */ = { + isa = PBXGroup; + children = ( + A5E75C181624443B0024C3C0 /* CoreData.framework */, + A5A4BE7B15F90ADB0043F896 /* UIKit.framework */, + A5A4BE7D15F90ADB0043F896 /* Foundation.framework */, + A5A4BE7F15F90ADB0043F896 /* CoreGraphics.framework */, + A5A4BE9C15F90ADB0043F896 /* SenTestingKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + A5A4BE8115F90ADB0043F896 /* HabraReader */ = { + isa = PBXGroup; + children = ( + A5A4BE8A15F90ADB0043F896 /* HRAppDelegate.h */, + A5A4BE8B15F90ADB0043F896 /* HRAppDelegate.m */, + A5A4BE8D15F90ADB0043F896 /* MainStoryboard_iPhone.storyboard */, + A5A4BE9015F90ADB0043F896 /* MainStoryboard_iPad.storyboard */, + A5E47765162CA2E3002CF89C /* HRStartupLoader.h */, + A5E47766162CA2E3002CF89C /* HRStartupLoader.m */, + A592200016775AC200E9A3DE /* HRGlagne.h */, + A592200116775AC200E9A3DE /* HRGlagne.m */, + A5921FFD16774BD000E9A3DE /* HRMultiFetchTableViewController.h */, + A5921FFE16774BD000E9A3DE /* HRMultiFetchTableViewController.m */, + A51689A9162B61520045EFDB /* HRPostViewer.h */, + A51689AA162B61530045EFDB /* HRPostViewer.m */, + A5D6D83916833B1200B2DE2E /* HRCommentsTableController.h */, + A5D6D83A16833B1200B2DE2E /* HRCommentsTableController.m */, + A5B165771624AD39008302C3 /* HRPostsTableViewController.h */, + A5B165781624AD39008302C3 /* HRPostsTableViewController.m */, + A5E75C1A1624651F0024C3C0 /* CoreDataTableViewController.h */, + A5E75C1B1624651F0024C3C0 /* CoreDataTableViewController.m */, + A56D81691624721100BD2159 /* HRHubTableViewController.h */, + A56D816A1624721200BD2159 /* HRHubTableViewController.m */, + A5B1656C1624911D008302C3 /* HRCompanyTableViewController.h */, + A5B1656D1624911D008302C3 /* HRCompanyTableViewController.m */, + A5BF3DFE1626026800754747 /* HRListOfGenericHubs.h */, + A5BF3DFF1626026800754747 /* HRListOfGenericHubs.m */, + A5EDBDF4167BAC32003A9665 /* Model */, + A5A4BE8215F90ADB0043F896 /* Supporting Files */, + ); + path = HabraReader; + sourceTree = ""; + }; + A5A4BE8215F90ADB0043F896 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + A503CE8C16679E02004E626E /* load.html */, + A5329BA11635EA980065CE4D /* habrahabr_01.png */, + A51689A7162B5BC20045EFDB /* habrahabr_02.png */, + A5329BA41635EACE0065CE4D /* habrahabr-iphone_02.png */, + A5E75C16162443D30024C3C0 /* Default-568h@2x.png */, + A5A4BE8315F90ADB0043F896 /* HabraReader-Info.plist */, + A5A4BE8415F90ADB0043F896 /* InfoPlist.strings */, + A5A4BE8715F90ADB0043F896 /* main.m */, + A5A4BE8915F90ADB0043F896 /* HabraReader-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + A5A4BEA215F90ADB0043F896 /* HabraReaderTests */ = { + isa = PBXGroup; + children = ( + A5A4BEA815F90ADB0043F896 /* HabraReaderTests.h */, + A5A4BEA915F90ADB0043F896 /* HabraReaderTests.m */, + A5A4BEA315F90ADB0043F896 /* Supporting Files */, + ); + path = HabraReaderTests; + sourceTree = ""; + }; + A5A4BEA315F90ADB0043F896 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + A5A4BEA415F90ADB0043F896 /* HabraReaderTests-Info.plist */, + A5A4BEA515F90ADB0043F896 /* InfoPlist.strings */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + A5EDBDF4167BAC32003A9665 /* Model */ = { + isa = PBXGroup; + children = ( + A5E0FBF8167B073300A72897 /* HRModel.h */, + A5E0FBF9167B073300A72897 /* HRModel.m */, + A588919C165BA41C005C5FB0 /* HTMLParser.h */, + A588919D165BA41C005C5FB0 /* HTMLParser.m */, + A5E755A21652E237008C8D57 /* NSString+Tags.h */, + A5E755A31652E237008C8D57 /* NSString+Tags.m */, + A5A4BEB315F911EC0043F896 /* NSMutableString+RemoveTag.h */, + A5A4BEB415F911EC0043F896 /* NSMutableString+RemoveTag.m */, + A54480131680A912002D570A /* HRCommentsParser.h */, + A54480141680A912002D570A /* HRCommentsParser.m */, + A56D816216246B2600BD2159 /* HRPDataLoader.h */, + A56D816316246B2600BD2159 /* HRPDataLoader.m */, + A5E4BFEE164FCC4C00B04847 /* HRRSSParser.h */, + A5E4BFEF164FCC4C00B04847 /* HRRSSParser.m */, + A503CE8816678ABB004E626E /* HRPostLoader.h */, + A503CE8916678ABB004E626E /* HRPostLoader.m */, + A56D8130162467AE00BD2159 /* HabraReader_Prototype.xcdatamodeld */, + A56D815516246A9500BD2159 /* CoreData Categories */, + A56D815416246A7900BD2159 /* CoreData Classes */, + ); + name = Model; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + A5A4BE7615F90ADB0043F896 /* HabraReader */ = { + isa = PBXNativeTarget; + buildConfigurationList = A5A4BEAD15F90ADB0043F896 /* Build configuration list for PBXNativeTarget "HabraReader" */; + buildPhases = ( + A5A4BE7315F90ADB0043F896 /* Sources */, + A5A4BE7415F90ADB0043F896 /* Frameworks */, + A5A4BE7515F90ADB0043F896 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = HabraReader; + productName = HabraReader; + productReference = A5A4BE7715F90ADB0043F896 /* HabraReader.app */; + productType = "com.apple.product-type.application"; + }; + A5A4BE9A15F90ADB0043F896 /* HabraReaderTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = A5A4BEB015F90ADB0043F896 /* Build configuration list for PBXNativeTarget "HabraReaderTests" */; + buildPhases = ( + A5A4BE9615F90ADB0043F896 /* Sources */, + A5A4BE9715F90ADB0043F896 /* Frameworks */, + A5A4BE9815F90ADB0043F896 /* Resources */, + A5A4BE9915F90ADB0043F896 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + A5A4BEA115F90ADB0043F896 /* PBXTargetDependency */, + ); + name = HabraReaderTests; + productName = HabraReaderTests; + productReference = A5A4BE9B15F90ADB0043F896 /* HabraReaderTests.octest */; + productType = "com.apple.product-type.bundle"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + A5A4BE6E15F90ADB0043F896 /* Project object */ = { + isa = PBXProject; + attributes = { + CLASSPREFIX = HR; + LastUpgradeCheck = 0440; + ORGANIZATIONNAME = "Sergey Starukhin"; + }; + buildConfigurationList = A5A4BE7115F90ADB0043F896 /* Build configuration list for PBXProject "HabraReader" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = A5A4BE6C15F90ADB0043F896; + productRefGroup = A5A4BE7815F90ADB0043F896 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + A5A4BE7615F90ADB0043F896 /* HabraReader */, + A5A4BE9A15F90ADB0043F896 /* HabraReaderTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + A5A4BE7515F90ADB0043F896 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A5A4BE8615F90ADB0043F896 /* InfoPlist.strings in Resources */, + A5A4BE8F15F90ADB0043F896 /* MainStoryboard_iPhone.storyboard in Resources */, + A5A4BE9215F90ADB0043F896 /* MainStoryboard_iPad.storyboard in Resources */, + A5E75C17162443D30024C3C0 /* Default-568h@2x.png in Resources */, + A51689A8162B5BC20045EFDB /* habrahabr_02.png in Resources */, + A5329BA21635EA980065CE4D /* habrahabr_01.png in Resources */, + A5329BA51635EACE0065CE4D /* habrahabr-iphone_02.png in Resources */, + A503CE8D16679E02004E626E /* load.html in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A5A4BE9815F90ADB0043F896 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A5A4BEA715F90ADB0043F896 /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + A5A4BE9915F90ADB0043F896 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + A5A4BE7315F90ADB0043F896 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A5A4BE8815F90ADB0043F896 /* main.m in Sources */, + A5A4BE8C15F90ADB0043F896 /* HRAppDelegate.m in Sources */, + A5A4BEB515F911EC0043F896 /* NSMutableString+RemoveTag.m in Sources */, + A5E75C1C1624651F0024C3C0 /* CoreDataTableViewController.m in Sources */, + A56D8132162467AE00BD2159 /* HabraReader_Prototype.xcdatamodeld in Sources */, + A56D8135162468F000BD2159 /* GenericHub.m in Sources */, + A56D813B162468F000BD2159 /* Company.m in Sources */, + A56D813E162468F000BD2159 /* Tag.m in Sources */, + A56D8141162468F000BD2159 /* Message.m in Sources */, + A56D8144162468F100BD2159 /* Hub.m in Sources */, + A56D814A162468F100BD2159 /* Author.m in Sources */, + A56D814D1624693800BD2159 /* Comment.m in Sources */, + A56D815E16246AEF00BD2159 /* Author+Create.m in Sources */, + A56D815F16246AEF00BD2159 /* Company+Create.m in Sources */, + A56D816016246AEF00BD2159 /* Hub+Create.m in Sources */, + A56D816116246AEF00BD2159 /* Post+Create.m in Sources */, + A56D816416246B2600BD2159 /* HRPDataLoader.m in Sources */, + A56D816B1624721200BD2159 /* HRHubTableViewController.m in Sources */, + A5B1656E1624911D008302C3 /* HRCompanyTableViewController.m in Sources */, + A5B165791624AD39008302C3 /* HRPostsTableViewController.m in Sources */, + A5BF3E001626026800754747 /* HRListOfGenericHubs.m in Sources */, + A51689A6162B58630045EFDB /* Post.m in Sources */, + A51689AB162B61540045EFDB /* HRPostViewer.m in Sources */, + A5E47767162CA2E3002CF89C /* HRStartupLoader.m in Sources */, + A5E4BFF0164FCC4C00B04847 /* HRRSSParser.m in Sources */, + A5E755A41652E237008C8D57 /* NSString+Tags.m in Sources */, + A588919E165BA41C005C5FB0 /* HTMLParser.m in Sources */, + A503CE8A16678ABB004E626E /* HRPostLoader.m in Sources */, + A5921FFF16774BD000E9A3DE /* HRMultiFetchTableViewController.m in Sources */, + A592200216775AC200E9A3DE /* HRGlagne.m in Sources */, + A5E0FBFA167B073300A72897 /* HRModel.m in Sources */, + A54480151680A912002D570A /* HRCommentsParser.m in Sources */, + A5D6D83B16833B1200B2DE2E /* HRCommentsTableController.m in Sources */, + A53F8B56168626DD0043E244 /* Message+Count.m in Sources */, + A53F8B5C168627770043E244 /* Comment+Description.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A5A4BE9615F90ADB0043F896 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A5A4BEAA15F90ADB0043F896 /* HabraReaderTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + A5A4BEA115F90ADB0043F896 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = A5A4BE7615F90ADB0043F896 /* HabraReader */; + targetProxy = A5A4BEA015F90ADB0043F896 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + A5A4BE8415F90ADB0043F896 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + A5A4BE8515F90ADB0043F896 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + A5A4BE8D15F90ADB0043F896 /* MainStoryboard_iPhone.storyboard */ = { + isa = PBXVariantGroup; + children = ( + A5A4BE8E15F90ADB0043F896 /* en */, + ); + name = MainStoryboard_iPhone.storyboard; + sourceTree = ""; + }; + A5A4BE9015F90ADB0043F896 /* MainStoryboard_iPad.storyboard */ = { + isa = PBXVariantGroup; + children = ( + A5A4BE9115F90ADB0043F896 /* en */, + ); + name = MainStoryboard_iPad.storyboard; + sourceTree = ""; + }; + A5A4BEA515F90ADB0043F896 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + A5A4BEA615F90ADB0043F896 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + A5A4BEAB15F90ADB0043F896 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 5.1; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + A5A4BEAC15F90ADB0043F896 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 5.1; + OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + A5A4BEAE15F90ADB0043F896 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "HabraReader/HabraReader-Prefix.pch"; + INFOPLIST_FILE = "HabraReader/HabraReader-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 5.0; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + A5A4BEAF15F90ADB0043F896 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "HabraReader/HabraReader-Prefix.pch"; + INFOPLIST_FILE = "HabraReader/HabraReader-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 5.0; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; + A5A4BEB115F90ADB0043F896 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/HabraReader.app/HabraReader"; + FRAMEWORK_SEARCH_PATHS = ( + "\"$(SDKROOT)/Developer/Library/Frameworks\"", + "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "HabraReader/HabraReader-Prefix.pch"; + INFOPLIST_FILE = "HabraReaderTests/HabraReaderTests-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUNDLE_LOADER)"; + WRAPPER_EXTENSION = octest; + }; + name = Debug; + }; + A5A4BEB215F90ADB0043F896 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/HabraReader.app/HabraReader"; + FRAMEWORK_SEARCH_PATHS = ( + "\"$(SDKROOT)/Developer/Library/Frameworks\"", + "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "HabraReader/HabraReader-Prefix.pch"; + INFOPLIST_FILE = "HabraReaderTests/HabraReaderTests-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUNDLE_LOADER)"; + WRAPPER_EXTENSION = octest; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + A5A4BE7115F90ADB0043F896 /* Build configuration list for PBXProject "HabraReader" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A5A4BEAB15F90ADB0043F896 /* Debug */, + A5A4BEAC15F90ADB0043F896 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A5A4BEAD15F90ADB0043F896 /* Build configuration list for PBXNativeTarget "HabraReader" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A5A4BEAE15F90ADB0043F896 /* Debug */, + A5A4BEAF15F90ADB0043F896 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A5A4BEB015F90ADB0043F896 /* Build configuration list for PBXNativeTarget "HabraReaderTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A5A4BEB115F90ADB0043F896 /* Debug */, + A5A4BEB215F90ADB0043F896 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCVersionGroup section */ + A56D8130162467AE00BD2159 /* HabraReader_Prototype.xcdatamodeld */ = { + isa = XCVersionGroup; + children = ( + A56D8131162467AE00BD2159 /* HabraReader_Prototype.xcdatamodel */, + ); + currentVersion = A56D8131162467AE00BD2159 /* HabraReader_Prototype.xcdatamodel */; + path = HabraReader_Prototype.xcdatamodeld; + sourceTree = ""; + versionGroupType = wrapper.xcdatamodel; + }; +/* End XCVersionGroup section */ + }; + rootObject = A5A4BE6E15F90ADB0043F896 /* Project object */; +} diff --git a/HabraReader/Author+Create.h b/HabraReader/Author+Create.h new file mode 100644 index 0000000..bf61696 --- /dev/null +++ b/HabraReader/Author+Create.h @@ -0,0 +1,17 @@ +// +// Author+Create.h +// HabraReader Prototype +// +// Created by Sergey on 04.10.12. +// Copyright (c) 2012 Sergey Starukhin. All rights reserved. +// + +#import "Author.h" + +@interface Author (Create) + +- (NSString *)description; + ++ (Author *)authorWithName:(NSString *)name inManagedObjectContext:(NSManagedObjectContext *)context; + +@end diff --git a/HabraReader/Author+Create.m b/HabraReader/Author+Create.m new file mode 100644 index 0000000..45a1ac1 --- /dev/null +++ b/HabraReader/Author+Create.m @@ -0,0 +1,41 @@ +// +// Author+Create.m +// HabraReader Prototype +// +// Created by Sergey on 04.10.12. +// Copyright (c) 2012 Sergey Starukhin. All rights reserved. +// + +#import "Author+Create.h" + +@implementation Author (Create) + +- (NSString *)description { + return self.nickName; +} + ++ (Author *)authorWithName:(NSString *)name inManagedObjectContext:(NSManagedObjectContext *)context { + + Author *author = nil; + + NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Author"]; + request.predicate = [NSPredicate predicateWithFormat:@"nickName = %@", name]; + NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"nickName" ascending:YES]; + request.sortDescriptors = @[sortDescriptor]; + + NSError *error = nil; + NSArray *authors = [context executeFetchRequest:request error:&error]; + + if (!authors || ([authors count] > 1)) { + // TODO: handle error + } else if (![authors count]) { + author = [NSEntityDescription insertNewObjectForEntityForName:@"Author" inManagedObjectContext:context]; + author.nickName = name; + } else { + author = [authors lastObject]; + } + + return author; +} + +@end diff --git a/HabraReader/Author.h b/HabraReader/Author.h new file mode 100644 index 0000000..7db8a52 --- /dev/null +++ b/HabraReader/Author.h @@ -0,0 +1,33 @@ +// +// Author.h +// HabraReader +// +// Created by Sergey on 09.10.12. +// Copyright (c) 2012 Sergey Starukhin. All rights reserved. +// + +#import +#import + +@class Comment, Post; + +@interface Author : NSManagedObject + +@property (nonatomic, retain) NSString * nickName; +@property (nonatomic, retain) NSSet *comments; +@property (nonatomic, retain) NSSet *posts; +@end + +@interface Author (CoreDataGeneratedAccessors) + +- (void)addCommentsObject:(Comment *)value; +- (void)removeCommentsObject:(Comment *)value; +- (void)addComments:(NSSet *)values; +- (void)removeComments:(NSSet *)values; + +- (void)addPostsObject:(Post *)value; +- (void)removePostsObject:(Post *)value; +- (void)addPosts:(NSSet *)values; +- (void)removePosts:(NSSet *)values; + +@end diff --git a/HabraReader/Author.m b/HabraReader/Author.m new file mode 100644 index 0000000..4b0fb85 --- /dev/null +++ b/HabraReader/Author.m @@ -0,0 +1,20 @@ +// +// Author.m +// HabraReader +// +// Created by Sergey on 09.10.12. +// Copyright (c) 2012 Sergey Starukhin. All rights reserved. +// + +#import "Author.h" +#import "Comment.h" +#import "Post.h" + + +@implementation Author + +@dynamic nickName; +@dynamic comments; +@dynamic posts; + +@end diff --git a/HabraReader/Comment+Description.h b/HabraReader/Comment+Description.h new file mode 100644 index 0000000..0f6e2f6 --- /dev/null +++ b/HabraReader/Comment+Description.h @@ -0,0 +1,15 @@ +// +// Comment+Description.h +// HabraReader +// +// Created by Sergey Starukhin on 22.12.12. +// Copyright (c) 2012 Sergey Starukhin. All rights reserved. +// + +#import "Comment.h" + +@interface Comment (Description) + +- (NSString *)description; + +@end diff --git a/HabraReader/Comment+Description.m b/HabraReader/Comment+Description.m new file mode 100644 index 0000000..6cfc860 --- /dev/null +++ b/HabraReader/Comment+Description.m @@ -0,0 +1,17 @@ +// +// Comment+Description.m +// HabraReader +// +// Created by Sergey Starukhin on 22.12.12. +// Copyright (c) 2012 Sergey Starukhin. All rights reserved. +// + +#import "Comment+Description.h" + +@implementation Comment (Description) + +- (NSString *)description { + return [NSString stringWithFormat:@"%@, %@\n\n%@", self.author, self.publicationDate, self.content]; +} + +@end diff --git a/HabraReader/Comment.h b/HabraReader/Comment.h new file mode 100644 index 0000000..03ccd24 --- /dev/null +++ b/HabraReader/Comment.h @@ -0,0 +1,21 @@ +// +// Comment.h +// HabraReader +// +// Created by Sergey on 09.10.12. +// Copyright (c) 2012 Sergey Starukhin. All rights reserved. +// + +#import +#import +#import "Message.h" + +@class Author, Message; + +@interface Comment : Message + +@property (nonatomic) BOOL isRead; +@property (nonatomic, retain) Author *author; +@property (nonatomic, retain) Message *replyTo; + +@end diff --git a/HabraReader/Comment.m b/HabraReader/Comment.m new file mode 100644 index 0000000..f29ca78 --- /dev/null +++ b/HabraReader/Comment.m @@ -0,0 +1,20 @@ +// +// Comment.m +// HabraReader +// +// Created by Sergey on 09.10.12. +// Copyright (c) 2012 Sergey Starukhin. All rights reserved. +// + +#import "Comment.h" +#import "Author.h" +#import "Message.h" + + +@implementation Comment + +@dynamic isRead; +@dynamic author; +@dynamic replyTo; + +@end diff --git a/HabraReader/Company+Create.h b/HabraReader/Company+Create.h new file mode 100644 index 0000000..39c93e3 --- /dev/null +++ b/HabraReader/Company+Create.h @@ -0,0 +1,15 @@ +// +// Company+Create.h +// HabraReader Prototype +// +// Created by Sergey on 04.10.12. +// Copyright (c) 2012 Sergey Starukhin. All rights reserved. +// + +#import "Company.h" + +@interface Company (Create) + ++ (Company *)companyWithName:(NSString *)name inManagedObjectContext:(NSManagedObjectContext *)context; + +@end diff --git a/HabraReader/Company+Create.m b/HabraReader/Company+Create.m new file mode 100644 index 0000000..decabba --- /dev/null +++ b/HabraReader/Company+Create.m @@ -0,0 +1,37 @@ +// +// Company+Create.m +// HabraReader Prototype +// +// Created by Sergey on 04.10.12. +// Copyright (c) 2012 Sergey Starukhin. All rights reserved. +// + +#import "Company+Create.h" + +@implementation Company (Create) + ++ (Company *)companyWithName:(NSString *)name inManagedObjectContext:(NSManagedObjectContext *)context { + + Company *company = nil; + + NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass(self)]; + request.predicate = [NSPredicate predicateWithFormat:@"name = %@", name]; + NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]; + request.sortDescriptors = @[sortDescriptor]; + + NSError *error = nil; + NSArray *companies = [context executeFetchRequest:request error:&error]; + + if (!companies || ([companies count] > 1)) { + // TODO: handle error + } else if (![companies count]) { + company = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass(self) inManagedObjectContext:context]; + company.name = name; + } else { + company = [companies lastObject]; + } + + return company; +} + +@end diff --git a/HabraReader/Company.h b/HabraReader/Company.h new file mode 100644 index 0000000..7bc4ea4 --- /dev/null +++ b/HabraReader/Company.h @@ -0,0 +1,17 @@ +// +// Company.h +// HabraReader +// +// Created by Sergey on 09.10.12. +// Copyright (c) 2012 Sergey Starukhin. All rights reserved. +// + +#import +#import +#import "GenericHub.h" + + +@interface Company : GenericHub + + +@end diff --git a/HabraReader/Company.m b/HabraReader/Company.m new file mode 100644 index 0000000..6e40d88 --- /dev/null +++ b/HabraReader/Company.m @@ -0,0 +1,15 @@ +// +// Company.m +// HabraReader +// +// Created by Sergey on 09.10.12. +// Copyright (c) 2012 Sergey Starukhin. All rights reserved. +// + +#import "Company.h" + + +@implementation Company + + +@end diff --git a/HabraReader/CoreDataTableViewController.h b/HabraReader/CoreDataTableViewController.h new file mode 100644 index 0000000..0f138b4 --- /dev/null +++ b/HabraReader/CoreDataTableViewController.h @@ -0,0 +1,53 @@ +// +// CoreDataTableViewController.h +// +// Created for Stanford CS193p Fall 2011. +// Copyright 2011 Stanford University. All rights reserved. +// +// This class mostly just copies the code from NSFetchedResultsController's documentation page +// into a subclass of UITableViewController. +// +// Just subclass this and set the fetchedResultsController. +// The only UITableViewDataSource method you'll HAVE to implement is tableView:cellForRowAtIndexPath:. +// And you can use the NSFetchedResultsController method objectAtIndexPath: to do it. +// +// Remember that once you create an NSFetchedResultsController, you CANNOT modify its @propertys. +// If you want new fetch parameters (predicate, sorting, etc.), +// create a NEW NSFetchedResultsController and set this class's fetchedResultsController @property again. +// + +#import +#import + +@interface CoreDataTableViewController : UITableViewController + +// The controller (this class fetches nothing if this is not set). +@property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController; + +// Causes the fetchedResultsController to refetch the data. +// You almost certainly never need to call this. +// The NSFetchedResultsController class observes the context +// (so if the objects in the context change, you do not need to call performFetch +// since the NSFetchedResultsController will notice and update the table automatically). +// This will also automatically be called if you change the fetchedResultsController @property. +- (void)performFetch; + +// Turn this on before making any changes in the managed object context that +// are a one-for-one result of the user manipulating rows directly in the table view. +// Such changes cause the context to report them (after a brief delay), +// and normally our fetchedResultsController would then try to update the table, +// but that is unnecessary because the changes were made in the table already (by the user) +// so the fetchedResultsController has nothing to do and needs to ignore those reports. +// Turn this back off after the user has finished the change. +// Note that the effect of setting this to NO actually gets delayed slightly +// so as to ignore previously-posted, but not-yet-processed context-changed notifications, +// therefore it is fine to set this to YES at the beginning of, e.g., tableView:moveRowAtIndexPath:toIndexPath:, +// and then set it back to NO at the end of your implementation of that method. +// It is not necessary (in fact, not desirable) to set this during row deletion or insertion +// (but definitely for row moves). +@property (nonatomic) BOOL suspendAutomaticTrackingOfChangesInManagedObjectContext; + +// Set to YES to get some debugging output in the console. +@property BOOL debug; + +@end diff --git a/HabraReader/CoreDataTableViewController.m b/HabraReader/CoreDataTableViewController.m new file mode 100644 index 0000000..c0d579d --- /dev/null +++ b/HabraReader/CoreDataTableViewController.m @@ -0,0 +1,174 @@ +// +// CoreDataTableViewController.m +// +// Created for Stanford CS193p Fall 2011. +// Copyright 2011 Stanford University. All rights reserved. +// + +#import "CoreDataTableViewController.h" + +@interface CoreDataTableViewController() +@property (nonatomic) BOOL beganUpdates; +@end + +@implementation CoreDataTableViewController + +#pragma mark - Properties + +@synthesize fetchedResultsController = _fetchedResultsController; +@synthesize suspendAutomaticTrackingOfChangesInManagedObjectContext = _suspendAutomaticTrackingOfChangesInManagedObjectContext; +@synthesize debug = _debug; +@synthesize beganUpdates = _beganUpdates; + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + return YES; +} + +#pragma mark - Fetching + +- (void)performFetch +{ + if (self.fetchedResultsController) { + if (self.fetchedResultsController.fetchRequest.predicate) { + if (self.debug) NSLog(@"[%@ %@] fetching %@ with predicate: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), self.fetchedResultsController.fetchRequest.entityName, self.fetchedResultsController.fetchRequest.predicate); + } else { + if (self.debug) NSLog(@"[%@ %@] fetching all %@ (i.e., no predicate)", NSStringFromClass([self class]), NSStringFromSelector(_cmd), self.fetchedResultsController.fetchRequest.entityName); + } + NSError *error; + [self.fetchedResultsController performFetch:&error]; + if (error) NSLog(@"[%@ %@] %@ (%@)", NSStringFromClass([self class]), NSStringFromSelector(_cmd), [error localizedDescription], [error localizedFailureReason]); + } else { + if (self.debug) NSLog(@"[%@ %@] no NSFetchedResultsController (yet?)", NSStringFromClass([self class]), NSStringFromSelector(_cmd)); + } + [self.tableView reloadData]; +} + +- (void)setFetchedResultsController:(NSFetchedResultsController *)newfrc +{ + NSFetchedResultsController *oldfrc = _fetchedResultsController; + if (newfrc != oldfrc) { + _fetchedResultsController = newfrc; + newfrc.delegate = self; + if ((!self.title || [self.title isEqualToString:oldfrc.fetchRequest.entity.name]) && (!self.navigationController || !self.navigationItem.title)) { + self.title = newfrc.fetchRequest.entity.name; + } + if (newfrc) { + if (self.debug) NSLog(@"[%@ %@] %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), oldfrc ? @"updated" : @"set"); + [self performFetch]; + } else { + if (self.debug) NSLog(@"[%@ %@] reset to nil", NSStringFromClass([self class]), NSStringFromSelector(_cmd)); + [self.tableView reloadData]; + } + } +} + +#pragma mark - UITableViewDataSource + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +{ + return [[self.fetchedResultsController sections] count]; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ + return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects]; +} + +- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section +{ + return [[[self.fetchedResultsController sections] objectAtIndex:section] name]; +} + +- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index +{ + return [self.fetchedResultsController sectionForSectionIndexTitle:title atIndex:index]; +} + +- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView +{ + return [self.fetchedResultsController sectionIndexTitles]; +} + +#pragma mark - NSFetchedResultsControllerDelegate + +- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller +{ + if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext) { + [self.tableView beginUpdates]; + self.beganUpdates = YES; + } +} + +- (void)controller:(NSFetchedResultsController *)controller + didChangeSection:(id )sectionInfo + atIndex:(NSUInteger)sectionIndex + forChangeType:(NSFetchedResultsChangeType)type +{ + if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext) + { + switch(type) + { + case NSFetchedResultsChangeInsert: + [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; + break; + + case NSFetchedResultsChangeDelete: + [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; + break; + } + } +} + + +- (void)controller:(NSFetchedResultsController *)controller + didChangeObject:(id)anObject + atIndexPath:(NSIndexPath *)indexPath + forChangeType:(NSFetchedResultsChangeType)type + newIndexPath:(NSIndexPath *)newIndexPath +{ + if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext) + { + switch(type) + { + case NSFetchedResultsChangeInsert: + [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; + break; + + case NSFetchedResultsChangeDelete: + [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; + break; + + case NSFetchedResultsChangeUpdate: + [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; + break; + + case NSFetchedResultsChangeMove: + [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; + [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; + break; + } + } +} + +- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller +{ + if (self.beganUpdates) [self.tableView endUpdates]; +} + +- (void)endSuspensionOfUpdatesDueToContextChanges +{ + _suspendAutomaticTrackingOfChangesInManagedObjectContext = NO; +} + +- (void)setSuspendAutomaticTrackingOfChangesInManagedObjectContext:(BOOL)suspend +{ + if (suspend) { + _suspendAutomaticTrackingOfChangesInManagedObjectContext = YES; + } else { + [self performSelector:@selector(endSuspensionOfUpdatesDueToContextChanges) withObject:0 afterDelay:0]; + } +} + +@end + diff --git a/HabraReader/GenericHub.h b/HabraReader/GenericHub.h new file mode 100644 index 0000000..5b2349d --- /dev/null +++ b/HabraReader/GenericHub.h @@ -0,0 +1,28 @@ +// +// GenericHub.h +// HabraReader +// +// Created by Sergey on 09.10.12. +// Copyright (c) 2012 Sergey Starukhin. All rights reserved. +// + +#import +#import + +@class Post; + +@interface GenericHub : NSManagedObject + +@property (nonatomic, retain) NSString * name; +@property (nonatomic, retain) NSString * title; +@property (nonatomic, retain) NSSet *posts; +@end + +@interface GenericHub (CoreDataGeneratedAccessors) + +- (void)addPostsObject:(Post *)value; +- (void)removePostsObject:(Post *)value; +- (void)addPosts:(NSSet *)values; +- (void)removePosts:(NSSet *)values; + +@end diff --git a/HabraReader/GenericHub.m b/HabraReader/GenericHub.m new file mode 100644 index 0000000..4819d59 --- /dev/null +++ b/HabraReader/GenericHub.m @@ -0,0 +1,19 @@ +// +// GenericHub.m +// HabraReader +// +// Created by Sergey on 09.10.12. +// Copyright (c) 2012 Sergey Starukhin. All rights reserved. +// + +#import "GenericHub.h" +#import "Post.h" + + +@implementation GenericHub + +@dynamic name; +@dynamic title; +@dynamic posts; + +@end diff --git a/HabraReader/HRAppDelegate.h b/HabraReader/HRAppDelegate.h new file mode 100644 index 0000000..4017f73 --- /dev/null +++ b/HabraReader/HRAppDelegate.h @@ -0,0 +1,18 @@ +// +// HRAppDelegate.h +// HabraReader +// +// Created by Sergey Starukhin on 06.09.12. +// Copyright (c) 2012 Sergey Starukhin. All rights reserved. +// + +#import +#import "HRModel.h" + +@interface HRAppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + +@property (readonly, strong, nonatomic) HRModel *model; + +@end diff --git a/HabraReader/HRAppDelegate.m b/HabraReader/HRAppDelegate.m new file mode 100644 index 0000000..73d1811 --- /dev/null +++ b/HabraReader/HRAppDelegate.m @@ -0,0 +1,53 @@ +// +// HRAppDelegate.m +// HabraReader +// +// Created by Sergey Starukhin on 06.09.12. +// Copyright (c) 2012 Sergey Starukhin. All rights reserved. +// + +#import "HRAppDelegate.h" + +@interface HRAppDelegate () +@property (strong, nonatomic) HRModel *model; +@end + +@implementation HRAppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + // Override point for customization after application launch. + self.model = [[HRModel alloc] init]; + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application +{ + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + [self.model saveContext]; +} + +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application +{ + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application +{ + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + [self.model saveContext]; +} + +@end diff --git a/HabraReader/HRCommentsParser.h b/HabraReader/HRCommentsParser.h new file mode 100644 index 0000000..eee96a4 --- /dev/null +++ b/HabraReader/HRCommentsParser.h @@ -0,0 +1,17 @@ +// +// HRCommentsParser.h +// HabraReader +// +// Created by Sergey Starukhin on 18.12.12. +// Copyright (c) 2012 Sergey Starukhin. All rights reserved. +// + +#import + +@class Post; + +@interface HRCommentsParser : NSObject + ++ (void)parseCommentsForPost:(Post *)post fromString:(NSString *)comments; + +@end diff --git a/HabraReader/HRCommentsParser.m b/HabraReader/HRCommentsParser.m new file mode 100644 index 0000000..dd9ccbb --- /dev/null +++ b/HabraReader/HRCommentsParser.m @@ -0,0 +1,196 @@ +// +// HRCommentsParser.m +// HabraReader +// +// Created by Sergey Starukhin on 18.12.12. +// Copyright (c) 2012 Sergey Starukhin. All rights reserved. +// + +#import "HRCommentsParser.h" +#import "HTMLParser.h" +#import "Post+Create.h" +#import "Author+Create.h" +#import "Comment.h" + +enum HRParsingState { + Stop = 0, + Parsing = 1, + CommentBegin = 2, + WaitForAuthorAndDate = 3, + WaitContent= 4 +}; + +@interface HRCommentsParser () { + NSUInteger state; + NSUInteger currentLevel; + NSUInteger commentLevel; + NSMutableString *currentElement; + Comment *currentComment; + Comment *lastComment; +} + +@property (nonatomic, strong) Post *postForComments; + +@end + +@implementation HRCommentsParser + ++ (void)parseCommentsForPost:(Post *)post fromString:(NSString *)comments { + HRCommentsParser *parser = [[HRCommentsParser alloc] init]; + parser.postForComments = post; + HTMLParser *htmlParser = [[HTMLParser alloc] initWithString:comments]; + htmlParser.delegate = parser; + [htmlParser parse]; +} + +#pragma mark - HTMLParserDelegate protocol implementation + +// документ начал парситься +- (void)parserDidStartDocument:(HTMLParser *)parser { + // NSLog(@"%s",__PRETTY_FUNCTION__); + state = Stop; +} + +// парсинг окончен +- (void)parserDidEndDocument:(HTMLParser *)parser { + // NSLog(@"%s",__PRETTY_FUNCTION__); +} + +// если произошла ошибка парсинга +-(void) parser:(HTMLParser *)parser parseErrorOccurred:(NSError *)parseError { + //NSLog(@"%s error %@ at string:%d",__PRETTY_FUNCTION__,[parseError localizedDescription],[parser lineNumber]); +} + +// встретили новый элемент +- (void)parser:(HTMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict { + switch (state) { + case Stop: + // ждем начала элемента