Compare commits
2 Commits
master
...
feature/im
| Author | SHA1 | Date |
|---|---|---|
|
|
39e789c3ae | |
|
|
a885479a2c |
1
Cartfile
1
Cartfile
|
|
@ -2,3 +2,4 @@ github "CocoaLumberjack/CocoaLumberjack" ~> 3.0.0
|
|||
github "ReactiveX/RxSwift" "3.0.1"
|
||||
github "RxSwiftCommunity/RxAlamofire" "3.0.1"
|
||||
github "Hearst-DD/ObjectMapper" ~> 2.1
|
||||
github "Alamofire/AlamofireImage" ~> 3.2
|
||||
|
|
|
|||
|
|
@ -2,4 +2,5 @@ github "Alamofire/Alamofire" "4.2.0"
|
|||
github "CocoaLumberjack/CocoaLumberjack" "3.0.0"
|
||||
github "Hearst-DD/ObjectMapper" "2.2.1"
|
||||
github "ReactiveX/RxSwift" "3.0.1"
|
||||
github "Alamofire/AlamofireImage" "3.2.0"
|
||||
github "RxSwiftCommunity/RxAlamofire" "3.0.1"
|
||||
|
|
|
|||
|
|
@ -7,6 +7,26 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
24F5EFDA1DEA148A00B9ADB6 /* ObservableType+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5EFD91DEA148A00B9ADB6 /* ObservableType+Extensions.swift */; };
|
||||
24F5EFE11DEA187D00B9ADB6 /* ImageLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5EFE01DEA187D00B9ADB6 /* ImageLoader.swift */; };
|
||||
24F5EFE41DEA18F300B9ADB6 /* MemoryStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5EFE31DEA18F300B9ADB6 /* MemoryStore.swift */; };
|
||||
24F5EFEA1DEA191A00B9ADB6 /* Sync.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5EFE91DEA191A00B9ADB6 /* Sync.swift */; };
|
||||
24F5EFF41DEA199300B9ADB6 /* ImageOperationWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5EFEE1DEA199300B9ADB6 /* ImageOperationWrapper.swift */; };
|
||||
24F5EFF51DEA199300B9ADB6 /* ImageOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5EFEF1DEA199300B9ADB6 /* ImageOperation.swift */; };
|
||||
24F5EFF61DEA199300B9ADB6 /* ImageOperationPerformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5EFF01DEA199300B9ADB6 /* ImageOperationPerformer.swift */; };
|
||||
24F5EFF71DEA199300B9ADB6 /* ImageLoadingOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5EFF11DEA199300B9ADB6 /* ImageLoadingOperation.swift */; };
|
||||
24F5EFF81DEA199300B9ADB6 /* ImageFakeOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5EFF21DEA199300B9ADB6 /* ImageFakeOperation.swift */; };
|
||||
24F5EFF91DEA199300B9ADB6 /* ImageStartOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5EFF31DEA199300B9ADB6 /* ImageStartOperation.swift */; };
|
||||
24F5EFFE1DEA1A1500B9ADB6 /* ImageSourceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5EFFA1DEA1A1500B9ADB6 /* ImageSourceType.swift */; };
|
||||
24F5F0011DEA1A1500B9ADB6 /* NetworkImageSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5EFFD1DEA1A1500B9ADB6 /* NetworkImageSource.swift */; };
|
||||
24F5F0081DEA1A1F00B9ADB6 /* ImagePluginOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5F0021DEA1A1F00B9ADB6 /* ImagePluginOperation.swift */; };
|
||||
24F5F0091DEA1A1F00B9ADB6 /* ImagePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5F0031DEA1A1F00B9ADB6 /* ImagePlugin.swift */; };
|
||||
24F5F00A1DEA1A1F00B9ADB6 /* ImageResizingPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5F0041DEA1A1F00B9ADB6 /* ImageResizingPlugin.swift */; };
|
||||
24F5F00B1DEA1A1F00B9ADB6 /* ImageRoundingPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5F0051DEA1A1F00B9ADB6 /* ImageRoundingPlugin.swift */; };
|
||||
24F5F00C1DEA1A1F00B9ADB6 /* ImageFilteringPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5F0061DEA1A1F00B9ADB6 /* ImageFilteringPlugin.swift */; };
|
||||
24F5F00D1DEA1A1F00B9ADB6 /* ImageBluringPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5F0071DEA1A1F00B9ADB6 /* ImageBluringPlugin.swift */; };
|
||||
24F5F00F1DEA228F00B9ADB6 /* AbstractMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5F00E1DEA228F00B9ADB6 /* AbstractMethod.swift */; };
|
||||
24F5F0121DEA249900B9ADB6 /* UIImageView+ImageLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5F0111DEA249900B9ADB6 /* UIImageView+ImageLoader.swift */; };
|
||||
78011A641D47ABC500EA16A2 /* UIView+DefaultReuseIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78011A631D47ABC500EA16A2 /* UIView+DefaultReuseIdentifier.swift */; };
|
||||
78011AB31D48B53600EA16A2 /* ApiRequestParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78011AB21D48B53600EA16A2 /* ApiRequestParameters.swift */; };
|
||||
780D23431DA412470084620D /* CGImage+Alpha.swift in Sources */ = {isa = PBXBuildFile; fileRef = 780D23421DA412470084620D /* CGImage+Alpha.swift */; };
|
||||
|
|
@ -75,6 +95,26 @@
|
|||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
24F5EFD91DEA148A00B9ADB6 /* ObservableType+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ObservableType+Extensions.swift"; sourceTree = "<group>"; };
|
||||
24F5EFE01DEA187D00B9ADB6 /* ImageLoader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageLoader.swift; sourceTree = "<group>"; };
|
||||
24F5EFE31DEA18F300B9ADB6 /* MemoryStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MemoryStore.swift; sourceTree = "<group>"; };
|
||||
24F5EFE91DEA191A00B9ADB6 /* Sync.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Sync.swift; sourceTree = "<group>"; };
|
||||
24F5EFEE1DEA199300B9ADB6 /* ImageOperationWrapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageOperationWrapper.swift; sourceTree = "<group>"; };
|
||||
24F5EFEF1DEA199300B9ADB6 /* ImageOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageOperation.swift; sourceTree = "<group>"; };
|
||||
24F5EFF01DEA199300B9ADB6 /* ImageOperationPerformer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageOperationPerformer.swift; sourceTree = "<group>"; };
|
||||
24F5EFF11DEA199300B9ADB6 /* ImageLoadingOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageLoadingOperation.swift; sourceTree = "<group>"; };
|
||||
24F5EFF21DEA199300B9ADB6 /* ImageFakeOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageFakeOperation.swift; sourceTree = "<group>"; };
|
||||
24F5EFF31DEA199300B9ADB6 /* ImageStartOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageStartOperation.swift; sourceTree = "<group>"; };
|
||||
24F5EFFA1DEA1A1500B9ADB6 /* ImageSourceType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageSourceType.swift; sourceTree = "<group>"; };
|
||||
24F5EFFD1DEA1A1500B9ADB6 /* NetworkImageSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkImageSource.swift; sourceTree = "<group>"; };
|
||||
24F5F0021DEA1A1F00B9ADB6 /* ImagePluginOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImagePluginOperation.swift; sourceTree = "<group>"; };
|
||||
24F5F0031DEA1A1F00B9ADB6 /* ImagePlugin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImagePlugin.swift; sourceTree = "<group>"; };
|
||||
24F5F0041DEA1A1F00B9ADB6 /* ImageResizingPlugin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageResizingPlugin.swift; sourceTree = "<group>"; };
|
||||
24F5F0051DEA1A1F00B9ADB6 /* ImageRoundingPlugin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageRoundingPlugin.swift; sourceTree = "<group>"; };
|
||||
24F5F0061DEA1A1F00B9ADB6 /* ImageFilteringPlugin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageFilteringPlugin.swift; sourceTree = "<group>"; };
|
||||
24F5F0071DEA1A1F00B9ADB6 /* ImageBluringPlugin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageBluringPlugin.swift; sourceTree = "<group>"; };
|
||||
24F5F00E1DEA228F00B9ADB6 /* AbstractMethod.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AbstractMethod.swift; sourceTree = "<group>"; };
|
||||
24F5F0111DEA249900B9ADB6 /* UIImageView+ImageLoader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImageView+ImageLoader.swift"; sourceTree = "<group>"; };
|
||||
78011A631D47ABC500EA16A2 /* UIView+DefaultReuseIdentifier.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+DefaultReuseIdentifier.swift"; sourceTree = "<group>"; };
|
||||
78011AB21D48B53600EA16A2 /* ApiRequestParameters.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApiRequestParameters.swift; sourceTree = "<group>"; };
|
||||
780D23421DA412470084620D /* CGImage+Alpha.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CGImage+Alpha.swift"; sourceTree = "<group>"; };
|
||||
|
|
@ -173,6 +213,95 @@
|
|||
path = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
24F5EFCA1DEA0F3200B9ADB6 /* ImageLoader */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
24F5F0101DEA23E200B9ADB6 /* UIImageView */,
|
||||
24F5EFEB1DEA197400B9ADB6 /* ImageOperation */,
|
||||
24F5EFEC1DEA197400B9ADB6 /* ImagePlugin */,
|
||||
24F5EFED1DEA197400B9ADB6 /* ImageSource */,
|
||||
24F5EFE01DEA187D00B9ADB6 /* ImageLoader.swift */,
|
||||
);
|
||||
path = ImageLoader;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
24F5EFD81DEA144100B9ADB6 /* Rx */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
24F5EFD91DEA148A00B9ADB6 /* ObservableType+Extensions.swift */,
|
||||
);
|
||||
path = Rx;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
24F5EFDB1DEA176500B9ADB6 /* Helpers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
24F5EFE21DEA18F300B9ADB6 /* MemoryStore */,
|
||||
24F5EFE81DEA191A00B9ADB6 /* Sync */,
|
||||
);
|
||||
path = Helpers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
24F5EFE21DEA18F300B9ADB6 /* MemoryStore */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
24F5EFE31DEA18F300B9ADB6 /* MemoryStore.swift */,
|
||||
);
|
||||
path = MemoryStore;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
24F5EFE81DEA191A00B9ADB6 /* Sync */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
24F5EFE91DEA191A00B9ADB6 /* Sync.swift */,
|
||||
);
|
||||
path = Sync;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
24F5EFEB1DEA197400B9ADB6 /* ImageOperation */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
24F5EFEF1DEA199300B9ADB6 /* ImageOperation.swift */,
|
||||
24F5EFEE1DEA199300B9ADB6 /* ImageOperationWrapper.swift */,
|
||||
24F5EFF01DEA199300B9ADB6 /* ImageOperationPerformer.swift */,
|
||||
24F5EFF11DEA199300B9ADB6 /* ImageLoadingOperation.swift */,
|
||||
24F5EFF21DEA199300B9ADB6 /* ImageFakeOperation.swift */,
|
||||
24F5EFF31DEA199300B9ADB6 /* ImageStartOperation.swift */,
|
||||
);
|
||||
path = ImageOperation;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
24F5EFEC1DEA197400B9ADB6 /* ImagePlugin */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
24F5F0021DEA1A1F00B9ADB6 /* ImagePluginOperation.swift */,
|
||||
24F5F0031DEA1A1F00B9ADB6 /* ImagePlugin.swift */,
|
||||
24F5F0041DEA1A1F00B9ADB6 /* ImageResizingPlugin.swift */,
|
||||
24F5F0051DEA1A1F00B9ADB6 /* ImageRoundingPlugin.swift */,
|
||||
24F5F0061DEA1A1F00B9ADB6 /* ImageFilteringPlugin.swift */,
|
||||
24F5F0071DEA1A1F00B9ADB6 /* ImageBluringPlugin.swift */,
|
||||
);
|
||||
path = ImagePlugin;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
24F5EFED1DEA197400B9ADB6 /* ImageSource */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
24F5EFFA1DEA1A1500B9ADB6 /* ImageSourceType.swift */,
|
||||
24F5EFFD1DEA1A1500B9ADB6 /* NetworkImageSource.swift */,
|
||||
);
|
||||
path = ImageSource;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
24F5F0101DEA23E200B9ADB6 /* UIImageView */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
24F5F0111DEA249900B9ADB6 /* UIImageView+ImageLoader.swift */,
|
||||
);
|
||||
name = UIImageView;
|
||||
path = "UIImageView+Loader";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
78011A651D47AF3000EA16A2 /* Enums */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -284,6 +413,7 @@
|
|||
children = (
|
||||
78B0FC7B1C6B2BAE00358B64 /* Logging */,
|
||||
78753E2A1DE58BED006BC0FB /* Cursors */,
|
||||
24F5EFCA1DEA0F3200B9ADB6 /* ImageLoader */,
|
||||
);
|
||||
path = Classes;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -342,6 +472,7 @@
|
|||
78011A651D47AF3000EA16A2 /* Enums */,
|
||||
78CFEE491C5C45E500F50370 /* Protocols */,
|
||||
78D4B54B1DA650FC005B0764 /* Functions */,
|
||||
24F5EFDB1DEA176500B9ADB6 /* Helpers */,
|
||||
78CFEE2D1C5C456B00F50370 /* LeadKit.h */,
|
||||
78CFEE2F1C5C456B00F50370 /* Info.plist */,
|
||||
);
|
||||
|
|
@ -376,6 +507,7 @@
|
|||
786D78E61D53C355006B2CEA /* Alamofire */,
|
||||
7884DB9A1DC1432B00E52A63 /* UserDefaults */,
|
||||
789CC6091DE584C000F789D3 /* CursorType */,
|
||||
24F5EFD81DEA144100B9ADB6 /* Rx */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -410,6 +542,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
78D4B5491DA64EAB005B0764 /* Any+TypeName.swift */,
|
||||
24F5F00E1DEA228F00B9ADB6 /* AbstractMethod.swift */,
|
||||
);
|
||||
path = Functions;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -624,34 +757,47 @@
|
|||
78CFEE541C5C45E500F50370 /* UIView+LoadFromNib.swift in Sources */,
|
||||
78D4B5461DA64D49005B0764 /* UIViewController+DefaultStoryboardIdentifier.swift in Sources */,
|
||||
7834236A1DB8D0E100A79643 /* StoryboardProtocol.swift in Sources */,
|
||||
24F5EFE41DEA18F300B9ADB6 /* MemoryStore.swift in Sources */,
|
||||
78CFEE521C5C45E500F50370 /* UITableView+CellRegistration.swift in Sources */,
|
||||
78B0FC7F1C6B2C4D00358B64 /* Log.swift in Sources */,
|
||||
78753E2E1DE58DBA006BC0FB /* FixedPageCursor.swift in Sources */,
|
||||
789CC60B1DE584F800F789D3 /* CursorType+Slice.swift in Sources */,
|
||||
78753E2C1DE58BF9006BC0FB /* StaticCursor.swift in Sources */,
|
||||
24F5F00D1DEA1A1F00B9ADB6 /* ImageBluringPlugin.swift in Sources */,
|
||||
78D4B54A1DA64EAB005B0764 /* Any+TypeName.swift in Sources */,
|
||||
78CFEE571C5C45E500F50370 /* StaticNibNameProtocol.swift in Sources */,
|
||||
24F5F00B1DEA1A1F00B9ADB6 /* ImageRoundingPlugin.swift in Sources */,
|
||||
788EC15A1CF64528009CFB6B /* UIStoryboard+InstantiateViewController.swift in Sources */,
|
||||
787783671CA04D4A001CDC9B /* String+SizeCalculation.swift in Sources */,
|
||||
78B036431DA4FEC90021D5CC /* CGImage+Transform.swift in Sources */,
|
||||
78011A641D47ABC500EA16A2 /* UIView+DefaultReuseIdentifier.swift in Sources */,
|
||||
786D78EC1D53C46E006B2CEA /* AlamofireManager+Extensions.swift in Sources */,
|
||||
78B0FC811C6B2CD500358B64 /* App.swift in Sources */,
|
||||
24F5F00A1DEA1A1F00B9ADB6 /* ImageResizingPlugin.swift in Sources */,
|
||||
78B036491DA562C30021D5CC /* CGImage+Template.swift in Sources */,
|
||||
78753E301DE594B4006BC0FB /* MapCursor.swift in Sources */,
|
||||
24F5EFEA1DEA191A00B9ADB6 /* Sync.swift in Sources */,
|
||||
780D23461DA416F80084620D /* CGContext+Initializers.swift in Sources */,
|
||||
24F5F00F1DEA228F00B9ADB6 /* AbstractMethod.swift in Sources */,
|
||||
95B39A861D9D51250057BD54 /* String+Localization.swift in Sources */,
|
||||
24F5F0091DEA1A1F00B9ADB6 /* ImagePlugin.swift in Sources */,
|
||||
24F5EFFE1DEA1A1500B9ADB6 /* ImageSourceType.swift in Sources */,
|
||||
78C36F7E1D801E3E00E7EBEA /* Double+Rounding.swift in Sources */,
|
||||
78CFEE551C5C45E500F50370 /* NibNameProtocol.swift in Sources */,
|
||||
24F5EFDA1DEA148A00B9ADB6 /* ObservableType+Extensions.swift in Sources */,
|
||||
78CFEE561C5C45E500F50370 /* ReuseIdentifierProtocol.swift in Sources */,
|
||||
24F5EFF51DEA199300B9ADB6 /* ImageOperation.swift in Sources */,
|
||||
78A0FCC81DC366A10070B5E1 /* StoryboardProtocol+Extensions.swift in Sources */,
|
||||
24F5EFF61DEA199300B9ADB6 /* ImageOperationPerformer.swift in Sources */,
|
||||
78B036411DA4D7060021D5CC /* UIImage+Extensions.swift in Sources */,
|
||||
24F5EFF81DEA199300B9ADB6 /* ImageFakeOperation.swift in Sources */,
|
||||
78A0FCC71DC366A10070B5E1 /* StoryboardProtocol+DefaultBundle.swift in Sources */,
|
||||
78753E241DE58A5D006BC0FB /* CursorError.swift in Sources */,
|
||||
786D78E81D53C378006B2CEA /* AlamofireRequest+Extensions.swift in Sources */,
|
||||
78C36F811D8021DD00E7EBEA /* UIColor+Hex.swift in Sources */,
|
||||
78CFEE5B1C5C45E500F50370 /* ViewModelProtocol.swift in Sources */,
|
||||
780D23431DA412470084620D /* CGImage+Alpha.swift in Sources */,
|
||||
24F5F0011DEA1A1500B9ADB6 /* NetworkImageSource.swift in Sources */,
|
||||
78CFEE5A1C5C45E500F50370 /* ViewHeightProtocol.swift in Sources */,
|
||||
787682FA1CAD40C300532AB3 /* StaticEstimatedViewHeightProtocol.swift in Sources */,
|
||||
78A74EA91C6B373700FE9724 /* UIView+DefaultNibName.swift in Sources */,
|
||||
|
|
@ -659,13 +805,20 @@
|
|||
E126CBB31DB68DDA00E1B2F8 /* UICollectionView+CellRegistration.swift in Sources */,
|
||||
78CFEE581C5C45E500F50370 /* StaticViewHeightProtocol.swift in Sources */,
|
||||
787783631CA03CA0001CDC9B /* IndexPath+ImmutableIndexPath.swift in Sources */,
|
||||
24F5F0081DEA1A1F00B9ADB6 /* ImagePluginOperation.swift in Sources */,
|
||||
24F5EFE11DEA187D00B9ADB6 /* ImageLoader.swift in Sources */,
|
||||
78B036471DA5624D0021D5CC /* CGImage+Creation.swift in Sources */,
|
||||
24F5EFF41DEA199300B9ADB6 /* ImageOperationWrapper.swift in Sources */,
|
||||
789CC6081DE5835600F789D3 /* CursorType.swift in Sources */,
|
||||
24F5F00C1DEA1A1F00B9ADB6 /* ImageFilteringPlugin.swift in Sources */,
|
||||
78B0364B1DA61EDE0021D5CC /* CGImage+Crop.swift in Sources */,
|
||||
78B036451DA561D00021D5CC /* CGImage+Utils.swift in Sources */,
|
||||
24F5EFF71DEA199300B9ADB6 /* ImageLoadingOperation.swift in Sources */,
|
||||
78CFEE591C5C45E500F50370 /* StoryboardIdentifierProtocol.swift in Sources */,
|
||||
78011AB31D48B53600EA16A2 /* ApiRequestParameters.swift in Sources */,
|
||||
24F5EFF91DEA199300B9ADB6 /* ImageStartOperation.swift in Sources */,
|
||||
78B0FC7D1C6B2BE200358B64 /* LogFormatter.swift in Sources */,
|
||||
24F5F0121DEA249900B9ADB6 /* UIImageView+ImageLoader.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
//
|
||||
// ImageLoader.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Anton on 26.11.16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxSwift
|
||||
|
||||
public class ImageLoader<TKey: CustomStringConvertible> {
|
||||
private let imageSource: ImageSource<TKey>
|
||||
private let imageCache: MemoryStore<String, UIImage>
|
||||
|
||||
private var loadingObservablesCache = [String : Observable<UIImage>]()
|
||||
|
||||
private let loadingSyncLock = Sync.Lock()
|
||||
|
||||
public func loadImage(key: TKey) -> ImageOperation {
|
||||
let loadingObservable = Observable.deferred({ () -> Observable<UIImage> in
|
||||
let imageCacheKey = key.description
|
||||
return self.beginLoadingImage(key: key, imageCacheKey: imageCacheKey)
|
||||
})
|
||||
.subcribeOnBackgroundScheduler()
|
||||
|
||||
return ImageLoadingOperation(imageLoader: self, key: key, loadingObservable: loadingObservable)
|
||||
}
|
||||
|
||||
internal func performImageOperation(operation: ImageOperation) -> Observable<UIImage> {
|
||||
return Observable.deferred({ () -> Observable<UIImage> in
|
||||
let operationCachingKey = operation._cachingKey
|
||||
|
||||
if let cachedImage = self.imageCache.loadData(key: operationCachingKey) {
|
||||
return Observable.just(cachedImage)
|
||||
} else {
|
||||
return operation._imageSource
|
||||
.observeOnBackgroundScheduler()
|
||||
.do(onNext: { (image) in
|
||||
self.imageCache.storeData(key: operationCachingKey, data: image)
|
||||
})
|
||||
}
|
||||
})
|
||||
.subcribeOnBackgroundScheduler()
|
||||
}
|
||||
|
||||
private func beginLoadingImage(key: TKey, imageCacheKey: String) -> Observable<UIImage> {
|
||||
return loadingSyncLock.sync {
|
||||
if let loadingObservable = loadingObservablesCache[imageCacheKey] {
|
||||
return loadingObservable
|
||||
}
|
||||
|
||||
let loadingObservable = imageSource.loadImage(key)
|
||||
.observeOnBackgroundScheduler()
|
||||
.do(onDispose: {
|
||||
self.removeLoadingObservable(cacheKey: imageCacheKey)
|
||||
})
|
||||
.shareReplay(1)
|
||||
|
||||
loadingObservablesCache[imageCacheKey] = loadingObservable
|
||||
|
||||
return loadingObservable
|
||||
}
|
||||
}
|
||||
|
||||
private func removeLoadingObservable(cacheKey: String) {
|
||||
loadingSyncLock.sync {
|
||||
loadingObservablesCache.removeValue(forKey: cacheKey)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
public init<TSource: ImageSourceType>(imageSource: TSource,
|
||||
imageCache: MemoryStore<String, UIImage> = MemoryStore()) where TSource.KeyType == TKey {
|
||||
self.imageSource = imageSource.asImageSource()
|
||||
self.imageCache = imageCache
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// ImageFakeOperation.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Anton on 26.11.16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxSwift
|
||||
|
||||
public class ImageFakeOperation: ImageOperationWrapper {
|
||||
public typealias PerformerObservableHandler = (Observable<UIImage>) -> Observable<UIImage>
|
||||
|
||||
private let performerObservableHandler: PerformerObservableHandler
|
||||
|
||||
public override func _preparePerformerObservable(performObservable: Observable<UIImage>) -> Observable<UIImage> {
|
||||
return super._preparePerformerObservable(performObservable: performerObservableHandler(performObservable))
|
||||
}
|
||||
|
||||
public init(originalOperation: ImageOperation, performerObservableHandler: @escaping PerformerObservableHandler) {
|
||||
self.performerObservableHandler = performerObservableHandler
|
||||
super.init(originalOperation: originalOperation)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public extension ImageOperation {
|
||||
public func performWith(_ perfrormHandler: @escaping ImageFakeOperation.PerformerObservableHandler) -> ImageOperation {
|
||||
return ImageFakeOperation(originalOperation: self, performerObservableHandler: perfrormHandler)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// ImageLoadingOperation.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Anton on 26.11.16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxSwift
|
||||
|
||||
public class ImageLoadingOperation<TKey: CustomStringConvertible>: ImageOperation, ImageOperationPerformer {
|
||||
public override var _imageSource: Observable<UIImage> {
|
||||
return loadingObservable
|
||||
}
|
||||
|
||||
public override var _performer: ImageOperationPerformer {
|
||||
return self
|
||||
}
|
||||
|
||||
public override var _cachingKey: String {
|
||||
return key.description
|
||||
}
|
||||
|
||||
public func performImageOperation(operation: ImageOperation) -> Observable<UIImage> {
|
||||
return imageLoader.performImageOperation(operation: operation)
|
||||
}
|
||||
|
||||
private let loadingObservable: Observable<UIImage>
|
||||
private let imageLoader: ImageLoader<TKey>
|
||||
private let key: TKey
|
||||
|
||||
public init(imageLoader: ImageLoader<TKey>, key: TKey, loadingObservable: Observable<UIImage>) {
|
||||
self.imageLoader = imageLoader
|
||||
self.key = key
|
||||
self.loadingObservable = loadingObservable
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// ImageOperation.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Anton on 26.11.16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxSwift
|
||||
|
||||
public class ImageOperation: ObservableType {
|
||||
public typealias E = UIImage
|
||||
|
||||
open var _imageSource: Observable<UIImage> {
|
||||
abstractMethod("_imageSource")
|
||||
}
|
||||
|
||||
open var _performer: ImageOperationPerformer {
|
||||
abstractMethod("_performer")
|
||||
}
|
||||
|
||||
open var _cachingKey: String {
|
||||
abstractMethod("_cachingKey")
|
||||
}
|
||||
|
||||
open func _preparePerformerObservable(performObservable: Observable<UIImage>) -> Observable<UIImage> {
|
||||
return performObservable
|
||||
}
|
||||
|
||||
public func subscribe<O: ObserverType>(_ observer: O) -> Disposable where O.E == UIImage {
|
||||
return _preparePerformerObservable(performObservable: _performer.performImageOperation(operation: self))
|
||||
.subscribe(observer)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
//
|
||||
// ImageOperationPerformer.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Anton on 26.11.16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxSwift
|
||||
|
||||
public protocol ImageOperationPerformer {
|
||||
func performImageOperation(operation: ImageOperation) -> Observable<UIImage>
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// ImageOperationWrapper.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Anton on 26.11.16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxSwift
|
||||
|
||||
public class ImageOperationWrapper: ImageOperation {
|
||||
open override var _imageSource: Observable<UIImage> {
|
||||
return _prepareWorkingObservable(workingObservable: originalOperation._imageSource)
|
||||
}
|
||||
|
||||
open override var _performer: ImageOperationPerformer {
|
||||
return originalOperation._performer
|
||||
}
|
||||
|
||||
open override var _cachingKey: String {
|
||||
return _prepareCachingKey(cachingKey: originalOperation._cachingKey)
|
||||
}
|
||||
|
||||
open func _prepareWorkingObservable(workingObservable: Observable<UIImage>) -> Observable<UIImage> {
|
||||
return workingObservable
|
||||
}
|
||||
|
||||
open override func _preparePerformerObservable(performObservable: Observable<UIImage>) -> Observable<UIImage> {
|
||||
return super._preparePerformerObservable(performObservable:
|
||||
originalOperation._preparePerformerObservable(performObservable: performObservable))
|
||||
}
|
||||
|
||||
open func _prepareCachingKey(cachingKey: String) -> String {
|
||||
return cachingKey
|
||||
}
|
||||
|
||||
private let originalOperation: ImageOperation
|
||||
|
||||
public init(originalOperation: ImageOperation) {
|
||||
self.originalOperation = originalOperation
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
//
|
||||
// ImageStartOperation.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Anton on 26.11.16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxSwift
|
||||
|
||||
public class ImageStartOperation: ImageOperation, ImageOperationPerformer {
|
||||
public override var _imageSource: Observable<UIImage> {
|
||||
return source
|
||||
}
|
||||
|
||||
public override var _performer: ImageOperationPerformer {
|
||||
return self
|
||||
}
|
||||
|
||||
public override var _cachingKey: String {
|
||||
return key
|
||||
}
|
||||
|
||||
public func performImageOperation(operation: ImageOperation) -> Observable<UIImage> {
|
||||
return operation._imageSource
|
||||
}
|
||||
|
||||
private let source: Observable<UIImage>
|
||||
private let key: String
|
||||
|
||||
public init(source: Observable<UIImage>, key: String? = nil) {
|
||||
self.key = key ?? String()
|
||||
self.source = source
|
||||
}
|
||||
}
|
||||
|
||||
public extension UIImage {
|
||||
public func asImageOperation(key: String? = nil) -> ImageOperation {
|
||||
return Observable.just(self).asImageOperation()
|
||||
}
|
||||
}
|
||||
|
||||
public extension ImageOperation {
|
||||
public func asImageOperation(key: String? = nil) -> ImageOperation {
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
public extension ObservableConvertibleType where E == UIImage {
|
||||
public func asImageOperation(key: String? = nil) -> ImageOperation {
|
||||
return ImageStartOperation(source: self.asObservable(), key: key)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
//
|
||||
// ImageBluringPlugin.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Anton on 26.11.16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class ImageBluringPlugin: ImageFilteringPlugin {
|
||||
public enum BlurType {
|
||||
case box(radius: CGFloat)
|
||||
case disc(radius: CGFloat)
|
||||
case gaussian(radius: CGFloat)
|
||||
case masked(radius: CGFloat, maskImage: UIImage)
|
||||
case median()
|
||||
case motion(radius: CGFloat, angle: CGFloat)
|
||||
|
||||
public func filterParams() -> [String : Any] {
|
||||
var resultRadius: CGFloat?
|
||||
var resultParams = [String : Any]()
|
||||
|
||||
switch self {
|
||||
case .box(let radius):
|
||||
resultRadius = radius
|
||||
case .disc(let radius):
|
||||
resultRadius = radius
|
||||
case .gaussian(let radius):
|
||||
resultRadius = radius
|
||||
case .masked(let radius, let maskImage):
|
||||
resultRadius = radius
|
||||
resultParams["inputMask"] = maskImage.cgImage
|
||||
case.median:
|
||||
break
|
||||
case .motion(let radius, let angle):
|
||||
resultRadius = radius
|
||||
resultParams["inputAngle"] = angle
|
||||
}
|
||||
|
||||
if let resultRadius = resultRadius {
|
||||
resultParams["inputRadius"] = resultRadius
|
||||
}
|
||||
|
||||
return resultParams
|
||||
}
|
||||
|
||||
public func filterName() -> String {
|
||||
switch self {
|
||||
case .box:
|
||||
return "CIBoxBlur"
|
||||
case .disc:
|
||||
return "CIDiscBlur"
|
||||
case .gaussian:
|
||||
return "CIGaussianBlur"
|
||||
case .masked:
|
||||
return "CIMaskedVariableBlur"
|
||||
case.median:
|
||||
return "CIMedianFilter"
|
||||
case .motion:
|
||||
return "CIMotionBlur"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public init(blurType: BlurType) {
|
||||
super.init(name: blurType.filterName(), params: blurType.filterParams())
|
||||
}
|
||||
}
|
||||
|
||||
public extension ImageOperation {
|
||||
public func blur(blurType: ImageBluringPlugin.BlurType) -> ImageOperation {
|
||||
return ImagePluginOperation(originalOperation: self, plugin: ImageBluringPlugin(blurType: blurType))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
//
|
||||
// ImageFilteringPlugin.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Anton on 26.11.16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import AlamofireImage
|
||||
import RxSwift
|
||||
|
||||
public class ImageFilteringPlugin: ImagePluginType {
|
||||
public enum FilterError: Error {
|
||||
case unknownError(description: String)
|
||||
}
|
||||
|
||||
public typealias FitlerParamsType = [String : Any]
|
||||
|
||||
private let filterName: String
|
||||
private let filterParams: FitlerParamsType?
|
||||
|
||||
public var pluginKey: String {
|
||||
var resultKey = filterName
|
||||
if let filterParams = filterParams {
|
||||
resultKey += filterParams.description
|
||||
}
|
||||
|
||||
return resultKey
|
||||
}
|
||||
|
||||
public func perform(image: UIImage) -> Observable<UIImage> {
|
||||
return Observable.deferred({ () -> Observable<UIImage> in
|
||||
guard let reusltImage = image.af_imageFiltered(withCoreImageFilter: self.filterName, parameters: self.filterParams) else {
|
||||
throw FilterError.unknownError(description: "ImageFilterPlugin failed with filter named \(self.filterName)")
|
||||
}
|
||||
|
||||
return Observable.just(reusltImage)
|
||||
})
|
||||
.subcribeOnBackgroundScheduler()
|
||||
}
|
||||
|
||||
public init(name: String, params: FitlerParamsType? = nil) {
|
||||
filterName = name
|
||||
filterParams = params
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public extension ImageOperation {
|
||||
public func filter(name: String, params: ImageFilteringPlugin.FitlerParamsType? = nil) -> ImageOperation {
|
||||
return ImagePluginOperation(originalOperation: self, plugin: ImageFilteringPlugin(name: name, params: params))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
//
|
||||
// ImagePlugin.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Anton on 26.11.16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxSwift
|
||||
|
||||
public protocol ImagePluginType {
|
||||
func perform(image: UIImage) -> Observable<UIImage>
|
||||
var pluginKey: String { get }
|
||||
}
|
||||
|
||||
extension UIImage {
|
||||
public func performPlugins(plugins: [ImagePluginType]) -> Observable<UIImage> {
|
||||
var observable = Observable.just(self)
|
||||
|
||||
for plugin in plugins {
|
||||
observable = observable.flatMap(plugin.perform)
|
||||
}
|
||||
|
||||
return observable
|
||||
}
|
||||
|
||||
public func performPlugins(plugins: ImagePluginType ...) -> Observable<UIImage> {
|
||||
return performPlugins(plugins: plugins)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// ImagePluginOperation.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Anton on 26.11.16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxSwift
|
||||
|
||||
public class ImagePluginOperation: ImageOperationWrapper {
|
||||
public override func _prepareCachingKey(cachingKey: String) -> String {
|
||||
return cachingKey + plugin.pluginKey
|
||||
}
|
||||
|
||||
public override func _prepareWorkingObservable(workingObservable: Observable<UIImage>) -> Observable<UIImage> {
|
||||
return workingObservable
|
||||
.flatMap({ (image) -> Observable<UIImage> in
|
||||
return self.plugin.perform(image: image)
|
||||
})
|
||||
}
|
||||
|
||||
private let plugin: ImagePluginType
|
||||
|
||||
public init(originalOperation: ImageOperation, plugin: ImagePluginType) {
|
||||
self.plugin = plugin
|
||||
super.init(originalOperation: originalOperation)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
//
|
||||
// ImageResizingPlugin.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Anton on 26.11.16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import AlamofireImage
|
||||
import RxSwift
|
||||
|
||||
public class ImageResizingPlugin: ImagePluginType {
|
||||
public enum Mode: String {
|
||||
case scale
|
||||
case aspectFit
|
||||
case aspectFill
|
||||
|
||||
static var `default`: Mode {
|
||||
return .scale
|
||||
}
|
||||
}
|
||||
|
||||
private let mode: Mode
|
||||
private let size: CGSize
|
||||
|
||||
public var pluginKey: String {
|
||||
return mode.rawValue + String(describing: size.width) + String(describing: size.height)
|
||||
}
|
||||
|
||||
public func perform(image: UIImage) -> Observable<UIImage> {
|
||||
return Observable.deferred({ () -> Observable<UIImage> in
|
||||
return Observable.just(self.beginPerform(image: image))
|
||||
})
|
||||
.subcribeOnBackgroundScheduler()
|
||||
}
|
||||
|
||||
private func beginPerform(image: UIImage) -> UIImage {
|
||||
switch mode {
|
||||
case .scale:
|
||||
return image.af_imageScaled(to: size)
|
||||
case .aspectFit:
|
||||
return image.af_imageAspectScaled(toFit: size)
|
||||
case .aspectFill:
|
||||
return image.af_imageAspectScaled(toFill: size)
|
||||
}
|
||||
}
|
||||
|
||||
public init(size: CGSize, mode: Mode = .default) {
|
||||
self.size = size
|
||||
self.mode = mode;
|
||||
}
|
||||
}
|
||||
|
||||
public extension ImageOperation {
|
||||
public func resize(size: CGSize, mode: ImageResizingPlugin.Mode = .default) -> ImageOperation {
|
||||
return ImagePluginOperation(originalOperation: self, plugin: ImageResizingPlugin(size: size, mode: mode))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
//
|
||||
// ImageRoundingPlugin.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Anton on 26.11.16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import AlamofireImage
|
||||
import RxSwift
|
||||
|
||||
public class ImageRoundingPlugin: ImagePluginType {
|
||||
public enum Mode {
|
||||
case cicrular
|
||||
case corners(radius: CGFloat)
|
||||
|
||||
static var `default`: Mode {
|
||||
return .cicrular
|
||||
}
|
||||
|
||||
public var key: String {
|
||||
switch self {
|
||||
case .cicrular:
|
||||
return "Circular"
|
||||
case .corners(let radius):
|
||||
return "Corners" + String(describing: radius)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private let mode: Mode
|
||||
|
||||
public var pluginKey: String {
|
||||
return mode.key
|
||||
}
|
||||
|
||||
public func perform(image: UIImage) -> Observable<UIImage> {
|
||||
return Observable.deferred({ () -> Observable<UIImage> in
|
||||
return Observable.just(self.beginPerform(image: image))
|
||||
})
|
||||
.subcribeOnBackgroundScheduler()
|
||||
}
|
||||
|
||||
private func beginPerform(image: UIImage) -> UIImage {
|
||||
switch mode {
|
||||
case .cicrular:
|
||||
return image.af_imageRoundedIntoCircle()
|
||||
case .corners(let radius):
|
||||
return image.af_imageRounded(withCornerRadius: radius)
|
||||
}
|
||||
}
|
||||
|
||||
public init(mode: Mode = .default) {
|
||||
self.mode = mode;
|
||||
}
|
||||
}
|
||||
|
||||
public extension ImageOperation {
|
||||
public func round(mode: ImageRoundingPlugin.Mode = .default) -> ImageOperation {
|
||||
return ImagePluginOperation(originalOperation: self, plugin: ImageRoundingPlugin(mode: mode))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
//
|
||||
// ImageSource.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Anton on 26.11.16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxSwift
|
||||
|
||||
public protocol ImageSourceType {
|
||||
associatedtype KeyType
|
||||
|
||||
func loadImage(_ key: KeyType) -> Observable<UIImage>
|
||||
|
||||
func asImageSource() -> ImageSource<KeyType>
|
||||
}
|
||||
|
||||
extension ImageSourceType {
|
||||
public func asImageSource() -> ImageSource<KeyType> {
|
||||
return ImageSource(source: self)
|
||||
}
|
||||
}
|
||||
|
||||
public class ImageSource<TKey>: ImageSourceType {
|
||||
public typealias KeyType = TKey
|
||||
public typealias ImageLoadingHandler = (KeyType) -> Observable<UIImage>
|
||||
|
||||
private let sourceLoadImageHandler: ImageLoadingHandler
|
||||
|
||||
public func loadImage(_ key: KeyType) -> Observable<UIImage> {
|
||||
return sourceLoadImageHandler(key)
|
||||
}
|
||||
|
||||
public init(imageLoadingHandler: @escaping ImageLoadingHandler) {
|
||||
sourceLoadImageHandler = imageLoadingHandler
|
||||
}
|
||||
|
||||
public convenience init<TSource: ImageSourceType>(source: TSource) where TSource.KeyType == KeyType {
|
||||
self.init(imageLoadingHandler: source.loadImage)
|
||||
}
|
||||
}
|
||||
|
||||
extension ImageSource {
|
||||
public func asImageSource() -> ImageSource<KeyType> {
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// NetworkImageSource.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Anton on 26.11.16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import RxSwift
|
||||
import Alamofire
|
||||
import AlamofireImage
|
||||
|
||||
public class NetworkImageSource<TKey: URLConvertible>: ImageSourceType where TKey: CustomStringConvertible {
|
||||
public typealias KeyType = TKey
|
||||
|
||||
private let sessionManager: SessionManager
|
||||
|
||||
public func loadImage(_ key: KeyType) -> Observable<UIImage> {
|
||||
return Observable.deferred({ () -> Observable<UIImage> in
|
||||
return self.beginLoadImage(try key.asURL())
|
||||
})
|
||||
}
|
||||
|
||||
private func beginLoadImage(_ url: URL) -> Observable<UIImage> {
|
||||
return Observable.create({ (observer) -> Disposable in
|
||||
let request = self.sessionManager.request(url)
|
||||
.responseImage(completionHandler: { (response) in
|
||||
switch response.result {
|
||||
case .success(let image):
|
||||
observer.onNext(image)
|
||||
observer.onCompleted()
|
||||
case .failure(let error):
|
||||
observer.onError(error)
|
||||
}
|
||||
})
|
||||
|
||||
return Disposables.create {
|
||||
request.cancel()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public init(sessionManager: SessionManager = SessionManager.default) {
|
||||
self.sessionManager = sessionManager
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
//
|
||||
// UIImageView+ImageLoader.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Anton on 26.11.16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxSwift
|
||||
|
||||
public extension ImageResizingPlugin.Mode {
|
||||
public static func fromUIContentMode(contentMode: UIViewContentMode) -> ImageResizingPlugin.Mode {
|
||||
switch contentMode {
|
||||
case .scaleAspectFill:
|
||||
return .aspectFill
|
||||
case .scaleAspectFit:
|
||||
return .aspectFit
|
||||
default:
|
||||
return .scale
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public extension UIImageView {
|
||||
public func loadImage<TKey: CustomStringConvertible>(key: TKey, loader: ImageLoader<TKey>, resizeImage: Bool = true,
|
||||
placeholder: UIImage? = nil) -> ImageOperation {
|
||||
|
||||
var resultOperation = loader.loadImage(key: key)
|
||||
|
||||
if resizeImage {
|
||||
resultOperation = resultOperation.resize(size: frame.size, mode: ImageResizingPlugin.Mode.fromUIContentMode(contentMode: contentMode))
|
||||
}
|
||||
|
||||
resultOperation = resultOperation.performWith({ (observable) -> Observable<UIImage> in
|
||||
var resultObservable = observable.observeOnMainScheduler()
|
||||
.do(onNext: { [weak self] (image) in
|
||||
self?.image = image
|
||||
})
|
||||
.takeUntil(self.rx.deallocated)
|
||||
|
||||
if let placeholder = placeholder {
|
||||
resultObservable = resultObservable.startWith(placeholder)
|
||||
}
|
||||
|
||||
return resultObservable
|
||||
})
|
||||
|
||||
return resultOperation
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// ObservableType+Extensions.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Anton on 26.11.16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxSwift
|
||||
|
||||
public extension ObservableType {
|
||||
public func subcribeOnBackgroundScheduler() -> Observable<E> {
|
||||
return self.subscribeOn(ConcurrentDispatchQueueScheduler(qos: .default))
|
||||
}
|
||||
|
||||
public func observeOnBackgroundScheduler() -> Observable<E> {
|
||||
return self.observeOn(ConcurrentDispatchQueueScheduler(qos: .default))
|
||||
}
|
||||
|
||||
public func subcribeOnMainScheduler() -> Observable<E> {
|
||||
return self.subscribeOn(MainScheduler.instance)
|
||||
}
|
||||
|
||||
public func observeOnMainScheduler() -> Observable<E> {
|
||||
return self.observeOn(MainScheduler.instance)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
//
|
||||
// AbstractMethod.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Anton on 26.11.16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public func abstractMethod(_ methodName: String = "Method") -> Never {
|
||||
fatalError("\(methodName) has not been implemented")
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
//
|
||||
// MemoryStore.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Anton on 26.11.16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class MemoryStore<TKey: Hashable, TData> {
|
||||
public typealias KeyType = TKey
|
||||
public typealias DataType = TData
|
||||
|
||||
private var syncLock = Sync.Lock()
|
||||
private var dictionaryStore: [KeyType : DataType] = [:]
|
||||
private let clearOnMemoryWarning: Bool
|
||||
|
||||
public init(clearOnMemoryWarning: Bool = false) {
|
||||
self.clearOnMemoryWarning = clearOnMemoryWarning
|
||||
|
||||
if clearOnMemoryWarning {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(onMemoryWarning),
|
||||
name: NSNotification.Name.UIApplicationDidReceiveMemoryWarning, object: UIApplication.shared)
|
||||
}
|
||||
}
|
||||
|
||||
public func removeAllData() {
|
||||
syncLock.sync {
|
||||
return dictionaryStore.removeAll()
|
||||
}
|
||||
}
|
||||
|
||||
public func loadData(key: KeyType) -> DataType? {
|
||||
return syncLock.sync {
|
||||
return dictionaryStore[key]
|
||||
}
|
||||
}
|
||||
|
||||
public func storeData(key: TKey, data: DataType?) {
|
||||
syncLock.sync {
|
||||
guard let data = data else {
|
||||
dictionaryStore.removeValue(forKey: key)
|
||||
return
|
||||
}
|
||||
|
||||
dictionaryStore[key] = data
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func onMemoryWarning() {
|
||||
removeAllData()
|
||||
}
|
||||
|
||||
deinit {
|
||||
if clearOnMemoryWarning {
|
||||
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIApplicationDidReceiveMemoryWarning, object: UIApplication.shared)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
//
|
||||
// Sync.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Anton on 26.11.16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
public final class Sync {
|
||||
public final class Lock {
|
||||
public func lock() {
|
||||
Sync.beginSyncLock(self)
|
||||
}
|
||||
|
||||
public func unlock() {
|
||||
Sync.endSyncLock(self)
|
||||
}
|
||||
|
||||
public func sync(block: () throws -> Void) rethrows {
|
||||
try Sync.synchronized(lockObj: self, block: block)
|
||||
}
|
||||
|
||||
public func sync<T>(block: () throws -> T) rethrows -> T {
|
||||
return try Sync.synchronized(lockObj: self, block: block)
|
||||
}
|
||||
}
|
||||
|
||||
public static func beginSyncLock(_ lockObj: Any) -> Void {
|
||||
objc_sync_enter(lockObj)
|
||||
}
|
||||
|
||||
public static func endSyncLock(_ lockObj: Any) -> Void {
|
||||
objc_sync_exit(lockObj)
|
||||
}
|
||||
|
||||
public static func synchronized(lockObj: Any, block: () throws -> Void) rethrows -> Void {
|
||||
beginSyncLock(lockObj)
|
||||
try block()
|
||||
endSyncLock(lockObj)
|
||||
}
|
||||
|
||||
public static func synchronized<T>(lockObj: Any, block: () throws -> T) rethrows -> T {
|
||||
beginSyncLock(lockObj)
|
||||
let result: T = try block()
|
||||
endSyncLock(lockObj)
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue