表情下载、解码,发送
This commit is contained in:
@@ -113,6 +113,9 @@
|
||||
9B0086C627BA392B0032BD2B /* AnchorStageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B0086C527BA392B0032BD2B /* AnchorStageView.m */; };
|
||||
9B0086CA27BA4F570032BD2B /* AnchorMicroView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B0086C927BA4F570032BD2B /* AnchorMicroView.m */; };
|
||||
9B060B5827BCAEE20001B767 /* AnchorGiftValueView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B060B5727BCAEE20001B767 /* AnchorGiftValueView.m */; };
|
||||
9B04CE20278937D100434F47 /* XPFaceParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B04CE1F278937D100434F47 /* XPFaceParser.m */; };
|
||||
9B04CE232789392E00434F47 /* FaceSendInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B04CE212789392E00434F47 /* FaceSendInfo.m */; };
|
||||
9B04CE26278940D700434F47 /* XPFaceProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B04CE25278940D700434F47 /* XPFaceProtocol.m */; };
|
||||
9B0E1C5926E77022005D4442 /* BaseNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B0E1C5826E77022005D4442 /* BaseNavigationController.m */; };
|
||||
9B17F71827BD150600440843 /* SVGAParserManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B17F71727BD150600440843 /* SVGAParserManager.m */; };
|
||||
9B7B605B27BB53060070BB72 /* XPAnchorAudienceUpMicView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B7B605A27BB53060070BB72 /* XPAnchorAudienceUpMicView.m */; };
|
||||
@@ -141,6 +144,15 @@
|
||||
9BE29A6B27D1BFF700446AB5 /* anchor_room_speak.svga in Resources */ = {isa = PBXBuildFile; fileRef = 9BE29A6927D1BFF700446AB5 /* anchor_room_speak.svga */; };
|
||||
9BE29A6D27D210A500446AB5 /* anchor_room_bg.svga in Resources */ = {isa = PBXBuildFile; fileRef = 9BE29A6C27D210A500446AB5 /* anchor_room_bg.svga */; };
|
||||
9B8585D3278837CE00D7D5C6 /* NobleLevelUpModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B8585D2278837CE00D7D5C6 /* NobleLevelUpModel.m */; };
|
||||
9B8585D6278844B300D7D5C6 /* NSString+JsonToDic.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B8585D4278844B300D7D5C6 /* NSString+JsonToDic.m */; };
|
||||
9B8585EE27885B3E00D7D5C6 /* YYWebResourceDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B8585ED27885B3E00D7D5C6 /* YYWebResourceDownloader.m */; };
|
||||
9B8585F52788699400D7D5C6 /* FBKVOController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B8585F42788699400D7D5C6 /* FBKVOController.m */; };
|
||||
9B8585F927886A1100D7D5C6 /* CommonFileUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B8585F827886A1000D7D5C6 /* CommonFileUtils.m */; };
|
||||
9BA9AD832789344E00C0BF8F /* FaceReceiveInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BA9AD7B2789344D00C0BF8F /* FaceReceiveInfo.m */; };
|
||||
9BA9AD842789344E00C0BF8F /* FaceInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BA9AD7D2789344D00C0BF8F /* FaceInfo.m */; };
|
||||
9BA9AD852789344E00C0BF8F /* FaceConfigInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BA9AD7F2789344D00C0BF8F /* FaceConfigInfo.m */; };
|
||||
9BA9AD862789344E00C0BF8F /* FaceInfoStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BA9AD802789344D00C0BF8F /* FaceInfoStorage.m */; };
|
||||
9BA9AD872789344E00C0BF8F /* FacePlayInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BA9AD812789344D00C0BF8F /* FacePlayInfo.m */; };
|
||||
9BB549592782E6A30090CD26 /* XPNobleCenterPresenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BB549582782E6A30090CD26 /* XPNobleCenterPresenter.m */; };
|
||||
9BB5495C2782E79E0090CD26 /* NobleCenterModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BB5495B2782E79E0090CD26 /* NobleCenterModel.m */; };
|
||||
9BB5495F2782E9DB0090CD26 /* NobleAuthInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BB5495E2782E9DB0090CD26 /* NobleAuthInfo.m */; };
|
||||
@@ -713,6 +725,12 @@
|
||||
9B0086C927BA4F570032BD2B /* AnchorMicroView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AnchorMicroView.m; sourceTree = "<group>"; };
|
||||
9B060B5627BCAEE20001B767 /* AnchorGiftValueView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AnchorGiftValueView.h; sourceTree = "<group>"; };
|
||||
9B060B5727BCAEE20001B767 /* AnchorGiftValueView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AnchorGiftValueView.m; sourceTree = "<group>"; };
|
||||
9B04CE1E278937D100434F47 /* XPFaceParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XPFaceParser.h; sourceTree = "<group>"; };
|
||||
9B04CE1F278937D100434F47 /* XPFaceParser.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XPFaceParser.m; sourceTree = "<group>"; };
|
||||
9B04CE212789392E00434F47 /* FaceSendInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FaceSendInfo.m; sourceTree = "<group>"; };
|
||||
9B04CE222789392E00434F47 /* FaceSendInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FaceSendInfo.h; sourceTree = "<group>"; };
|
||||
9B04CE24278940D700434F47 /* XPFaceProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XPFaceProtocol.h; sourceTree = "<group>"; };
|
||||
9B04CE25278940D700434F47 /* XPFaceProtocol.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XPFaceProtocol.m; sourceTree = "<group>"; };
|
||||
9B0E1C5726E77022005D4442 /* BaseNavigationController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BaseNavigationController.h; sourceTree = "<group>"; };
|
||||
9B0E1C5826E77022005D4442 /* BaseNavigationController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BaseNavigationController.m; sourceTree = "<group>"; };
|
||||
9B17F71627BD150600440843 /* SVGAParserManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAParserManager.h; sourceTree = "<group>"; };
|
||||
@@ -765,6 +783,24 @@
|
||||
9BAA5FEF277A23F4007453F3 /* XPPermissionsViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XPPermissionsViewController.m; sourceTree = "<group>"; };
|
||||
9B8585D1278837CE00D7D5C6 /* NobleLevelUpModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NobleLevelUpModel.h; sourceTree = "<group>"; };
|
||||
9B8585D2278837CE00D7D5C6 /* NobleLevelUpModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NobleLevelUpModel.m; sourceTree = "<group>"; };
|
||||
9B8585D4278844B300D7D5C6 /* NSString+JsonToDic.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+JsonToDic.m"; sourceTree = "<group>"; };
|
||||
9B8585D5278844B300D7D5C6 /* NSString+JsonToDic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+JsonToDic.h"; sourceTree = "<group>"; };
|
||||
9B8585EC27885B3E00D7D5C6 /* YYWebResourceDownloader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYWebResourceDownloader.h; sourceTree = "<group>"; };
|
||||
9B8585ED27885B3E00D7D5C6 /* YYWebResourceDownloader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYWebResourceDownloader.m; sourceTree = "<group>"; };
|
||||
9B8585F32788699400D7D5C6 /* FBKVOController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBKVOController.h; sourceTree = "<group>"; };
|
||||
9B8585F42788699400D7D5C6 /* FBKVOController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBKVOController.m; sourceTree = "<group>"; };
|
||||
9B8585F727886A1000D7D5C6 /* CommonFileUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommonFileUtils.h; sourceTree = "<group>"; };
|
||||
9B8585F827886A1000D7D5C6 /* CommonFileUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CommonFileUtils.m; sourceTree = "<group>"; };
|
||||
9BA9AD792789344D00C0BF8F /* FaceConfigInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FaceConfigInfo.h; sourceTree = "<group>"; };
|
||||
9BA9AD7A2789344D00C0BF8F /* FaceInfoStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FaceInfoStorage.h; sourceTree = "<group>"; };
|
||||
9BA9AD7B2789344D00C0BF8F /* FaceReceiveInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FaceReceiveInfo.m; sourceTree = "<group>"; };
|
||||
9BA9AD7C2789344D00C0BF8F /* FacePlayInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FacePlayInfo.h; sourceTree = "<group>"; };
|
||||
9BA9AD7D2789344D00C0BF8F /* FaceInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FaceInfo.m; sourceTree = "<group>"; };
|
||||
9BA9AD7E2789344D00C0BF8F /* FaceInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FaceInfo.h; sourceTree = "<group>"; };
|
||||
9BA9AD7F2789344D00C0BF8F /* FaceConfigInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FaceConfigInfo.m; sourceTree = "<group>"; };
|
||||
9BA9AD802789344D00C0BF8F /* FaceInfoStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FaceInfoStorage.m; sourceTree = "<group>"; };
|
||||
9BA9AD812789344D00C0BF8F /* FacePlayInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FacePlayInfo.m; sourceTree = "<group>"; };
|
||||
9BA9AD822789344E00C0BF8F /* FaceReceiveInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FaceReceiveInfo.h; sourceTree = "<group>"; };
|
||||
9BB549572782E6A30090CD26 /* XPNobleCenterPresenter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XPNobleCenterPresenter.h; sourceTree = "<group>"; };
|
||||
9BB549582782E6A30090CD26 /* XPNobleCenterPresenter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XPNobleCenterPresenter.m; sourceTree = "<group>"; };
|
||||
9BB5495A2782E79E0090CD26 /* NobleCenterModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NobleCenterModel.h; sourceTree = "<group>"; };
|
||||
@@ -1926,6 +1962,9 @@
|
||||
E80CBDE727D0C528001E1EC2 /* Timer */,
|
||||
180116F6279E8C3100F2CBC0 /* Date */,
|
||||
9B17F71527BD14FF00440843 /* SVGAParserManager */,
|
||||
9B8585F627886A1000D7D5C6 /* File */,
|
||||
9B8585F22788699400D7D5C6 /* KVO */,
|
||||
9B8585EA27885B3D00D7D5C6 /* WebResource */,
|
||||
E82D5C77276B25B000858D6D /* SpriteSheetManager */,
|
||||
E865964E2701A1A900846EBD /* StatisticsService */,
|
||||
E89DA6612700590A008483C1 /* IAPHelper */,
|
||||
@@ -2193,10 +2232,38 @@
|
||||
);
|
||||
path = Model;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9B04CE1B2789379B00434F47 /* XPFaceParser */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9B04CE1E278937D100434F47 /* XPFaceParser.h */,
|
||||
9B04CE1F278937D100434F47 /* XPFaceParser.m */,
|
||||
);
|
||||
path = XPFaceParser;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9B04CE1C278937B300434F47 /* Procotol */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9B04CE24278940D700434F47 /* XPFaceProtocol.h */,
|
||||
9B04CE25278940D700434F47 /* XPFaceProtocol.m */,
|
||||
);
|
||||
path = Procotol;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9B04CE1D278937BB00434F47 /* Api */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
path = Api;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9B208A372779C1EF00F9E54A /* FaceView */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9B04CE1D278937BB00434F47 /* Api */,
|
||||
9B04CE1C278937B300434F47 /* Procotol */,
|
||||
9B04CE1B2789379B00434F47 /* XPFaceParser */,
|
||||
9BC5C8E6277AAD8B007C8719 /* Presenter */,
|
||||
9B208A492779C30600F9E54A /* Model */,
|
||||
9B208A382779C2CA00F9E54A /* View */,
|
||||
@@ -2232,6 +2299,18 @@
|
||||
9B208A492779C30600F9E54A /* Model */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9BA9AD792789344D00C0BF8F /* FaceConfigInfo.h */,
|
||||
9BA9AD7F2789344D00C0BF8F /* FaceConfigInfo.m */,
|
||||
9BA9AD7E2789344D00C0BF8F /* FaceInfo.h */,
|
||||
9BA9AD7D2789344D00C0BF8F /* FaceInfo.m */,
|
||||
9BA9AD7A2789344D00C0BF8F /* FaceInfoStorage.h */,
|
||||
9BA9AD802789344D00C0BF8F /* FaceInfoStorage.m */,
|
||||
9BA9AD7C2789344D00C0BF8F /* FacePlayInfo.h */,
|
||||
9BA9AD812789344D00C0BF8F /* FacePlayInfo.m */,
|
||||
9BA9AD822789344E00C0BF8F /* FaceReceiveInfo.h */,
|
||||
9BA9AD7B2789344D00C0BF8F /* FaceReceiveInfo.m */,
|
||||
9B04CE222789392E00434F47 /* FaceSendInfo.h */,
|
||||
9B04CE212789392E00434F47 /* FaceSendInfo.m */,
|
||||
9B208A4A2779C30600F9E54A /* XCGameRoomFaceViewDisplayModel.h */,
|
||||
9B208A4D2779C30600F9E54A /* XCGameRoomFaceViewDisplayModel.m */,
|
||||
9B208A4C2779C30600F9E54A /* XCGameRoomFaceTitleDisplayModel.h */,
|
||||
@@ -2265,6 +2344,48 @@
|
||||
path = NobleVIP;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9B8585D727884FE200D7D5C6 /* Face */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
path = Face;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9B8585EA27885B3D00D7D5C6 /* WebResource */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9B8585EB27885B3E00D7D5C6 /* Downloader */,
|
||||
);
|
||||
path = WebResource;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9B8585EB27885B3E00D7D5C6 /* Downloader */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9B8585EC27885B3E00D7D5C6 /* YYWebResourceDownloader.h */,
|
||||
9B8585ED27885B3E00D7D5C6 /* YYWebResourceDownloader.m */,
|
||||
);
|
||||
path = Downloader;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9B8585F22788699400D7D5C6 /* KVO */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9B8585F32788699400D7D5C6 /* FBKVOController.h */,
|
||||
9B8585F42788699400D7D5C6 /* FBKVOController.m */,
|
||||
);
|
||||
path = KVO;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9B8585F627886A1000D7D5C6 /* File */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9B8585F727886A1000D7D5C6 /* CommonFileUtils.h */,
|
||||
9B8585F827886A1000D7D5C6 /* CommonFileUtils.m */,
|
||||
);
|
||||
path = File;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9BB549632782F96F0090CD26 /* SubViews */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -2526,6 +2647,8 @@
|
||||
E81366E426F0A4820076364C /* NSString */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9B8585D5278844B300D7D5C6 /* NSString+JsonToDic.h */,
|
||||
9B8585D4278844B300D7D5C6 /* NSString+JsonToDic.m */,
|
||||
E81366E526F0A49E0076364C /* NSString+Utils.h */,
|
||||
E81366E626F0A49E0076364C /* NSString+Utils.m */,
|
||||
);
|
||||
@@ -3516,6 +3639,7 @@
|
||||
E8412F9A2779BAC2006E1101 /* Setting */,
|
||||
E84150B027747A7400A7F548 /* FirstRecharge */,
|
||||
E81C1B1327705EF00020D1E4 /* ArrangeMic */,
|
||||
9B8585D727884FE200D7D5C6 /* Face */,
|
||||
9B8585D0278835BF00D7D5C6 /* NobleVIP */,
|
||||
9BC5C915277C809E007C8719 /* ReleaseRadio */,
|
||||
E8A1E4462761F8EA00B294CA /* CandyTree */,
|
||||
@@ -4278,6 +4402,7 @@
|
||||
E8ACEFEF27C8C45100F66D1A /* XPHomeHapppyRoomTableViewCell.m in Sources */,
|
||||
E84BF7DA277C72AC00EF8877 /* XPRoomRoleTableViewCell.m in Sources */,
|
||||
E839532D276A030F00CF2F24 /* XPMineDressUpListViewController.m in Sources */,
|
||||
9BA9AD832789344E00C0BF8F /* FaceReceiveInfo.m in Sources */,
|
||||
E8B846D826FDE17300A777FE /* XPMineRechargeProtocol.h in Sources */,
|
||||
E82D5C7D276B343300858D6D /* YYAnimatedImageView+ImageShow.m in Sources */,
|
||||
E8B846C726FDB45000A777FE /* XPMineUserInfoAlbumProtocol.h in Sources */,
|
||||
@@ -4333,11 +4458,14 @@
|
||||
E84150BB27747BAF00A7F548 /* XPFirstRechargePresenter.m in Sources */,
|
||||
9BEE3D1727858E5700C83219 /* XPNobleAuthorityDescView.m in Sources */,
|
||||
E82325F9274E2E42003A3332 /* Api+UserCard.m in Sources */,
|
||||
9B04CE20278937D100434F47 /* XPFaceParser.m in Sources */,
|
||||
E82109B026F1D83500FC3319 /* LoginBindPhonePresent.m in Sources */,
|
||||
E81C1B1F27705F7A0020D1E4 /* XPArrangeMicViewController.m in Sources */,
|
||||
9BA9AD852789344E00C0BF8F /* FaceConfigInfo.m in Sources */,
|
||||
E8B825C726EA0D9A009E8E9F /* LoginVerifCodeProtocol.h in Sources */,
|
||||
E824544E26F5BC1A00BE8163 /* XPMineModifPayPwdView.m in Sources */,
|
||||
E8A6C2A227CF856E00AC7442 /* HomeCollectRoomModel.m in Sources */,
|
||||
9B8585F52788699400D7D5C6 /* FBKVOController.m in Sources */,
|
||||
E8A03DE22762FA000098D9EA /* XPCandyTreeMoreView.m in Sources */,
|
||||
E8B825CA26EA1231009E8E9F /* LoginVerifCodeViewController.m in Sources */,
|
||||
189DD76226E60DDC00AB55B1 /* Api+Login.m in Sources */,
|
||||
@@ -4387,6 +4515,7 @@
|
||||
189DD53426DE255300AB55B1 /* TabbarViewController.m in Sources */,
|
||||
E87A26F927587C62002DDC7A /* XPHomeContainerPresenter.m in Sources */,
|
||||
18EE401A2754BA9F00A452BF /* NIMMessageMaker.m in Sources */,
|
||||
9B8585EE27885B3E00D7D5C6 /* YYWebResourceDownloader.m in Sources */,
|
||||
E8EEB91D26FC9D58007C6EBA /* XPMineUserInfoDateView.m in Sources */,
|
||||
E82325E9274CE56A003A3332 /* XPShareItem.m in Sources */,
|
||||
E890BC0D273D09A50007C46B /* XPGiftCountView.m in Sources */,
|
||||
@@ -4506,6 +4635,8 @@
|
||||
18E7B31E26F0984C0064BC9B /* UserLevelVo.m in Sources */,
|
||||
E82D5C7A276B25D100858D6D /* SpriteSheetImageManager.m in Sources */,
|
||||
E874B88B27215EAF003954B9 /* MicroQueueModel.m in Sources */,
|
||||
9BA9AD872789344E00C0BF8F /* FacePlayInfo.m in Sources */,
|
||||
9B8585D6278844B300D7D5C6 /* NSString+JsonToDic.m in Sources */,
|
||||
E8EE827D272B9A2300A17217 /* XPRoomSendTextView.m in Sources */,
|
||||
9BD63FAE277EE97A006EB744 /* XPReleaseRadioPresenter.m in Sources */,
|
||||
E8EEB90626FC5772007C6EBA /* XPMineUserInfoEditViewController.m in Sources */,
|
||||
@@ -4553,6 +4684,7 @@
|
||||
186A534A26FC6ED900D67B2C /* TTActionSheetConfig.m in Sources */,
|
||||
9BBC028B2786E05A0007C24B /* XPNobleCenterEntranceView.m in Sources */,
|
||||
E81C279326EB394D0031E639 /* LoginForgetPasswordViewController.m in Sources */,
|
||||
9BA9AD862789344E00C0BF8F /* FaceInfoStorage.m in Sources */,
|
||||
E81C278D26EAFAF60031E639 /* DESEncrypt.m in Sources */,
|
||||
9BC5C8E9277AB6AE007C8719 /* XPFacePresenter.m in Sources */,
|
||||
E81366E726F0A49E0076364C /* NSString+Utils.m in Sources */,
|
||||
@@ -4636,6 +4768,7 @@
|
||||
E83DB481274649FB00D8CBD1 /* XPGiftBannerUserInfoModel.m in Sources */,
|
||||
E878893F273A54F500BF1D57 /* XPGiftPresenter.m in Sources */,
|
||||
E8A03DF62763367F0098D9EA /* XPCandyTreeEmptyableViewCell.m in Sources */,
|
||||
9B04CE232789392E00434F47 /* FaceSendInfo.m in Sources */,
|
||||
E8AEAEED27141AE20017FCE0 /* XPRoomBackContainerView.m in Sources */,
|
||||
E88B5CC126FB407B00DA9178 /* XPMineUserInfoViewController.m in Sources */,
|
||||
18F4043A275E20D900A6C548 /* TRTCRtcImpl.m in Sources */,
|
||||
@@ -4649,9 +4782,11 @@
|
||||
E8A6C28C27CF436300AC7442 /* XPHomeLikeViewController.m in Sources */,
|
||||
E8E70D8F26F2F5DB00F03460 /* XPMineMenuTableViewCell.m in Sources */,
|
||||
E8E5E1A927C3850400F457D8 /* XPHomeHotRoomCollectionViewCell.m in Sources */,
|
||||
9B8585F927886A1100D7D5C6 /* CommonFileUtils.m in Sources */,
|
||||
187EEEE126E89BFB002833B2 /* AccountModel.m in Sources */,
|
||||
E896EFA92771AEEC00AD2CC1 /* XPMineAttentionTableViewCell.m in Sources */,
|
||||
9BBC02912786FC570007C24B /* XPMineNobleCardTableViewCell.m in Sources */,
|
||||
9B04CE26278940D700434F47 /* XPFaceProtocol.m in Sources */,
|
||||
E8AC722126F47E23007D6E91 /* XPMineAboutUsViewController.m in Sources */,
|
||||
18F403CB2758C66800A6C548 /* MessageContentText.m in Sources */,
|
||||
E8232600274E48EA003A3332 /* XPUserCardItemCollectionViewCell.m in Sources */,
|
||||
@@ -4674,6 +4809,7 @@
|
||||
E84BF7E0277C869A00EF8877 /* XPRoomOnLineViewController.m in Sources */,
|
||||
186A534826FC6ED900D67B2C /* TTAlertButtonConfig.m in Sources */,
|
||||
E8ACEFF827C9034C00F66D1A /* XPHomeListEmptyTableViewCell.m in Sources */,
|
||||
9BA9AD842789344E00C0BF8F /* FaceInfo.m in Sources */,
|
||||
E89D60BA271D643A001F8895 /* Api+Room.m in Sources */,
|
||||
E872308926E89BE000B90D4F /* LoginPhoneViewController.m in Sources */,
|
||||
E8C6FFEA2755040B004DC9F0 /* XPHomeSearchNavView.m in Sources */,
|
||||
|
91
xplan-ios/Base/Tool/File/CommonFileUtils.h
Normal file
91
xplan-ios/Base/Tool/File/CommonFileUtils.h
Normal file
@@ -0,0 +1,91 @@
|
||||
//
|
||||
// CommonFileUtils.h
|
||||
// Commons
|
||||
//
|
||||
// Created by 小城 on 14-6-5.
|
||||
// Copyright (c) 2014年 YY Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface CommonFileUtils : NSObject
|
||||
|
||||
/**Some FilePaths
|
||||
*/
|
||||
+ (NSString *)documentsDirectory;
|
||||
+ (NSString *)cachesDirectory;
|
||||
|
||||
/**
|
||||
* File Operation
|
||||
*/
|
||||
|
||||
/**
|
||||
* 创建文件所在的目录
|
||||
*
|
||||
* @param path 文件的绝对路径
|
||||
*
|
||||
* @return 是否创建成功
|
||||
*/
|
||||
+ (BOOL)createDirForPath:(NSString *)path;
|
||||
|
||||
/**
|
||||
* 创建目录
|
||||
*
|
||||
* @param dirPath 目录绝对路径
|
||||
*
|
||||
* @return 是否创建成功
|
||||
*/
|
||||
+ (BOOL)createDirWithDirPath:(NSString *)dirPath;
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
*
|
||||
* @param path 文件所在的绝对路径
|
||||
*
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
+ (BOOL)deleteFileWithFullPath:(NSString *)path;
|
||||
|
||||
/**
|
||||
* 指定路径的文件是否存在
|
||||
*
|
||||
* @param filePath 文件的绝对路径
|
||||
*
|
||||
* @return 是否存在
|
||||
*/
|
||||
+ (BOOL)isFileExists:(NSString *)filePath;
|
||||
|
||||
/**
|
||||
* 在文件的末尾追加文本内容
|
||||
*
|
||||
* @param content 文本内容
|
||||
* @param filePath 文件绝对路径,比如保证该文件是存在的,返回会返回NO
|
||||
*
|
||||
* @return 是否追加成功
|
||||
*/
|
||||
+ (BOOL)appendContent:(NSString *)content toFilePath:(NSString *)filePath;
|
||||
|
||||
|
||||
/**FileUtils In UserDefault
|
||||
*/
|
||||
+ (BOOL)writeObject:(id)object toUserDefaultWithKey:(NSString*)key;
|
||||
+ (id)readObjectFromUserDefaultWithKey:(NSString*)key;
|
||||
+ (BOOL)deleteObjectFromUserDefaultWithKey:(NSString*)key;
|
||||
|
||||
/**FileUtils In CachesPath
|
||||
*/
|
||||
+ (void)writeObject:(id)object toCachesPath:(NSString*)path;
|
||||
+ (id)readObjectFromCachesPath:(NSString*)path;
|
||||
+ (BOOL)deleteFileFromCachesPath:(NSString *)path;
|
||||
|
||||
/**FileUtils In DocumentPath
|
||||
*/
|
||||
+ (void)writeObject:(id)object toDocumentPath:(NSString *)path;
|
||||
+ (id)readObjectFromDocumentPath:(NSString *)path;
|
||||
+ (BOOL)deleteFileFromDocumentPath:(NSString *)path;
|
||||
|
||||
+ (BOOL)copyItem:(NSString *)destination toPath:(NSString *)toPath;
|
||||
|
||||
+ (NSString*)getFileMD5WithPath:(NSString*)path;
|
||||
|
||||
@end
|
360
xplan-ios/Base/Tool/File/CommonFileUtils.m
Normal file
360
xplan-ios/Base/Tool/File/CommonFileUtils.m
Normal file
@@ -0,0 +1,360 @@
|
||||
//
|
||||
// CommonFileUtils.m
|
||||
// Commons
|
||||
//
|
||||
// Created by 小城 on 14-6-5.
|
||||
// Copyright (c) 2014年 YY Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import "CommonFileUtils.h"
|
||||
#import <CommonCrypto/CommonDigest.h>
|
||||
#define FileHashDefaultChunkSizeForReadingData 1024*8 // 8K
|
||||
|
||||
@implementation CommonFileUtils
|
||||
|
||||
+ (NSString *)documentsDirectory
|
||||
{
|
||||
static NSString *docsDir = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
|
||||
});
|
||||
return docsDir;
|
||||
}
|
||||
|
||||
+ (NSString *)cachesDirectory
|
||||
{
|
||||
static NSString *cachesDir = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
|
||||
});
|
||||
return cachesDir;
|
||||
}
|
||||
|
||||
+ (BOOL)createDirForPath:(NSString *)path
|
||||
{
|
||||
return [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
|
||||
}
|
||||
|
||||
+ (BOOL)createDirWithDirPath:(NSString *)dirPath
|
||||
{
|
||||
return [[NSFileManager defaultManager] createDirectoryAtPath:dirPath
|
||||
withIntermediateDirectories:YES
|
||||
attributes:nil
|
||||
error:nil];
|
||||
}
|
||||
|
||||
+ (BOOL)deleteFileWithFullPath:(NSString *)fullPath
|
||||
{
|
||||
BOOL deleteSucc = NO;
|
||||
if ([[NSFileManager defaultManager] isDeletableFileAtPath:fullPath]) {
|
||||
deleteSucc = [[NSFileManager defaultManager] removeItemAtPath:fullPath error:NULL];
|
||||
}
|
||||
|
||||
return deleteSucc;
|
||||
}
|
||||
|
||||
|
||||
/**UserDefault
|
||||
*/
|
||||
+ (BOOL)writeObject:(id)object toUserDefaultWithKey:(NSString*)key
|
||||
{
|
||||
if (object == nil || key == nil) return NO;
|
||||
|
||||
NSData *myEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:object];
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
[defaults setObject:myEncodedObject forKey:key];
|
||||
return [defaults synchronize];
|
||||
}
|
||||
|
||||
+ (id)readObjectFromUserDefaultWithKey:(NSString*)key
|
||||
{
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSData *myEncodedObject = [defaults objectForKey:key];
|
||||
|
||||
if (myEncodedObject == nil) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
@try {
|
||||
return [NSKeyedUnarchiver unarchiveObjectWithData: myEncodedObject];
|
||||
}
|
||||
@catch (NSException *e){
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
+ (BOOL)deleteObjectFromUserDefaultWithKey:(NSString*)key
|
||||
{
|
||||
if (!key) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
[defaults removeObjectForKey:key];
|
||||
return [defaults synchronize];
|
||||
}
|
||||
|
||||
+ (BOOL)isFileExists:(NSString *)filePath
|
||||
{
|
||||
return [[NSFileManager defaultManager] fileExistsAtPath:filePath];
|
||||
}
|
||||
|
||||
+ (BOOL)appendContent:(NSString *)content toFilePath:(NSString *)filePath
|
||||
{
|
||||
if (![CommonFileUtils isFileExists:filePath]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
BOOL appendSucc = YES;
|
||||
|
||||
NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:filePath];
|
||||
if (!fileHandle) {
|
||||
appendSucc = NO;
|
||||
} else {
|
||||
[fileHandle seekToEndOfFile];
|
||||
[fileHandle writeData:[content dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
[fileHandle closeFile];
|
||||
}
|
||||
|
||||
return appendSucc;
|
||||
}
|
||||
|
||||
|
||||
/**CachesPath
|
||||
*/
|
||||
+ (void)writeObject:(id)object toCachesPath:(NSString*)path
|
||||
{
|
||||
if (object == nil || [path length] == 0)
|
||||
return;
|
||||
|
||||
NSString *fullPath = [[CommonFileUtils cachesDirectory] stringByAppendingPathComponent:path];
|
||||
[CommonFileUtils _writeObject:object toPath:fullPath];
|
||||
}
|
||||
|
||||
+ (id)readObjectFromCachesPath:(NSString*)path
|
||||
{
|
||||
if ([path length] == 0)
|
||||
return nil;
|
||||
|
||||
NSString *fullPath = [[CommonFileUtils cachesDirectory] stringByAppendingPathComponent:path];
|
||||
return [CommonFileUtils _readObjectFromPath:fullPath];
|
||||
}
|
||||
|
||||
+ (BOOL)deleteFileFromCachesPath:(NSString *)path
|
||||
{
|
||||
NSString *fullPath = [[CommonFileUtils cachesDirectory] stringByAppendingPathComponent:path];
|
||||
return [CommonFileUtils deleteFileWithFullPath:fullPath];
|
||||
}
|
||||
|
||||
/**DocumentPath
|
||||
*/
|
||||
+ (void)writeObject:(id)object toDocumentPath:(NSString *)path
|
||||
{
|
||||
if (object == nil || [path length] == 0)
|
||||
return;
|
||||
|
||||
NSString *fullPath = [[CommonFileUtils documentsDirectory] stringByAppendingPathComponent:path];
|
||||
[CommonFileUtils _writeObject:object toPath:fullPath];
|
||||
|
||||
}
|
||||
|
||||
+ (id)readObjectFromDocumentPath:(NSString *)path
|
||||
{
|
||||
if ([path length] == 0)
|
||||
return nil;
|
||||
|
||||
NSString *fullPath = [[CommonFileUtils documentsDirectory] stringByAppendingPathComponent:path];
|
||||
return [CommonFileUtils _readObjectFromPath:fullPath];
|
||||
}
|
||||
|
||||
+ (BOOL)deleteFileFromDocumentPath:(NSString *)path
|
||||
{
|
||||
NSString *fullPath = [[CommonFileUtils documentsDirectory] stringByAppendingPathComponent:path];
|
||||
return [CommonFileUtils deleteFileWithFullPath:fullPath];
|
||||
}
|
||||
|
||||
+ (BOOL)copyItem:(NSString *)destination toPath:(NSString *)toPath
|
||||
{
|
||||
NSError *error = nil;
|
||||
[[NSFileManager defaultManager] copyItemAtPath:destination toPath:toPath error:&error];
|
||||
return error != nil;
|
||||
}
|
||||
|
||||
#pragma mark - private
|
||||
static id getSemaphore(NSString *key)
|
||||
{
|
||||
static NSMutableDictionary *dict = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
dict = [[NSMutableDictionary alloc] initWithCapacity:10];
|
||||
});
|
||||
|
||||
id obj = [dict objectForKey:key];
|
||||
if (!obj)
|
||||
{
|
||||
obj = [[NSObject alloc] init];
|
||||
[dict setObject:obj forKey:key];
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
static dispatch_queue_t getFileQueue()
|
||||
{
|
||||
static dispatch_queue_t queue = NULL;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
queue = dispatch_queue_create("FileQueue", NULL);
|
||||
});
|
||||
return queue;
|
||||
}
|
||||
|
||||
|
||||
+ (void)_writeObject:(id)obj toPath:(NSString *)fullPath
|
||||
{
|
||||
if (obj == nil || [fullPath length] == 0)
|
||||
return;
|
||||
|
||||
id newObj = obj;
|
||||
if ([obj isKindOfClass:[NSArray class]] || [obj isKindOfClass:[NSDictionary class]])
|
||||
{
|
||||
//集合类型为了避免出现写的同时另一个线程在操作同一个集合可能导致崩溃,这里在主线程生成一个新的集合
|
||||
if ([obj isKindOfClass:[NSMutableArray class]])
|
||||
newObj = [NSMutableArray arrayWithArray:obj];
|
||||
else if ([obj isKindOfClass:[NSArray class]])
|
||||
newObj = [NSArray arrayWithArray:obj];
|
||||
else if ([obj isKindOfClass:[NSMutableDictionary class]])
|
||||
newObj = [NSMutableDictionary dictionaryWithDictionary:obj];
|
||||
else
|
||||
newObj = [NSDictionary dictionaryWithDictionary:obj];
|
||||
}
|
||||
|
||||
id sema = getSemaphore(fullPath);
|
||||
|
||||
//在queue中操作
|
||||
dispatch_async(getFileQueue(), ^{
|
||||
@synchronized(sema)
|
||||
{
|
||||
//必须先创建目录,否则archiveRootObject操作在没有目录的情况下会失败!
|
||||
if ([CommonFileUtils createDirForPath:fullPath])
|
||||
{
|
||||
[NSKeyedArchiver archiveRootObject:newObj toFile:fullPath];
|
||||
}
|
||||
// else
|
||||
// {
|
||||
|
||||
// }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+ (id)_readObjectFromPath:(NSString *)fullPath
|
||||
{
|
||||
id sema = getSemaphore(fullPath);
|
||||
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:fullPath])
|
||||
{
|
||||
@try
|
||||
{
|
||||
@synchronized(sema)
|
||||
{
|
||||
return [NSKeyedUnarchiver unarchiveObjectWithFile:fullPath];
|
||||
}
|
||||
}
|
||||
@catch (NSException *e)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
else
|
||||
return nil;
|
||||
}
|
||||
|
||||
+(NSString*)getFileMD5WithPath:(NSString*)path
|
||||
{
|
||||
return (__bridge NSString *)FileMD5HashCreateWithPath((__bridge CFStringRef)path,FileHashDefaultChunkSizeForReadingData);
|
||||
}
|
||||
|
||||
CFStringRef FileMD5HashCreateWithPath(CFStringRef filePath,
|
||||
size_t chunkSizeForReadingData) {
|
||||
|
||||
// Declare needed variables
|
||||
CFStringRef result = NULL;
|
||||
CFReadStreamRef readStream = NULL;
|
||||
|
||||
// Get the file URL
|
||||
CFURLRef fileURL =
|
||||
CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
|
||||
(CFStringRef)filePath,
|
||||
kCFURLPOSIXPathStyle,
|
||||
(Boolean)false);
|
||||
|
||||
CC_MD5_CTX hashObject;
|
||||
bool hasMoreData = true;
|
||||
bool didSucceed;
|
||||
|
||||
if (!fileURL) goto done;
|
||||
|
||||
// Create and open the read stream
|
||||
readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault,
|
||||
(CFURLRef)fileURL);
|
||||
if (!readStream) goto done;
|
||||
didSucceed = (bool)CFReadStreamOpen(readStream);
|
||||
if (!didSucceed) goto done;
|
||||
|
||||
// Initialize the hash object
|
||||
CC_MD5_Init(&hashObject);
|
||||
|
||||
// Make sure chunkSizeForReadingData is valid
|
||||
if (!chunkSizeForReadingData) {
|
||||
chunkSizeForReadingData = FileHashDefaultChunkSizeForReadingData;
|
||||
}
|
||||
|
||||
// Feed the data to the hash object
|
||||
while (hasMoreData) {
|
||||
uint8_t buffer[chunkSizeForReadingData];
|
||||
CFIndex readBytesCount = CFReadStreamRead(readStream,
|
||||
(UInt8 *)buffer,
|
||||
(CFIndex)sizeof(buffer));
|
||||
if (readBytesCount == -1)break;
|
||||
if (readBytesCount == 0) {
|
||||
hasMoreData =false;
|
||||
continue;
|
||||
}
|
||||
CC_MD5_Update(&hashObject,(const void *)buffer,(CC_LONG)readBytesCount);
|
||||
}
|
||||
|
||||
// Check if the read operation succeeded
|
||||
didSucceed = !hasMoreData;
|
||||
|
||||
// Compute the hash digest
|
||||
unsigned char digest[CC_MD5_DIGEST_LENGTH];
|
||||
CC_MD5_Final(digest, &hashObject);
|
||||
|
||||
// Abort if the read operation failed
|
||||
if (!didSucceed) goto done;
|
||||
|
||||
// Compute the string result
|
||||
char hash[2 *sizeof(digest) + 1];
|
||||
for (size_t i =0; i < sizeof(digest); ++i) {
|
||||
snprintf(hash + (2 * i),3, "%02x", (int)(digest[i]));
|
||||
}
|
||||
result = CFStringCreateWithCString(kCFAllocatorDefault,
|
||||
(const char *)hash,
|
||||
kCFStringEncodingUTF8);
|
||||
|
||||
done:
|
||||
|
||||
if (readStream) {
|
||||
CFReadStreamClose(readStream);
|
||||
CFRelease(readStream);
|
||||
}
|
||||
if (fileURL) {
|
||||
CFRelease(fileURL);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@end
|
137
xplan-ios/Base/Tool/KVO/FBKVOController.h
Normal file
137
xplan-ios/Base/Tool/KVO/FBKVOController.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
Copyright (c) 2014-present, Facebook, Inc.
|
||||
All rights reserved.
|
||||
|
||||
This source code is licensed under the BSD-style license found in the
|
||||
LICENSE file in the root directory of this source tree. An additional grant
|
||||
of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
@abstract Block called on key-value change notification.
|
||||
@param observer The observer of the change.
|
||||
@param object The object changed.
|
||||
@param change The change dictionary.
|
||||
*/
|
||||
typedef void (^FBKVONotificationBlock)(id observer, id object, NSDictionary *change);
|
||||
|
||||
|
||||
/**
|
||||
@abstract FBKVOController makes Key-Value Observing simpler and safer.
|
||||
@discussion FBKVOController adds support for handling key-value changes with blocks and custom actions, as well as the NSKeyValueObserving callback. Notification will never message a deallocated observer. Observer removal never throws exceptions, and observers are removed implicitely on controller deallocation. FBKVOController is also thread safe. When used in a concurrent environment, it protects observers from possible ressurection and avoids ensuing crash. By default, the controller maintains a strong reference to objects observed.
|
||||
*/
|
||||
@interface FBKVOController : NSObject
|
||||
|
||||
/**
|
||||
@abstract Creates and returns an initialized KVO controller instance.
|
||||
@param observer The object notified on key-value change.
|
||||
@return The initialized KVO controller instance.
|
||||
*/
|
||||
+ (instancetype)controllerWithObserver:(id)observer;
|
||||
|
||||
/**
|
||||
@abstract The designated initializer.
|
||||
@param observer The object notified on key-value change. The specified observer must support weak references.
|
||||
@param retainObserved Flag indicating whether observed objects should be retained.
|
||||
@return The initialized KVO controller instance.
|
||||
@discussion Use retainObserved = NO when a strong reference between controller and observee would create a retain loop. When not retaining observees, special care must be taken to remove observation info prior to observee dealloc.
|
||||
*/
|
||||
- (instancetype)initWithObserver:(id)observer retainObserved:(BOOL)retainObserved;
|
||||
|
||||
/**
|
||||
@abstract Convenience initializer.
|
||||
@param observer The object notified on key-value change. The specified observer must support weak references.
|
||||
@return The initialized KVO controller instance.
|
||||
@discussion By default, KVO controller retains objects observed.
|
||||
*/
|
||||
- (instancetype)initWithObserver:(id)observer;
|
||||
|
||||
/// The observer notified on key-value change. Specified on initialization.
|
||||
@property (atomic, weak, readonly) id observer;
|
||||
|
||||
/**
|
||||
@abstract Registers observer for key-value change notification.
|
||||
@param object The object to observe.
|
||||
@param keyPath The key path to observe.
|
||||
@param options The NSKeyValueObservingOptions to use for observation.
|
||||
@param block The block to execute on notification.
|
||||
@discussion On key-value change, the specified block is called. Inorder to avoid retain loops, the block must avoid referencing the KVO controller or an owner thereof. Observing an already observed object key path or nil results in no operation.
|
||||
*/
|
||||
- (void)observe:(id)object keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options block:(FBKVONotificationBlock)block;
|
||||
|
||||
/**
|
||||
@abstract Registers observer for key-value change notification.
|
||||
@param object The object to observe.
|
||||
@param keyPath The key path to observe.
|
||||
@param options The NSKeyValueObservingOptions to use for observation.
|
||||
@param action The observer selector called on key-value change.
|
||||
@discussion On key-value change, the observer's action selector is called. The selector provided should take the form of -propertyDidChange, -propertyDidChange: or -propertyDidChange:object:, where optional parameters delivered will be KVO change dictionary and object observed. Observing nil or observing an already observed object's key path results in no operation.
|
||||
*/
|
||||
- (void)observe:(id)object keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options action:(SEL)action;
|
||||
|
||||
/**
|
||||
@abstract Registers observer for key-value change notification.
|
||||
@param object The object to observe.
|
||||
@param keyPath The key path to observe.
|
||||
@param options The NSKeyValueObservingOptions to use for observation.
|
||||
@param context The context specified.
|
||||
@discussion On key-value change, the observer's -observeValueForKeyPath:ofObject:change:context: method is called. Observing an already observed object key path or nil results in no operation.
|
||||
*/
|
||||
- (void)observe:(id)object keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
|
||||
|
||||
|
||||
/**
|
||||
@abstract Registers observer for key-value change notification.
|
||||
@param object The object to observe.
|
||||
@param keyPaths The key paths to observe.
|
||||
@param options The NSKeyValueObservingOptions to use for observation.
|
||||
@param block The block to execute on notification.
|
||||
@discussion On key-value change, the specified block is called. Inorder to avoid retain loops, the block must avoid referencing the KVO controller or an owner thereof. Observing an already observed object key path or nil results in no operation.
|
||||
*/
|
||||
- (void)observe:(id)object keyPaths:(NSArray *)keyPaths options:(NSKeyValueObservingOptions)options block:(FBKVONotificationBlock)block;
|
||||
|
||||
/**
|
||||
@abstract Registers observer for key-value change notification.
|
||||
@param object The object to observe.
|
||||
@param keyPaths The key paths to observe.
|
||||
@param options The NSKeyValueObservingOptions to use for observation.
|
||||
@param action The observer selector called on key-value change.
|
||||
@discussion On key-value change, the observer's action selector is called. The selector provided should take the form of -propertyDidChange, -propertyDidChange: or -propertyDidChange:object:, where optional parameters delivered will be KVO change dictionary and object observed. Observing nil or observing an already observed object's key path results in no operation.
|
||||
*/
|
||||
- (void)observe:(id)object keyPaths:(NSArray *)keyPaths options:(NSKeyValueObservingOptions)options action:(SEL)action;
|
||||
|
||||
/**
|
||||
@abstract Registers observer for key-value change notification.
|
||||
@param object The object to observe.
|
||||
@param keyPaths The key paths to observe.
|
||||
@param options The NSKeyValueObservingOptions to use for observation.
|
||||
@param context The context specified.
|
||||
@discussion On key-value change, the observer's -observeValueForKeyPath:ofObject:change:context: method is called. Observing an already observed object key path or nil results in no operation.
|
||||
*/
|
||||
- (void)observe:(id)object keyPaths:(NSArray *)keyPaths options:(NSKeyValueObservingOptions)options context:(void *)context;
|
||||
|
||||
|
||||
/**
|
||||
@abstract Unobserve object key path.
|
||||
@param object The object to unobserve.
|
||||
@param keyPath The key path to observe.
|
||||
@discussion If not observing object key path, or unobserving nil, this method results in no operation.
|
||||
*/
|
||||
- (void)unobserve:(id)object keyPath:(NSString *)keyPath;
|
||||
|
||||
/**
|
||||
@abstract Unobserve all object key paths.
|
||||
@param object The object to unobserve.
|
||||
@discussion If not observing object, or unobserving nil, this method results in no operation.
|
||||
*/
|
||||
- (void)unobserve:(id)object;
|
||||
|
||||
/**
|
||||
@abstract Unobserve all objects.
|
||||
@discussion If not observing any objects, this method results in no operation.
|
||||
*/
|
||||
- (void)unobserveAll;
|
||||
|
||||
@end
|
624
xplan-ios/Base/Tool/KVO/FBKVOController.m
Normal file
624
xplan-ios/Base/Tool/KVO/FBKVOController.m
Normal file
@@ -0,0 +1,624 @@
|
||||
/**
|
||||
Copyright (c) 2014-present, Facebook, Inc.
|
||||
All rights reserved.
|
||||
|
||||
This source code is licensed under the BSD-style license found in the
|
||||
LICENSE file in the root directory of this source tree. An additional grant
|
||||
of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import "FBKVOController.h"
|
||||
|
||||
#import <libkern/OSAtomic.h>
|
||||
#import <objc/message.h>
|
||||
|
||||
#if !__has_feature(objc_arc)
|
||||
#error This file must be compiled with ARC. Convert your project to ARC or specify the -fobjc-arc flag.
|
||||
#endif
|
||||
|
||||
#pragma mark Utilities -
|
||||
|
||||
static NSString *describe_option(NSKeyValueObservingOptions option)
|
||||
{
|
||||
switch (option) {
|
||||
case NSKeyValueObservingOptionNew:
|
||||
return @"NSKeyValueObservingOptionNew";
|
||||
break;
|
||||
case NSKeyValueObservingOptionOld:
|
||||
return @"NSKeyValueObservingOptionOld";
|
||||
break;
|
||||
case NSKeyValueObservingOptionInitial:
|
||||
return @"NSKeyValueObservingOptionInitial";
|
||||
break;
|
||||
case NSKeyValueObservingOptionPrior:
|
||||
return @"NSKeyValueObservingOptionPrior";
|
||||
break;
|
||||
default:
|
||||
NSCAssert(NO, @"unexpected option %tu", option);
|
||||
break;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
static void append_option_description(NSMutableString *s, NSUInteger option)
|
||||
{
|
||||
if (0 == s.length) {
|
||||
[s appendString:describe_option(option)];
|
||||
} else {
|
||||
[s appendString:@"|"];
|
||||
[s appendString:describe_option(option)];
|
||||
}
|
||||
}
|
||||
|
||||
static NSUInteger enumerate_flags(NSUInteger *ptrFlags)
|
||||
{
|
||||
NSCAssert(ptrFlags, @"expected ptrFlags");
|
||||
if (!ptrFlags) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
NSUInteger flags = *ptrFlags;
|
||||
if (!flags) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
NSUInteger flag = 1 << __builtin_ctzl(flags);
|
||||
flags &= ~flag;
|
||||
*ptrFlags = flags;
|
||||
return flag;
|
||||
}
|
||||
|
||||
static NSString *describe_options(NSKeyValueObservingOptions options)
|
||||
{
|
||||
NSMutableString *s = [NSMutableString string];
|
||||
NSUInteger option;
|
||||
while (0 != (option = enumerate_flags(&options))) {
|
||||
append_option_description(s, option);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
#pragma mark _FBKVOInfo -
|
||||
|
||||
/**
|
||||
@abstract The key-value observation info.
|
||||
@discussion Object equality is only used within the scope of a controller instance. Safely omit controller from equality definition.
|
||||
*/
|
||||
@interface _FBKVOInfo : NSObject
|
||||
@end
|
||||
|
||||
@implementation _FBKVOInfo
|
||||
{
|
||||
@public
|
||||
__weak FBKVOController *_controller;
|
||||
NSString *_keyPath;
|
||||
NSKeyValueObservingOptions _options;
|
||||
SEL _action;
|
||||
void *_context;
|
||||
FBKVONotificationBlock _block;
|
||||
}
|
||||
|
||||
- (instancetype)initWithController:(FBKVOController *)controller keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options block:(FBKVONotificationBlock)block action:(SEL)action context:(void *)context
|
||||
{
|
||||
self = [super init];
|
||||
if (nil != self) {
|
||||
_controller = controller;
|
||||
_block = [block copy];
|
||||
_keyPath = [keyPath copy];
|
||||
_options = options;
|
||||
_action = action;
|
||||
_context = context;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithController:(FBKVOController *)controller keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options block:(FBKVONotificationBlock)block
|
||||
{
|
||||
return [self initWithController:controller keyPath:keyPath options:options block:block action:NULL context:NULL];
|
||||
}
|
||||
|
||||
- (instancetype)initWithController:(FBKVOController *)controller keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options action:(SEL)action
|
||||
{
|
||||
return [self initWithController:controller keyPath:keyPath options:options block:NULL action:action context:NULL];
|
||||
}
|
||||
|
||||
- (instancetype)initWithController:(FBKVOController *)controller keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
|
||||
{
|
||||
return [self initWithController:controller keyPath:keyPath options:options block:NULL action:NULL context:context];
|
||||
}
|
||||
|
||||
- (instancetype)initWithController:(FBKVOController *)controller keyPath:(NSString *)keyPath
|
||||
{
|
||||
return [self initWithController:controller keyPath:keyPath options:0 block:NULL action:NULL context:NULL];
|
||||
}
|
||||
|
||||
- (NSUInteger)hash
|
||||
{
|
||||
return [_keyPath hash];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object
|
||||
{
|
||||
if (nil == object) {
|
||||
return NO;
|
||||
}
|
||||
if (self == object) {
|
||||
return YES;
|
||||
}
|
||||
if (![object isKindOfClass:[self class]]) {
|
||||
return NO;
|
||||
}
|
||||
return [_keyPath isEqualToString:((_FBKVOInfo *)object)->_keyPath];
|
||||
}
|
||||
|
||||
- (NSString *)debugDescription
|
||||
{
|
||||
NSMutableString *s = [NSMutableString stringWithFormat:@"<%@:%p keyPath:%@", NSStringFromClass([self class]), self, _keyPath];
|
||||
if (0 != _options) {
|
||||
[s appendFormat:@" options:%@", describe_options(_options)];
|
||||
}
|
||||
if (NULL != _action) {
|
||||
[s appendFormat:@" action:%@", NSStringFromSelector(_action)];
|
||||
}
|
||||
if (NULL != _context) {
|
||||
[s appendFormat:@" context:%p", _context];
|
||||
}
|
||||
if (NULL != _block) {
|
||||
[s appendFormat:@" block:%p", _block];
|
||||
}
|
||||
[s appendString:@">"];
|
||||
return s;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark _FBKVOSharedController -
|
||||
|
||||
/**
|
||||
@abstract The shared KVO controller instance.
|
||||
@discussion Acts as a receptionist, receiving and forwarding KVO notifications.
|
||||
*/
|
||||
@interface _FBKVOSharedController : NSObject
|
||||
|
||||
/** A shared instance that never deallocates. */
|
||||
+ (instancetype)sharedController;
|
||||
|
||||
/** observe an object, info pair */
|
||||
- (void)observe:(id)object info:(_FBKVOInfo *)info;
|
||||
|
||||
/** unobserve an object, info pair */
|
||||
- (void)unobserve:(id)object info:(_FBKVOInfo *)info;
|
||||
|
||||
/** unobserve an object with a set of infos */
|
||||
- (void)unobserve:(id)object infos:(NSSet *)infos;
|
||||
|
||||
@end
|
||||
|
||||
@implementation _FBKVOSharedController
|
||||
{
|
||||
NSHashTable *_infos;
|
||||
OSSpinLock _lock;
|
||||
}
|
||||
|
||||
+ (instancetype)sharedController
|
||||
{
|
||||
static _FBKVOSharedController *_controller = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
_controller = [[_FBKVOSharedController alloc] init];
|
||||
});
|
||||
return _controller;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (nil != self) {
|
||||
NSHashTable *infos = [NSHashTable alloc];
|
||||
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||
_infos = [infos initWithOptions:NSPointerFunctionsWeakMemory|NSPointerFunctionsObjectPointerPersonality capacity:0];
|
||||
#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
|
||||
if ([NSHashTable respondsToSelector:@selector(weakObjectsHashTable)]) {
|
||||
_infos = [infos initWithOptions:NSPointerFunctionsWeakMemory|NSPointerFunctionsObjectPointerPersonality capacity:0];
|
||||
} else {
|
||||
// silence deprecated warnings
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
_infos = [infos initWithOptions:NSPointerFunctionsZeroingWeakMemory|NSPointerFunctionsObjectPointerPersonality capacity:0];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
|
||||
#endif
|
||||
_lock = OS_SPINLOCK_INIT;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)debugDescription
|
||||
{
|
||||
NSMutableString *s = [NSMutableString stringWithFormat:@"<%@:%p", NSStringFromClass([self class]), self];
|
||||
|
||||
// lock
|
||||
OSSpinLockLock(&_lock);
|
||||
|
||||
NSMutableArray *infoDescriptions = [NSMutableArray arrayWithCapacity:_infos.count];
|
||||
for (_FBKVOInfo *info in _infos) {
|
||||
[infoDescriptions addObject:info.debugDescription];
|
||||
}
|
||||
|
||||
[s appendFormat:@" contexts:%@", infoDescriptions];
|
||||
|
||||
// unlock
|
||||
OSSpinLockUnlock(&_lock);
|
||||
|
||||
[s appendString:@">"];
|
||||
return s;
|
||||
}
|
||||
|
||||
- (void)observe:(id)object info:(_FBKVOInfo *)info
|
||||
{
|
||||
if (nil == info) {
|
||||
return;
|
||||
}
|
||||
|
||||
// register info
|
||||
OSSpinLockLock(&_lock);
|
||||
[_infos addObject:info];
|
||||
OSSpinLockUnlock(&_lock);
|
||||
|
||||
// add observer
|
||||
[object addObserver:self forKeyPath:info->_keyPath options:info->_options context:(void *)info];
|
||||
}
|
||||
|
||||
- (void)unobserve:(id)object info:(_FBKVOInfo *)info
|
||||
{
|
||||
if (nil == info) {
|
||||
return;
|
||||
}
|
||||
|
||||
// unregister info
|
||||
OSSpinLockLock(&_lock);
|
||||
[_infos removeObject:info];
|
||||
OSSpinLockUnlock(&_lock);
|
||||
|
||||
// remove observer
|
||||
[object removeObserver:self forKeyPath:info->_keyPath context:(void *)info];
|
||||
}
|
||||
|
||||
- (void)unobserve:(id)object infos:(NSSet *)infos
|
||||
{
|
||||
if (0 == infos.count) {
|
||||
return;
|
||||
}
|
||||
|
||||
// unregister info
|
||||
OSSpinLockLock(&_lock);
|
||||
for (_FBKVOInfo *info in infos) {
|
||||
[_infos removeObject:info];
|
||||
}
|
||||
OSSpinLockUnlock(&_lock);
|
||||
|
||||
// remove observer
|
||||
for (_FBKVOInfo *info in infos) {
|
||||
[object removeObserver:self forKeyPath:info->_keyPath context:(void *)info];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
|
||||
{
|
||||
NSAssert(context, @"missing context keyPath:%@ object:%@ change:%@", keyPath, object, change);
|
||||
|
||||
_FBKVOInfo *info;
|
||||
|
||||
{
|
||||
// lookup context in registered infos, taking out a strong reference only if it exists
|
||||
OSSpinLockLock(&_lock);
|
||||
info = [_infos member:(__bridge id)context];
|
||||
OSSpinLockUnlock(&_lock);
|
||||
}
|
||||
|
||||
if (nil != info) {
|
||||
|
||||
// take strong reference to controller
|
||||
FBKVOController *controller = info->_controller;
|
||||
if (nil != controller) {
|
||||
|
||||
// take strong reference to observer
|
||||
id observer = controller.observer;
|
||||
if (nil != observer) {
|
||||
|
||||
// dispatch custom block or action, fall back to default action
|
||||
if (info->_block) {
|
||||
info->_block(observer, object, change);
|
||||
} else if (info->_action) {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
|
||||
[observer performSelector:info->_action withObject:change withObject:object];
|
||||
#pragma clang diagnostic pop
|
||||
} else {
|
||||
[observer observeValueForKeyPath:keyPath ofObject:object change:change context:info->_context];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark FBKVOController -
|
||||
|
||||
@implementation FBKVOController
|
||||
{
|
||||
NSMapTable *_objectInfosMap;
|
||||
OSSpinLock _lock;
|
||||
}
|
||||
|
||||
#pragma mark Lifecycle -
|
||||
|
||||
+ (instancetype)controllerWithObserver:(id)observer
|
||||
{
|
||||
return [[self alloc] initWithObserver:observer];
|
||||
}
|
||||
|
||||
- (instancetype)initWithObserver:(id)observer retainObserved:(BOOL)retainObserved
|
||||
{
|
||||
self = [super init];
|
||||
if (nil != self) {
|
||||
_observer = observer;
|
||||
NSPointerFunctionsOptions keyOptions = retainObserved ? NSPointerFunctionsStrongMemory|NSPointerFunctionsObjectPointerPersonality : NSPointerFunctionsWeakMemory|NSPointerFunctionsObjectPointerPersonality;
|
||||
_objectInfosMap = [[NSMapTable alloc] initWithKeyOptions:keyOptions valueOptions:NSPointerFunctionsStrongMemory|NSPointerFunctionsObjectPersonality capacity:0];
|
||||
_lock = OS_SPINLOCK_INIT;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithObserver:(id)observer
|
||||
{
|
||||
return [self initWithObserver:observer retainObserved:YES];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self unobserveAll];
|
||||
}
|
||||
|
||||
#pragma mark Properties -
|
||||
|
||||
- (NSString *)debugDescription
|
||||
{
|
||||
NSMutableString *s = [NSMutableString stringWithFormat:@"<%@:%p", NSStringFromClass([self class]), self];
|
||||
[s appendFormat:@" observer:<%@:%p>", NSStringFromClass([_observer class]), _observer];
|
||||
|
||||
// lock
|
||||
OSSpinLockLock(&_lock);
|
||||
|
||||
if (0 != _objectInfosMap.count) {
|
||||
[s appendString:@"\n "];
|
||||
}
|
||||
|
||||
for (id object in _objectInfosMap) {
|
||||
NSMutableSet *infos = [_objectInfosMap objectForKey:object];
|
||||
NSMutableArray *infoDescriptions = [NSMutableArray arrayWithCapacity:infos.count];
|
||||
[infos enumerateObjectsUsingBlock:^(_FBKVOInfo *info, BOOL *stop) {
|
||||
[infoDescriptions addObject:info.debugDescription];
|
||||
}];
|
||||
[s appendFormat:@"%@ -> %@", object, infoDescriptions];
|
||||
}
|
||||
|
||||
// unlock
|
||||
OSSpinLockUnlock(&_lock);
|
||||
|
||||
[s appendString:@">"];
|
||||
return s;
|
||||
}
|
||||
|
||||
#pragma mark Utilities -
|
||||
|
||||
- (void)_observe:(id)object info:(_FBKVOInfo *)info
|
||||
{
|
||||
// lock
|
||||
OSSpinLockLock(&_lock);
|
||||
|
||||
NSMutableSet *infos = [_objectInfosMap objectForKey:object];
|
||||
|
||||
// check for info existence
|
||||
_FBKVOInfo *existingInfo = [infos member:info];
|
||||
if (nil != existingInfo) {
|
||||
NSLog(@"observation info already exists %@", existingInfo);
|
||||
|
||||
// unlock and return
|
||||
OSSpinLockUnlock(&_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
// lazilly create set of infos
|
||||
if (nil == infos) {
|
||||
infos = [NSMutableSet set];
|
||||
[_objectInfosMap setObject:infos forKey:object];
|
||||
}
|
||||
|
||||
// add info and oberve
|
||||
[infos addObject:info];
|
||||
|
||||
// unlock prior to callout
|
||||
OSSpinLockUnlock(&_lock);
|
||||
|
||||
[[_FBKVOSharedController sharedController] observe:object info:info];
|
||||
}
|
||||
|
||||
- (void)_unobserve:(id)object info:(_FBKVOInfo *)info
|
||||
{
|
||||
// lock
|
||||
OSSpinLockLock(&_lock);
|
||||
|
||||
// get observation infos
|
||||
NSMutableSet *infos = [_objectInfosMap objectForKey:object];
|
||||
|
||||
// lookup registered info instance
|
||||
_FBKVOInfo *registeredInfo = [infos member:info];
|
||||
|
||||
if (nil != registeredInfo) {
|
||||
[infos removeObject:registeredInfo];
|
||||
|
||||
// remove no longer used infos
|
||||
if (0 == infos.count) {
|
||||
[_objectInfosMap removeObjectForKey:object];
|
||||
}
|
||||
}
|
||||
|
||||
// unlock
|
||||
OSSpinLockUnlock(&_lock);
|
||||
|
||||
// unobserve
|
||||
[[_FBKVOSharedController sharedController] unobserve:object info:registeredInfo];
|
||||
}
|
||||
|
||||
- (void)_unobserve:(id)object
|
||||
{
|
||||
// lock
|
||||
OSSpinLockLock(&_lock);
|
||||
|
||||
NSMutableSet *infos = [_objectInfosMap objectForKey:object];
|
||||
|
||||
// remove infos
|
||||
[_objectInfosMap removeObjectForKey:object];
|
||||
|
||||
// unlock
|
||||
OSSpinLockUnlock(&_lock);
|
||||
|
||||
// unobserve
|
||||
[[_FBKVOSharedController sharedController] unobserve:object infos:infos];
|
||||
}
|
||||
|
||||
- (void)_unobserveAll
|
||||
{
|
||||
// lock
|
||||
OSSpinLockLock(&_lock);
|
||||
|
||||
NSMapTable *objectInfoMaps = [_objectInfosMap copy];
|
||||
|
||||
// clear table and map
|
||||
[_objectInfosMap removeAllObjects];
|
||||
|
||||
// unlock
|
||||
OSSpinLockUnlock(&_lock);
|
||||
|
||||
_FBKVOSharedController *shareController = [_FBKVOSharedController sharedController];
|
||||
|
||||
for (id object in objectInfoMaps) {
|
||||
// unobserve each registered object and infos
|
||||
NSSet *infos = [objectInfoMaps objectForKey:object];
|
||||
[shareController unobserve:object infos:infos];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark API -
|
||||
|
||||
- (void)observe:(id)object keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options block:(FBKVONotificationBlock)block
|
||||
{
|
||||
NSAssert(0 != keyPath.length && NULL != block, @"missing required parameters observe:%@ keyPath:%@ block:%p", object, keyPath, block);
|
||||
if (nil == object || 0 == keyPath.length || NULL == block) {
|
||||
return;
|
||||
}
|
||||
|
||||
// create info
|
||||
_FBKVOInfo *info = [[_FBKVOInfo alloc] initWithController:self keyPath:keyPath options:options block:block];
|
||||
|
||||
// observe object with info
|
||||
[self _observe:object info:info];
|
||||
}
|
||||
|
||||
|
||||
- (void)observe:(id)object keyPaths:(NSArray *)keyPaths options:(NSKeyValueObservingOptions)options block:(FBKVONotificationBlock)block
|
||||
{
|
||||
NSAssert(0 != keyPaths.count && NULL != block, @"missing required parameters observe:%@ keyPath:%@ block:%p", object, keyPaths, block);
|
||||
if (nil == object || 0 == keyPaths.count || NULL == block) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (NSString *keyPath in keyPaths)
|
||||
{
|
||||
[self observe:object keyPath:keyPath options:options block:block];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)observe:(id)object keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options action:(SEL)action
|
||||
{
|
||||
NSAssert(0 != keyPath.length && NULL != action, @"missing required parameters observe:%@ keyPath:%@ action:%@", object, keyPath, NSStringFromSelector(action));
|
||||
NSAssert([_observer respondsToSelector:action], @"%@ does not respond to %@", _observer, NSStringFromSelector(action));
|
||||
if (nil == object || 0 == keyPath.length || NULL == action) {
|
||||
return;
|
||||
}
|
||||
|
||||
// create info
|
||||
_FBKVOInfo *info = [[_FBKVOInfo alloc] initWithController:self keyPath:keyPath options:options action:action];
|
||||
|
||||
// observe object with info
|
||||
[self _observe:object info:info];
|
||||
}
|
||||
|
||||
- (void)observe:(id)object keyPaths:(NSArray *)keyPaths options:(NSKeyValueObservingOptions)options action:(SEL)action
|
||||
{
|
||||
NSAssert(0 != keyPaths.count && NULL != action, @"missing required parameters observe:%@ keyPath:%@ action:%@", object, keyPaths, NSStringFromSelector(action));
|
||||
NSAssert([_observer respondsToSelector:action], @"%@ does not respond to %@", _observer, NSStringFromSelector(action));
|
||||
if (nil == object || 0 == keyPaths.count || NULL == action) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (NSString *keyPath in keyPaths)
|
||||
{
|
||||
[self observe:object keyPath:keyPath options:options action:action];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)observe:(id)object keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
|
||||
{
|
||||
NSAssert(0 != keyPath.length, @"missing required parameters observe:%@ keyPath:%@", object, keyPath);
|
||||
if (nil == object || 0 == keyPath.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// create info
|
||||
_FBKVOInfo *info = [[_FBKVOInfo alloc] initWithController:self keyPath:keyPath options:options context:context];
|
||||
|
||||
// observe object with info
|
||||
[self _observe:object info:info];
|
||||
}
|
||||
|
||||
- (void)observe:(id)object keyPaths:(NSArray *)keyPaths options:(NSKeyValueObservingOptions)options context:(void *)context
|
||||
{
|
||||
NSAssert(0 != keyPaths.count, @"missing required parameters observe:%@ keyPath:%@", object, keyPaths);
|
||||
if (nil == object || 0 == keyPaths.count) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (NSString *keyPath in keyPaths)
|
||||
{
|
||||
[self observe:object keyPath:keyPath options:options context:context];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)unobserve:(id)object keyPath:(NSString *)keyPath
|
||||
{
|
||||
// create representative info
|
||||
_FBKVOInfo *info = [[_FBKVOInfo alloc] initWithController:self keyPath:keyPath];
|
||||
|
||||
// unobserve object property
|
||||
[self _unobserve:object info:info];
|
||||
}
|
||||
|
||||
- (void)unobserve:(id)object
|
||||
{
|
||||
if (nil == object) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self _unobserve:object];
|
||||
}
|
||||
|
||||
- (void)unobserveAll
|
||||
{
|
||||
[self _unobserveAll];
|
||||
}
|
||||
|
||||
@end
|
16
xplan-ios/Base/Tool/NSString/NSString+JsonToDic.h
Normal file
16
xplan-ios/Base/Tool/NSString/NSString+JsonToDic.h
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// NSString+JsonToDic.h
|
||||
// XChatFramework
|
||||
//
|
||||
// Created by 卫明何 on 2017/9/11.
|
||||
// Copyright © 2017年 chenran. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface NSString (JsonToDic)
|
||||
|
||||
+ (NSDictionary *)dictionaryWithJsonString:(NSString *)jsonString;
|
||||
|
||||
+ (id)idWithJsonString:(NSString *)str;
|
||||
@end
|
61
xplan-ios/Base/Tool/NSString/NSString+JsonToDic.m
Normal file
61
xplan-ios/Base/Tool/NSString/NSString+JsonToDic.m
Normal file
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// NSString+JsonToDic.m
|
||||
// XChatFramework
|
||||
//
|
||||
// Created by 卫明何 on 2017/9/11.
|
||||
// Copyright © 2017年 chenran. All rights reserved.
|
||||
//
|
||||
|
||||
#import "NSString+JsonToDic.h"
|
||||
|
||||
@implementation NSString (JsonToDic)
|
||||
|
||||
+ (NSDictionary *)dictionaryWithJsonString:(NSString *)jsonString {
|
||||
|
||||
if (jsonString == nil) {
|
||||
|
||||
return nil;
|
||||
|
||||
}
|
||||
|
||||
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
NSError *err;
|
||||
|
||||
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData
|
||||
|
||||
options:NSJSONReadingMutableContainers
|
||||
|
||||
error:&err];
|
||||
if(err) {
|
||||
|
||||
NSLog(@"json解析失败:%@",err);
|
||||
|
||||
return nil;
|
||||
|
||||
}
|
||||
|
||||
return dic;
|
||||
|
||||
}
|
||||
|
||||
+ (id)idWithJsonString:(NSString *)str {
|
||||
|
||||
if (!str) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSError *error = nil;
|
||||
id jsonObject = [NSJSONSerialization JSONObjectWithData:[str dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments
|
||||
error:nil];
|
||||
|
||||
if (jsonObject != nil && error == nil){
|
||||
return jsonObject;
|
||||
}else{
|
||||
// 解析错误
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@end
|
@@ -0,0 +1,72 @@
|
||||
//
|
||||
// YYWebResourceDownloader.h
|
||||
// YYMobileFramework
|
||||
//
|
||||
// Created by wuwei on 14/6/12.
|
||||
// Copyright (c) 2014年 YY Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
typedef NS_OPTIONS(NSUInteger, YYWebResourceDownloaderOptions) {
|
||||
YYWebResourceDownloaderProgressiveDownload = 1 << 1,
|
||||
YYWebResourceDownloaderUseNSURLCache = 1 << 2,
|
||||
YYWebResourceDownloaderIgnoreCachedResponse = 1 << 3,
|
||||
YYWebResourceDownloaderContinueInBackground = 1 << 4,
|
||||
YYWebResourceDownloaderHandleCookies = 1 << 5,
|
||||
};
|
||||
|
||||
/**
|
||||
* 下载的进度回调
|
||||
*
|
||||
* @param received
|
||||
* @param expected
|
||||
*/
|
||||
typedef void(^YYWebResourceDownloaderProgressBlock)(int64_t received, int64_t expected, CGFloat progress);
|
||||
|
||||
/**
|
||||
* 下载完成回调Block
|
||||
*
|
||||
* @param filePath 下载完成后文件的URL(fileURL)
|
||||
* @param error 下载过程中的错误
|
||||
* @param finished 是否完成
|
||||
*/
|
||||
typedef void(^YYWebResourceDownloaderCompletionBlock)(NSURL *filePath, NSError *error, BOOL finished);
|
||||
|
||||
@class YYWebResourceDownloader;
|
||||
@class YYWebResourceDownloadOperation;
|
||||
|
||||
@interface YYWebResourceDownloadOperation : NSOperation
|
||||
|
||||
@end
|
||||
|
||||
NS_AVAILABLE_IOS(7_0) @interface YYWebResourceDownloader : NSObject
|
||||
|
||||
+ (instancetype)sharedDownloader;
|
||||
|
||||
/**
|
||||
* The designated initializer
|
||||
*
|
||||
* @param name name of the downloader
|
||||
*
|
||||
* @return The initialized YYWebResourceDownloader instance
|
||||
*/
|
||||
- (instancetype)initWithName:(NSString *)name;
|
||||
|
||||
@property (nonatomic, strong, readonly) NSString *downloaderName;
|
||||
|
||||
// default is 15.0
|
||||
@property (nonatomic, assign) NSTimeInterval downloadTimeout;
|
||||
|
||||
@property (nonatomic, strong) NSDictionary*(^headerFilter)(NSURL *url, NSDictionary *headers);
|
||||
|
||||
- (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field;
|
||||
- (NSString *)valueForHTTPHeaderField:(NSString *)field;
|
||||
|
||||
- (YYWebResourceDownloadOperation *)downloadWithURL:(NSURL *)url
|
||||
fileName:(NSString *)fileName
|
||||
options:(YYWebResourceDownloaderOptions)options
|
||||
progress:(YYWebResourceDownloaderProgressBlock)progress
|
||||
completion:(YYWebResourceDownloaderCompletionBlock)completion;
|
||||
|
||||
@end
|
@@ -0,0 +1,415 @@
|
||||
//
|
||||
// YYWebResourceDownloader.m
|
||||
// YYMobileFramework
|
||||
//
|
||||
// Created by wuwei on 14/6/12.
|
||||
// Copyright (c) 2014年 YY Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import "YYWebResourceDownloader.h"
|
||||
#import <AFURLSessionManager.h>
|
||||
#import "FBKVOController.h"
|
||||
|
||||
#if TRAFFIC_DATA
|
||||
#import "../../../../YYMobileCore/YYMobileCore/Cores/CoreManager.h"
|
||||
#import "../../../../YYMobileCore/YYMobileCore/Cores/Carrier/ICarrierService.h"
|
||||
#import "../../../../YYMobileCore/YYMobileCore/Cores/Carrier/CarrierServiceTypes.h"
|
||||
#endif
|
||||
|
||||
#define ENABLE_UNICOM_PROXY 0
|
||||
|
||||
static NSString * const kProgressCallbackKey = @"progress";
|
||||
static NSString * const kCompletionCallbackKey = @"completed";
|
||||
|
||||
#if TRAFFIC_DATA
|
||||
extern NSString * const CarrierDataTrafficPackageSubscribeStateUpdateNotification;
|
||||
#endif
|
||||
|
||||
static const NSTimeInterval kDefaultDownloadTimeout = 15.0f;
|
||||
|
||||
@interface YYWebResourceDownloadOperation ()
|
||||
|
||||
- (instancetype)initWithTask:(NSURLSessionTask *)task;
|
||||
- (instancetype)initWithTask:(NSURLSessionTask *)task cancelledBlock:(dispatch_block_t)cancelBlock;
|
||||
|
||||
@end
|
||||
|
||||
@implementation YYWebResourceDownloadOperation
|
||||
{
|
||||
NSURLSessionTask *_task;
|
||||
dispatch_block_t _cancelBlock;
|
||||
}
|
||||
|
||||
- (instancetype)initWithTask:(NSURLSessionTask *)task {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_task = task;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithTask:(NSURLSessionTask *)task cancelledBlock:(dispatch_block_t)cancel
|
||||
{
|
||||
self = [self initWithTask:task];
|
||||
if (self) {
|
||||
_cancelBlock = cancel;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)cancel {
|
||||
[super cancel];
|
||||
|
||||
[_task cancel];
|
||||
if (_cancelBlock) {
|
||||
_cancelBlock();
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface YYWebResourceDownloader ()
|
||||
|
||||
@property (nonatomic, strong, readonly) AFURLSessionManager *sessionManager;
|
||||
@property (nonatomic, strong) NSURLSessionConfiguration *sessionConfiguration;
|
||||
|
||||
@property (nonatomic, strong, readonly) dispatch_queue_t barrierQueue;
|
||||
@property (nonatomic, strong, readonly) NSMutableDictionary *URLCallbacks;
|
||||
@property (nonatomic, strong, readonly) NSMutableDictionary *HTTPHeaders;
|
||||
@property (nonatomic, strong, readonly) NSMapTable *downloadingTasks;
|
||||
|
||||
@end
|
||||
|
||||
@implementation YYWebResourceDownloader
|
||||
|
||||
@synthesize barrierQueue = _barrierQueue;
|
||||
@synthesize URLCallbacks = _URLCallbacks;
|
||||
@synthesize HTTPHeaders =_HTTPHeaders;
|
||||
@synthesize downloaderName = _downloaderName;
|
||||
@synthesize sessionManager = _sessionManager;
|
||||
|
||||
+ (instancetype)sharedDownloader
|
||||
{
|
||||
static id instance;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
instance = [[self alloc] initWithName:@"default"];
|
||||
});
|
||||
return instance;
|
||||
}
|
||||
|
||||
- (instancetype)initWithName:(NSString *)name
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_downloaderName = name;
|
||||
_downloadingTasks = [NSMapTable strongToWeakObjectsMapTable];
|
||||
|
||||
#if TRAFFIC_DATA
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(OnCarrierDataTrafficPackageSubscribeStateUpdate:) name:CarrierDataTrafficPackageSubscribeStateUpdateNotification object:nil];
|
||||
#endif
|
||||
|
||||
NSURLSessionConfiguration *defaultConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
|
||||
|
||||
/*
|
||||
defaultConfiguration.connectionProxyDictionary = @{
|
||||
(NSString *)kCFStreamPropertyHTTPProxyHost: @"huanjushidai.gzproxy.10155.com",
|
||||
(NSString *)kCFStreamPropertyHTTPProxyPort: @(8080)};
|
||||
|
||||
defaultConfiguration.HTTPAdditionalHeaders = @{@"Authorization": @"Basic MzAwMDAwNDU0NDo5OEI4NTU5MDI0ODYwQkE1NDE2MTUwNDM4NzA2NjdGMQ=="};
|
||||
*/
|
||||
|
||||
_sessionManager = [[AFURLSessionManager alloc] initWithSessionConfiguration:defaultConfiguration];
|
||||
_downloadTimeout = kDefaultDownloadTimeout;
|
||||
_URLCallbacks = [NSMutableDictionary dictionary];
|
||||
_HTTPHeaders = [NSMutableDictionary dictionary];
|
||||
// Create a queue using the downloader name
|
||||
name = name ? : @"<anonymous>";
|
||||
NSString *queueName = [NSString stringWithFormat:@"com.yy.webResourceDownloader.%@.barrierQueue", name];
|
||||
_barrierQueue = dispatch_queue_create([queueName UTF8String], DISPATCH_QUEUE_CONCURRENT);
|
||||
|
||||
static char kBarrierQueueSpecificKey;
|
||||
dispatch_queue_set_specific(self.barrierQueue, &kBarrierQueueSpecificKey, (__bridge void *)self, NULL);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
return [self initWithName:nil];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
- (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field
|
||||
{
|
||||
if (value) {
|
||||
self.HTTPHeaders[field] = value;
|
||||
}
|
||||
else {
|
||||
[self.HTTPHeaders removeObjectForKey:field];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)valueForHTTPHeaderField:(NSString *)field
|
||||
{
|
||||
return self.HTTPHeaders[field];
|
||||
}
|
||||
|
||||
- (YYWebResourceDownloadOperation *)downloadWithURL:(NSURL *)url
|
||||
fileName:(NSString *)fileName
|
||||
options:(YYWebResourceDownloaderOptions)options
|
||||
progress:(YYWebResourceDownloaderProgressBlock)progress
|
||||
completion:(YYWebResourceDownloaderCompletionBlock)completion
|
||||
{
|
||||
#if TRAFFIC_DATA
|
||||
//处理缓存的Session的代理配置
|
||||
if(!_sessionManager)
|
||||
{
|
||||
NSURLSessionConfiguration *defaultConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
|
||||
|
||||
BOOL isDataTrafficeFree = [GetCoreI(ICarrierService) isDataTrafficFree];
|
||||
if(isDataTrafficeFree)
|
||||
{
|
||||
CarrierProxyConfiguration* httpProxyConfiguration = [GetCoreI(ICarrierService) getProxyConfiguration];
|
||||
if(httpProxyConfiguration)
|
||||
{
|
||||
defaultConfiguration.connectionProxyDictionary = @{ (NSString *)kCFStreamPropertyHTTPProxyHost: httpProxyConfiguration.serverAddress,
|
||||
(NSString *)kCFStreamPropertyHTTPProxyPort: @(httpProxyConfiguration.serverPort)};
|
||||
defaultConfiguration.HTTPAdditionalHeaders = @{@"Authorization": [NSString stringWithFormat:@"Basic %@", httpProxyConfiguration.authenticationString]};
|
||||
}
|
||||
self.sessionConfiguration = defaultConfiguration;
|
||||
}
|
||||
|
||||
_sessionManager = [[AFURLSessionManager alloc] initWithSessionConfiguration:self.sessionConfiguration];
|
||||
|
||||
[_sessionManager setTaskWillPerformHTTPRedirectionBlock:^NSURLRequest *(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request) {
|
||||
|
||||
NSMutableURLRequest *redirectRequest = [request mutableCopy];
|
||||
if(isDataTrafficeFree)
|
||||
{
|
||||
CarrierProxyConfiguration* httpProxyConfiguration = [GetCoreI(ICarrierService) getProxyConfiguration];
|
||||
[redirectRequest addValue:[NSString stringWithFormat:@"Basic %@", httpProxyConfiguration.authenticationString] forHTTPHeaderField:@"Authorization"];
|
||||
}
|
||||
return redirectRequest;
|
||||
}];
|
||||
}
|
||||
#endif
|
||||
|
||||
__block YYWebResourceDownloadOperation *downloadOperation = nil;
|
||||
__weak YYWebResourceDownloader *wself = self;
|
||||
|
||||
[self _addProgressCallback:progress andCompletionBlock:completion forURL:url createCallback:^{
|
||||
NSTimeInterval timeoutInterval = wself.downloadTimeout;
|
||||
if (timeoutInterval == 0.0) {
|
||||
timeoutInterval = kDefaultDownloadTimeout;
|
||||
}
|
||||
|
||||
// In order to prevent from potential duplicate caching (NSURLCache + YYImageCache), we disable the cache for image requests if told otherwise
|
||||
NSURLRequestCachePolicy cachePolicy = (options & YYWebResourceDownloaderUseNSURLCache) ? NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData;
|
||||
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url
|
||||
cachePolicy:cachePolicy
|
||||
timeoutInterval:timeoutInterval];
|
||||
request.HTTPShouldHandleCookies = (options & YYWebResourceDownloaderHandleCookies);
|
||||
request.HTTPShouldUsePipelining = YES;
|
||||
if (wself.headerFilter) {
|
||||
request.allHTTPHeaderFields = wself.headerFilter(url, [wself.HTTPHeaders copy]);
|
||||
}
|
||||
else {
|
||||
request.allHTTPHeaderFields = [wself.HTTPHeaders copy];
|
||||
}
|
||||
|
||||
__block NSProgress *progress;
|
||||
__block FBKVOController *controller = [FBKVOController controllerWithObserver:wself];
|
||||
|
||||
__block NSURLSessionTask *sessionTask = [wself.sessionManager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
|
||||
progress = downloadProgress;
|
||||
} destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
|
||||
// return [targetPath URLByAppendingPathExtension:@"download"];
|
||||
NSString *fullPath;
|
||||
if (fileName.length > 0 || fileName) {
|
||||
fullPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:fileName];
|
||||
}else {
|
||||
fullPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename];
|
||||
}
|
||||
|
||||
return [NSURL fileURLWithPath:fullPath];
|
||||
} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
|
||||
if (error) {
|
||||
// [YYLogger debug:TAG(THTTP,TNetSend) message:@"[Task: %@] Download %@ failed with error %@", sessionTask, url, error];
|
||||
} else {
|
||||
// [YYLogger debug:TAG(THTTP,TNetSend) message:@"[Task: %@] Download %@ successfully, store to %@", sessionTask, url, filePath];
|
||||
}
|
||||
|
||||
if (error.code == NSURLErrorCancelled) {
|
||||
// Cancel由YYWebResourceOperation的cancelBlock处理
|
||||
return;
|
||||
}
|
||||
|
||||
if (!wself) return; // return if deallocated
|
||||
__strong __typeof__(wself) sself = wself;
|
||||
NSArray *callbacksForURL = [sself _callbacksForURL:url];
|
||||
[sself _removeCallbacksForURL:url];
|
||||
for (NSDictionary *callbacks in callbacksForURL) {
|
||||
YYWebResourceDownloaderCompletionBlock complete = callbacks[kCompletionCallbackKey];
|
||||
if (complete) {
|
||||
complete(filePath, error, YES);
|
||||
}
|
||||
}
|
||||
|
||||
// 移除文件
|
||||
[[NSFileManager defaultManager] removeItemAtURL:filePath error:nil];
|
||||
|
||||
// Remove KVO
|
||||
controller = nil;
|
||||
|
||||
}];
|
||||
|
||||
// Observe the fractionCompleted property of the progress
|
||||
[controller observe:progress keyPath:@"fractionCompleted" options:NSKeyValueObservingOptionNew block:^(id observer, id object, NSDictionary *change) {
|
||||
if (!wself) return; // return if deallocated
|
||||
__strong __typeof__(wself) sself = wself;
|
||||
NSArray *callbacksForURL = [sself _callbacksForURL:url];
|
||||
for (NSDictionary *callbacks in callbacksForURL) {
|
||||
YYWebResourceDownloaderProgressBlock progressBlock = callbacks[kProgressCallbackKey];
|
||||
if (progressBlock) {
|
||||
progressBlock(progress.completedUnitCount, progress.totalUnitCount, progress.fractionCompleted);
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
|
||||
// [YYLogger debug:TAG(THTTP,TNetSend)message:@"[Task: %@] download %@ DID START!", sessionTask, url];
|
||||
|
||||
downloadOperation = [[YYWebResourceDownloadOperation alloc] initWithTask:sessionTask cancelledBlock:^{
|
||||
__strong __typeof__(wself) sself = wself;
|
||||
if (sself) {
|
||||
[sself _removeCallbacksForURL:url];
|
||||
}
|
||||
}];
|
||||
|
||||
// [wself.downloadingTasks setObject:downloadOperation forKey:url];
|
||||
|
||||
// start the task
|
||||
[sessionTask resume];
|
||||
}];
|
||||
|
||||
return downloadOperation;
|
||||
}
|
||||
|
||||
- (void)_addProgressCallback:(YYWebResourceDownloaderProgressBlock)progress
|
||||
andCompletionBlock:(YYWebResourceDownloaderCompletionBlock)completion
|
||||
forURL:(NSURL *)url
|
||||
createCallback:(dispatch_block_t)createCallback
|
||||
{
|
||||
NSParameterAssert(createCallback);
|
||||
|
||||
if (url == nil) {
|
||||
if (completion != nil) {
|
||||
completion(nil, nil, NO);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch_barrier_sync(self.barrierQueue, ^{
|
||||
|
||||
BOOL first = NO;
|
||||
if (!self.URLCallbacks[url]) {
|
||||
self.URLCallbacks[url] = [NSMutableArray new];
|
||||
first = YES;
|
||||
}
|
||||
|
||||
id task = [self.downloadingTasks objectForKey:url];
|
||||
// [YYLogger debug:TAG(THTTP,TNetSend) message:@"add Callbacks for url %@, existing task: %@, isFirst: %d", url, task, first];
|
||||
|
||||
// Handle single download of simulaneous download request for the same URL
|
||||
NSMutableArray *callbacksForURL = self.URLCallbacks[url];
|
||||
NSMutableDictionary *callbacks = [NSMutableDictionary new];
|
||||
if (progress) {
|
||||
callbacks[kProgressCallbackKey] = [progress copy];
|
||||
}
|
||||
if (completion) {
|
||||
callbacks[kCompletionCallbackKey] = [completion copy];
|
||||
}
|
||||
[callbacksForURL addObject:callbacks];
|
||||
self.URLCallbacks[url] = callbacksForURL;
|
||||
|
||||
if (first) {
|
||||
createCallback();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (NSArray *)_callbacksForURL:(NSURL *)url {
|
||||
__block NSArray *callbacksForURL;
|
||||
dispatch_sync(self.barrierQueue, ^{
|
||||
callbacksForURL = self.URLCallbacks[url];
|
||||
});
|
||||
return [callbacksForURL copy];
|
||||
}
|
||||
|
||||
- (void)_removeCallbacksForURL:(NSURL *)url {
|
||||
dispatch_barrier_async(self.barrierQueue, ^{
|
||||
[self.URLCallbacks removeObjectForKey:url];
|
||||
});
|
||||
}
|
||||
|
||||
#if TRAFFIC_DATA
|
||||
-(void) OnCarrierDataTrafficPackageSubscribeStateUpdate:(NSNotification*)notification
|
||||
{
|
||||
CarrierProxyConfiguration* httpProxyConfiguration = [notification object];
|
||||
if (httpProxyConfiguration && httpProxyConfiguration.serverAddress.length > 0)
|
||||
{
|
||||
NSURLSessionConfiguration *proxyConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
|
||||
proxyConfiguration.connectionProxyDictionary = @{ (NSString *)kCFStreamPropertyHTTPProxyHost: httpProxyConfiguration.serverAddress,
|
||||
(NSString *)kCFStreamPropertyHTTPProxyPort: @(httpProxyConfiguration.serverPort)};
|
||||
proxyConfiguration.HTTPAdditionalHeaders = @{@"Authorization": [NSString stringWithFormat:@"Basic %@", httpProxyConfiguration.authenticationString]};
|
||||
|
||||
|
||||
self.sessionConfiguration = proxyConfiguration;
|
||||
|
||||
if(!_sessionManager)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if([_sessionManager.tasks count] > 0)
|
||||
{
|
||||
[_sessionManager invalidateSessionCancelingTasks:false];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:AFURLSessionDidInvalidateNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(__unused NSNotification *note) {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:AFURLSessionDidInvalidateNotification object:nil];
|
||||
_sessionManager = nil;
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
_sessionManager = nil;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!self.sessionConfiguration)
|
||||
return;
|
||||
|
||||
if([_sessionManager.tasks count] > 0)
|
||||
{
|
||||
[_sessionManager invalidateSessionCancelingTasks:false];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:AFURLSessionDidInvalidateNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(__unused NSNotification *note) {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:AFURLSessionDidInvalidateNotification object:nil];
|
||||
self.sessionConfiguration = nil;
|
||||
_sessionManager = nil;
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
self.sessionConfiguration = nil;
|
||||
_sessionManager = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@end
|
@@ -18,6 +18,8 @@ typedef NS_ENUM(NSUInteger, CustomMessageType) {
|
||||
CustomMessageType_Account = 5,
|
||||
///队列操作
|
||||
CustomMessageType_Queue = 8,
|
||||
///表情
|
||||
CustomMessageType_Face = 9,
|
||||
///全麦送
|
||||
CustomMessageType_AllMicroSend = 12,
|
||||
///座驾进房动画
|
||||
@@ -81,6 +83,12 @@ typedef NS_ENUM(NSInteger, CustomMessageSubQueue) {
|
||||
Custom_Message_Sub_Queue_Kick = 82,
|
||||
};
|
||||
|
||||
//first = CustomMessageType_Face
|
||||
typedef NS_ENUM(NSUInteger, CustomMessageSubFace) {
|
||||
///发送
|
||||
Custom_Message_Sub_Face_Send = 91,
|
||||
};
|
||||
|
||||
///first = CustomMessageType_ALLMicroSend
|
||||
typedef NS_ENUM(NSUInteger, CustomMessageSubAllMicroSend) {
|
||||
///全麦送礼物
|
||||
|
48
xplan-ios/Main/ModuleKit/FaceView/Model/FaceConfigInfo.h
Normal file
48
xplan-ios/Main/ModuleKit/FaceView/Model/FaceConfigInfo.h
Normal file
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// FaceConfigModel.h
|
||||
// xplan-ios
|
||||
//
|
||||
// Created by GreenLand on 2022/1/7.
|
||||
//
|
||||
|
||||
#import "NSObject+MJExtension.h"
|
||||
#import "GiftNobleInfoModel.h"
|
||||
|
||||
typedef enum : NSUInteger {
|
||||
XCFaceDisplayTypeOnlyOne = 0,
|
||||
XCFaceDisplayTypeFlow = 1,
|
||||
XCFaceDisplayTypeOverLay = 2,
|
||||
XCFaceDisplayTypeOnlyOneLine = 3,
|
||||
} XCFaceDisplayType;
|
||||
|
||||
typedef enum : NSUInteger {
|
||||
XCFaceType_Face = 1,//1 正常表情,需要在表情面板显示
|
||||
XCFaceType_Dragon = 2,// 2 龙珠
|
||||
XCFaceType_PlayTogether = 3, //一起玩
|
||||
} XCFaceType;
|
||||
|
||||
@interface FaceConfigInfo : NSObject
|
||||
|
||||
@property (nonatomic, assign) int id;
|
||||
@property (nonatomic, copy) NSString *name;
|
||||
@property (nonatomic, copy) NSString *pinyin;
|
||||
@property (nonatomic, assign) NSInteger animDuration;
|
||||
@property (nonatomic, assign) NSInteger animEndPos;
|
||||
@property (nonatomic, assign) NSInteger animStartPos;
|
||||
@property (nonatomic, assign) NSInteger iconPos;
|
||||
@property (nonatomic, assign) NSInteger animRepeatCount;
|
||||
@property (nonatomic, assign) NSInteger resultCount;
|
||||
@property (nonatomic, assign) BOOL canResultRepeat;
|
||||
@property (nonatomic, assign) NSInteger resultDuration;
|
||||
@property (nonatomic, assign) NSInteger resultEndPos;
|
||||
@property (nonatomic, assign) NSInteger resultStartPos;
|
||||
@property (nonatomic, assign) NSInteger imageCount;
|
||||
@property (nonatomic, assign) XCFaceDisplayType displayType;
|
||||
@property (nonatomic, assign) BOOL isNobleFace; //是否贵族表情
|
||||
@property (nonatomic, assign) int nobleId;//贵族等级
|
||||
@property (nonatomic, assign) XCFaceType faceType;//1 正常表情,需要在表情面板显示, 2 龙珠 3.一起玩
|
||||
@property (nonatomic, assign) BOOL isLuckFace;//YES 表示审核中需要隐藏的表情,NO 审核中不需要隐藏的表情
|
||||
///贵族表情信息
|
||||
@property (nonatomic, strong) GiftNobleInfoModel *faceVipInfo;
|
||||
|
||||
@end
|
12
xplan-ios/Main/ModuleKit/FaceView/Model/FaceConfigInfo.m
Normal file
12
xplan-ios/Main/ModuleKit/FaceView/Model/FaceConfigInfo.m
Normal file
@@ -0,0 +1,12 @@
|
||||
//
|
||||
// FaceConfigModel.m
|
||||
// xplan-ios
|
||||
//
|
||||
// Created by GreenLand on 2022/1/7.
|
||||
//
|
||||
|
||||
#import "FaceConfigInfo.h"
|
||||
|
||||
@implementation FaceConfigInfo
|
||||
|
||||
@end
|
23
xplan-ios/Main/ModuleKit/FaceView/Model/FaceInfo.h
Normal file
23
xplan-ios/Main/ModuleKit/FaceView/Model/FaceInfo.h
Normal file
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// FaceInfo.h
|
||||
// BberryCore
|
||||
//
|
||||
// Created by 卫明何 on 2017/9/29.
|
||||
// Copyright © 2017年 chenran. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface FaceInfo : NSObject
|
||||
|
||||
@property (assign, nonatomic) NSInteger faceId;
|
||||
@property (copy, nonatomic) NSString *faceName;
|
||||
@property (assign, nonatomic) NSInteger faceParentId;
|
||||
@property (copy, nonatomic) NSString *facePicUrl;
|
||||
@property (assign, nonatomic) BOOL hasGifUrl;
|
||||
@property (copy, nonatomic) NSString *faceGifUrl;
|
||||
@property (assign, nonatomic) BOOL show;
|
||||
@property (strong, nonatomic) NSArray *children;
|
||||
@property (assign, nonatomic) NSInteger faceValue;
|
||||
|
||||
@end
|
19
xplan-ios/Main/ModuleKit/FaceView/Model/FaceInfo.m
Normal file
19
xplan-ios/Main/ModuleKit/FaceView/Model/FaceInfo.m
Normal file
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// FaceInfo.m
|
||||
// BberryCore
|
||||
//
|
||||
// Created by 卫明何 on 2017/9/29.
|
||||
// Copyright © 2017年 chenran. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FaceInfo.h"
|
||||
|
||||
@implementation FaceInfo
|
||||
|
||||
+ (nullable NSDictionary<NSString *, id> *)modelContainerPropertyGenericClass{
|
||||
return @{
|
||||
@"children" : FaceInfo.class,
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
16
xplan-ios/Main/ModuleKit/FaceView/Model/FaceInfoStorage.h
Normal file
16
xplan-ios/Main/ModuleKit/FaceView/Model/FaceInfoStorage.h
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// FaceInfoStorage.h
|
||||
// BberryCore
|
||||
//
|
||||
// Created by 卫明何 on 2017/9/29.
|
||||
// Copyright © 2017年 chenran. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface FaceInfoStorage : NSObject
|
||||
|
||||
+ (NSMutableArray *)getFaceInfos;
|
||||
+ (void)saveFaceInfos:(NSString *)json;
|
||||
|
||||
@end
|
48
xplan-ios/Main/ModuleKit/FaceView/Model/FaceInfoStorage.m
Normal file
48
xplan-ios/Main/ModuleKit/FaceView/Model/FaceInfoStorage.m
Normal file
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// FaceInfoStorage.m
|
||||
// BberryCore
|
||||
//
|
||||
// Created by 卫明何 on 2017/9/29.
|
||||
// Copyright © 2017年 chenran. All rights reserved.
|
||||
//
|
||||
|
||||
#define kFileName @"FaceInfoList.data"
|
||||
#define kDataKey @"faceInfos"
|
||||
#define EncodeKey @"1ea53d260ecf11e7b56e00163e046a26123"
|
||||
|
||||
|
||||
#import "FaceInfoStorage.h"
|
||||
#import "FaceInfo.h"
|
||||
#import "DESEncrypt.h"
|
||||
#import "SSKeychain.h"
|
||||
#import "FaceConfigInfo.h"
|
||||
#import <MJExtension/MJExtension.h>
|
||||
|
||||
@implementation FaceInfoStorage
|
||||
|
||||
+ (NSString *)getFilePath {
|
||||
NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
||||
NSString *path = [[array objectAtIndex:0] stringByAppendingPathComponent:kFileName];
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
|
||||
[[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:nil];
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
+ (NSMutableArray *)getFaceInfos{
|
||||
NSMutableArray *faceInfos = [NSMutableArray array];
|
||||
NSString *encodeJson = [SSKeychain passwordForService:@"json" account:@"face"];
|
||||
NSString *decodeJson = [DESEncrypt decryptUseDES:encodeJson key:EncodeKey];
|
||||
if (decodeJson.length > 0) {
|
||||
// faceInfos = [[NSArray yy_modelArrayWithClass:[FaceConfigModel class] json:decodeJson] mutableCopy];
|
||||
faceInfos = [[FaceConfigInfo modelsWithArray:decodeJson] mutableCopy];
|
||||
}
|
||||
return faceInfos;
|
||||
}
|
||||
|
||||
+ (void)saveFaceInfos:(NSString *)json {
|
||||
NSString *encodeJson = [DESEncrypt encryptUseDES:json key:EncodeKey];
|
||||
[SSKeychain setPassword:encodeJson forService:@"json" account:@"face"];
|
||||
}
|
||||
|
||||
@end
|
18
xplan-ios/Main/ModuleKit/FaceView/Model/FacePlayInfo.h
Normal file
18
xplan-ios/Main/ModuleKit/FaceView/Model/FacePlayInfo.h
Normal file
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// FacePlayInfo.h
|
||||
// BberryCore
|
||||
//
|
||||
// Created by 卫明何 on 2017/9/29.
|
||||
// Copyright © 2017年 chenran. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "FaceReceiveInfo.h"
|
||||
|
||||
@interface FacePlayInfo : NSObject
|
||||
|
||||
@property (assign, nonatomic) double delay;
|
||||
@property (strong, nonatomic) NIMMessage *message;
|
||||
@property (strong, nonatomic) FaceReceiveInfo *faceReceiveInfo;
|
||||
|
||||
@end
|
13
xplan-ios/Main/ModuleKit/FaceView/Model/FacePlayInfo.m
Normal file
13
xplan-ios/Main/ModuleKit/FaceView/Model/FacePlayInfo.m
Normal file
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// FacePlayInfo.m
|
||||
// BberryCore
|
||||
//
|
||||
// Created by 卫明何 on 2017/9/29.
|
||||
// Copyright © 2017年 chenran. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FacePlayInfo.h"
|
||||
|
||||
@implementation FacePlayInfo
|
||||
|
||||
@end
|
19
xplan-ios/Main/ModuleKit/FaceView/Model/FaceReceiveInfo.h
Normal file
19
xplan-ios/Main/ModuleKit/FaceView/Model/FaceReceiveInfo.h
Normal file
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// FaceReceiveInfo.h
|
||||
// BberryCore
|
||||
//
|
||||
// Created by 卫明何 on 2017/9/29.
|
||||
// Copyright © 2017年 chenran. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "AttachmentModel.h"
|
||||
|
||||
@interface FaceReceiveInfo : NSObject
|
||||
|
||||
@property (assign, nonatomic)long long uid;
|
||||
@property (copy, nonatomic) NSString *nick;
|
||||
@property (assign, nonatomic) NSInteger faceId;
|
||||
@property (strong, nonatomic) UIImage *resultImage;
|
||||
@property (strong, nonatomic) NSMutableArray *resultIndexes;//骰子数
|
||||
@end
|
13
xplan-ios/Main/ModuleKit/FaceView/Model/FaceReceiveInfo.m
Normal file
13
xplan-ios/Main/ModuleKit/FaceView/Model/FaceReceiveInfo.m
Normal file
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// FaceReceiveInfo.m
|
||||
// BberryCore
|
||||
//
|
||||
// Created by 卫明何 on 2017/9/29.
|
||||
// Copyright © 2017年 chenran. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FaceReceiveInfo.h"
|
||||
|
||||
@implementation FaceReceiveInfo
|
||||
|
||||
@end
|
17
xplan-ios/Main/ModuleKit/FaceView/Model/FaceSendInfo.h
Normal file
17
xplan-ios/Main/ModuleKit/FaceView/Model/FaceSendInfo.h
Normal file
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// FaceSendInfo.h
|
||||
// BberryCore
|
||||
//
|
||||
// Created by 卫明何 on 2017/9/29.
|
||||
// Copyright © 2017年 chenran. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <NIMSDK/NIMSDK.h>
|
||||
|
||||
@interface FaceSendInfo : NSObject<NIMCustomAttachment>
|
||||
|
||||
@property (strong, nonatomic) NSArray *data; //faceRecieveInfos
|
||||
@property (assign, nonatomic) long long uid;
|
||||
@property (copy, nonatomic) NSDictionary *encodeAttachemt;
|
||||
@end
|
32
xplan-ios/Main/ModuleKit/FaceView/Model/FaceSendInfo.m
Normal file
32
xplan-ios/Main/ModuleKit/FaceView/Model/FaceSendInfo.m
Normal file
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// FaceSendInfo.m
|
||||
// BberryCore
|
||||
//
|
||||
// Created by 卫明何 on 2017/9/29.
|
||||
// Copyright © 2017年 chenran. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FaceSendInfo.h"
|
||||
#import "FaceInfo.h"
|
||||
#import "FaceReceiveInfo.h"
|
||||
//#import "NSObject+YYModel.h"
|
||||
|
||||
@implementation FaceSendInfo
|
||||
|
||||
|
||||
- (NSDictionary *)encodeAttachemt {
|
||||
NSDictionary *dict = @{
|
||||
@"data" : self.data,
|
||||
@"uid" : @(self.uid)
|
||||
};
|
||||
return dict;
|
||||
}
|
||||
|
||||
+ (nullable NSDictionary<NSString *, id> *)modelContainerPropertyGenericClass{
|
||||
return @{
|
||||
@"data" : [FaceReceiveInfo class],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@end
|
@@ -5,11 +5,22 @@
|
||||
// Created by GreenLand on 2021/12/28.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "BaseMvpPresenter.h"
|
||||
#import <NIMSDK/NIMSDK.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface XPFacePresenter : NSObject
|
||||
@class FaceConfigInfo, UserInfoModel;
|
||||
@interface XPFacePresenter : BaseMvpPresenter
|
||||
|
||||
/**
|
||||
单独发表情
|
||||
|
||||
@param faceInfo 表情信息
|
||||
@param roomId 房间ID
|
||||
@param sendUser 发送人信息
|
||||
*/
|
||||
- (void)sendFace:(FaceConfigInfo *)faceInfo roomId:(long long)roomId sendUser:(UserInfoModel *)sendUser member:(NIMChatroomMember *)member;
|
||||
|
||||
@end
|
||||
|
||||
|
@@ -6,7 +6,189 @@
|
||||
//
|
||||
|
||||
#import "XPFacePresenter.h"
|
||||
///Tool
|
||||
#import "NSString+JsonToDic.h"
|
||||
#import "NSObject+MJExtension.h"
|
||||
#import <MJExtension/MJExtension.h>
|
||||
//#import "AccountInfoStorage.h"
|
||||
//#import "XPGiftStorage.h"
|
||||
//#import "Api+Gift.h"
|
||||
///Model
|
||||
#import "FaceReceiveInfo.h"
|
||||
#import "FaceConfigInfo.h"
|
||||
#import "FaceSendInfo.h"
|
||||
#import "UserInfoModel.h"
|
||||
///P
|
||||
#import "XPFaceProtocol.h"
|
||||
|
||||
@interface XPFacePresenter ()
|
||||
///
|
||||
@property (nonatomic,weak) id view;
|
||||
|
||||
@end
|
||||
|
||||
@implementation XPFacePresenter
|
||||
|
||||
///先这样写着 想好了在改
|
||||
- (void)attatchView:(id)view {
|
||||
self.view = view;
|
||||
}
|
||||
|
||||
- (id)getView {
|
||||
return self.view;
|
||||
}
|
||||
|
||||
// 单独发表情
|
||||
- (void)sendFace:(FaceConfigInfo *)faceInfo roomId:(long long)roomId sendUser:(UserInfoModel *)sendUser member:(NIMChatroomMember *)member {
|
||||
if (roomId) {
|
||||
FaceReceiveInfo *faceRecieveInfo = [[FaceReceiveInfo alloc]init];
|
||||
NSMutableArray *resultIndexs = [NSMutableArray array];
|
||||
if (faceInfo.resultStartPos > 0 && faceInfo.resultEndPos > 0) {
|
||||
int value;
|
||||
if (faceInfo.canResultRepeat) { //结果可以重复
|
||||
for (int i = 0; i < faceInfo.resultCount; i++) {
|
||||
value = [self getRandomNumber:(short)faceInfo.resultStartPos to:(short)faceInfo.resultEndPos];
|
||||
[resultIndexs addObject:@(value)];
|
||||
faceRecieveInfo.resultIndexes = [resultIndexs copy];
|
||||
}
|
||||
|
||||
}else {
|
||||
faceRecieveInfo.resultIndexes = [[self randomArray:(short)faceInfo.resultStartPos to:(short)faceInfo.resultEndPos count:(short)faceInfo.resultCount] mutableCopy];
|
||||
}
|
||||
|
||||
}
|
||||
NSMutableArray *faceRecieveInfos = [NSMutableArray array];
|
||||
|
||||
faceRecieveInfo.nick = sendUser.nick;
|
||||
faceRecieveInfo.faceId = faceInfo.id;
|
||||
faceRecieveInfo.uid = sendUser.uid;
|
||||
[faceRecieveInfos addObject:faceRecieveInfo];
|
||||
|
||||
FaceSendInfo *sendInfo = [[FaceSendInfo alloc]init];
|
||||
sendInfo.data = [FaceReceiveInfo mj_keyValuesArrayWithObjectArray:faceRecieveInfos];
|
||||
sendInfo.uid = sendUser.uid;
|
||||
|
||||
AttachmentModel *attachment = [[AttachmentModel alloc]init];
|
||||
attachment.first = CustomMessageType_Face;
|
||||
attachment.second = Custom_Message_Sub_Face_Send;
|
||||
attachment.data = [sendInfo encodeAttachemt];
|
||||
|
||||
NSString *sessionID = [NSString stringWithFormat:@"%lld",roomId];
|
||||
[self sendCustomMessageAttachement:attachment sessionId:sessionID type:NIMSessionTypeChatroom member:member];
|
||||
}
|
||||
}
|
||||
|
||||
///发送表情消息
|
||||
- (void)sendCustomMessageAttachement:(AttachmentModel *)attachment sessionId:(NSString *)sessionId type:(NIMSessionType)type member:(NIMChatroomMember *)member {
|
||||
NIMMessage *message = [[NIMMessage alloc]init];
|
||||
//yidun
|
||||
NIMAntiSpamOption *option = [NIMAntiSpamOption new];
|
||||
option.yidunEnabled = NO;
|
||||
|
||||
NSMutableDictionary *meRoomExt = nil;
|
||||
meRoomExt = [[NSString dictionaryWithJsonString:member.roomExt] mutableCopy];
|
||||
|
||||
NIMCustomObject *customObject = [[NIMCustomObject alloc]init];
|
||||
customObject.attachment = attachment;
|
||||
message.messageObject = customObject;
|
||||
|
||||
// NSMutableDictionary *memberExtDic = [GetCore(ImRoomCoreV2) queryOnMicroMemberExt];
|
||||
NSMutableDictionary *realMeExt = meRoomExt;
|
||||
[realMeExt removeObjectForKey:@"banner"];
|
||||
[realMeExt removeObjectForKey:@"open_effect"];
|
||||
[realMeExt removeObjectForKey:@"halo"];
|
||||
[realMeExt removeObjectForKey:@"headwear"];
|
||||
[realMeExt removeObjectForKey:@"recommend"];
|
||||
[realMeExt removeObjectForKey:@"pic"];
|
||||
[realMeExt removeObjectForKey:@"cardbg"];
|
||||
[realMeExt removeObjectForKey:@"zonebg"];
|
||||
|
||||
// [memberExtDic setValuesForKeysWithDictionary:meRoomExt];
|
||||
|
||||
if (type == NIMSessionTypeChatroom) {
|
||||
message.remoteExt = meRoomExt;
|
||||
}
|
||||
message.antiSpamOption = option;
|
||||
|
||||
NIMMessageSetting *setting = [[NIMMessageSetting alloc]init];
|
||||
message.setting = setting;
|
||||
//构造会话
|
||||
NIMSession *session = [NIMSession session:sessionId type:type];
|
||||
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil];
|
||||
}
|
||||
|
||||
- (void)sendMessageCollectionRequestWithMessage:(NIMMessage *)message firstAttachment:(int)firstAttachment {
|
||||
|
||||
// if (GetCore(ClientCore).reportSwitch) {
|
||||
//
|
||||
// int remoteDataLength;
|
||||
// if (message.remoteExt) {
|
||||
// NSData *remoteData = [NSJSONSerialization dataWithJSONObject:message.remoteExt options:0 error:nil];
|
||||
// remoteDataLength = (int)remoteData.length;
|
||||
// }else {
|
||||
// remoteDataLength = 0;
|
||||
// }
|
||||
//
|
||||
// int messageTextDataLength;
|
||||
// if (message.text) {
|
||||
// NSData *messageTextData = [message.text dataUsingEncoding:NSUTF8StringEncoding];
|
||||
// messageTextDataLength = (int)messageTextData.length;
|
||||
// }else {
|
||||
// messageTextDataLength = 0;
|
||||
// }
|
||||
//
|
||||
// int messageSize = (int)(messageTextDataLength + sizeof(message.messageObject) + remoteDataLength);
|
||||
//
|
||||
// self.messageCollectionDict = @{
|
||||
// @"uid":@([message.from intValue]),
|
||||
// @"sessionType":@(message.session.sessionType),
|
||||
// @"sessionId":@([message.session.sessionId intValue]),
|
||||
// @"packetSize":@(messageSize),
|
||||
// @"messageType":@(message.messageType),
|
||||
// @"chatroomMemberNumber":@(GetCore(ImRoomCoreV2).onlineNumber),
|
||||
// @"attachementId":@(firstAttachment)
|
||||
// };
|
||||
// }
|
||||
}
|
||||
#pragma mark - private
|
||||
/**
|
||||
生成随机数
|
||||
|
||||
@param from 最小值
|
||||
@param to 最大值
|
||||
@return 随机数
|
||||
*/
|
||||
- (int)getRandomNumber:(int)from to:(int)to {
|
||||
return (int)(from + (arc4random() % (to - from + 1)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
生成固定区间的不重复随机数
|
||||
|
||||
@param from 最小值
|
||||
@param to 最大值
|
||||
@param count 数量
|
||||
@return 返回值
|
||||
*/
|
||||
- (NSArray *)randomArray:(int)from to:(int)to count:(int)count {
|
||||
|
||||
//随机数从这里边产生
|
||||
NSMutableArray *startArray= [NSMutableArray array];
|
||||
for (int i = from; i <= to; i++) {
|
||||
[startArray addObject:@(i)];
|
||||
}
|
||||
|
||||
//随机数产生结果
|
||||
NSMutableArray *resultArray=[[NSMutableArray alloc] initWithCapacity:0];
|
||||
//随机数个数
|
||||
NSInteger m = count;
|
||||
for (int i=0; i<m; i++) {
|
||||
int t = arc4random()%startArray.count;
|
||||
resultArray[i]=startArray[t];
|
||||
startArray[t]=[startArray lastObject]; //为更好的乱序,故交换下位置
|
||||
[startArray removeLastObject];
|
||||
}
|
||||
return resultArray;
|
||||
}
|
||||
@end
|
||||
|
16
xplan-ios/Main/ModuleKit/FaceView/Procotol/XPFaceProtocol.h
Normal file
16
xplan-ios/Main/ModuleKit/FaceView/Procotol/XPFaceProtocol.h
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// XPFaceProtocol.h
|
||||
// xplan-ios
|
||||
//
|
||||
// Created by GreenLand on 2022/1/8.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface XPFaceProtocol : NSObject
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
12
xplan-ios/Main/ModuleKit/FaceView/Procotol/XPFaceProtocol.m
Normal file
12
xplan-ios/Main/ModuleKit/FaceView/Procotol/XPFaceProtocol.m
Normal file
@@ -0,0 +1,12 @@
|
||||
//
|
||||
// XPFaceProtocol.m
|
||||
// xplan-ios
|
||||
//
|
||||
// Created by GreenLand on 2022/1/8.
|
||||
//
|
||||
|
||||
#import "XPFaceProtocol.h"
|
||||
|
||||
@implementation XPFaceProtocol
|
||||
|
||||
@end
|
@@ -10,6 +10,13 @@
|
||||
|
||||
@class FaceConfigInfo;
|
||||
|
||||
@protocol XCGameRoomFaceContainerCellDelegate <NSObject>
|
||||
|
||||
///选中的表情
|
||||
- (void)onSelectFace:(FaceConfigInfo *)faceInfo;
|
||||
|
||||
@end
|
||||
|
||||
@interface XCGameRoomFaceContainerCell : UICollectionViewCell
|
||||
|
||||
/**
|
||||
@@ -22,4 +29,6 @@
|
||||
*/
|
||||
@property (strong, nonatomic) NSMutableArray<FaceConfigInfo *> *faceInfos;
|
||||
|
||||
@property (nonatomic, weak) id<XCGameRoomFaceContainerCellDelegate> delegate;
|
||||
|
||||
@end
|
||||
|
@@ -24,6 +24,8 @@
|
||||
|
||||
//tool
|
||||
//#import "XCAlertControllerCenter.h"
|
||||
#import "XPFaceParser.h"
|
||||
#import "NSArray+Lookin.h"
|
||||
|
||||
|
||||
@interface XCGameRoomFaceContainerCell()
|
||||
@@ -79,12 +81,15 @@ UICollectionViewDelegateFlowLayout
|
||||
#pragma mark - UICollectionViewDelegate
|
||||
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
self.currentIndexPath = indexPath;
|
||||
// FaceConfigInfo *info = [self.faceInfos safeObjectAtIndex:indexPath.row];
|
||||
//
|
||||
// if (![GetCore(FaceCore) getShowingFace]) {
|
||||
FaceConfigInfo *info = [self.faceInfos lookin_safeObjectAtIndex:indexPath.row];
|
||||
|
||||
if (![[XPFaceParser shareParser] getShowingFace]) {
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(onSelectFace:)]) {
|
||||
[self.delegate onSelectFace:info];
|
||||
}
|
||||
// [GetCore(FaceCore) sendFace:info];
|
||||
// [[XCAlertControllerCenter defaultCenter]dismissAlertNeedBlock:NO];
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - UICollectionViewDataSource
|
||||
@@ -103,9 +108,9 @@ UICollectionViewDelegateFlowLayout
|
||||
|
||||
FaceConfigInfo *info = self.faceInfos[indexPath.row];
|
||||
//读取图片
|
||||
// UIImage *face = [GetCore(FaceCore) findFaceIconImageById:info.id];
|
||||
// [cell.faceImageView setImage:face];
|
||||
// [cell.faceName setText:info.name];
|
||||
UIImage *face = [[XPFaceParser shareParser] findFaceIconImageById:info.id];
|
||||
[cell.faceImageView setImage:face];
|
||||
[cell.faceName setText:info.name];
|
||||
|
||||
cell.nobleTagImageView.hidden = YES;
|
||||
}
|
||||
|
@@ -15,18 +15,15 @@
|
||||
///Third
|
||||
#import <Masonry/Masonry.h>
|
||||
#import "NSArray+Lookin.h"
|
||||
#import <ReactiveObjC/ReactiveObjC.h>
|
||||
///tool
|
||||
#import "XPMacro.h"
|
||||
|
||||
//core
|
||||
//#import "FaceCore.h"
|
||||
//#import "VersionCore.h"
|
||||
|
||||
//client
|
||||
//#import "FaceSourceClient.h"
|
||||
|
||||
#import "XPFaceParser.h"
|
||||
///P
|
||||
#import "XPFacePresenter.h"
|
||||
//model
|
||||
//#import "FaceInfo.h"
|
||||
#import "UserInfoModel.h"
|
||||
#import "RoomInfoModel.h"
|
||||
//#import "FaceConfigInfo.h"
|
||||
//#import "AuthCore.h"
|
||||
//#import "UserCore.h"
|
||||
@@ -51,7 +48,8 @@
|
||||
UICollectionViewDelegate,
|
||||
UICollectionViewDataSource,
|
||||
UICollectionViewDelegateFlowLayout,
|
||||
UIScrollViewDelegate
|
||||
UIScrollViewDelegate,
|
||||
XCGameRoomFaceContainerCellDelegate
|
||||
>
|
||||
|
||||
/**
|
||||
@@ -96,6 +94,10 @@
|
||||
///房主的uid
|
||||
@property (nonatomic,copy) NSString *roomUid;
|
||||
|
||||
@property (nonatomic,strong) XPFacePresenter *facePresenter;
|
||||
|
||||
@property (nonatomic, strong) NIMChatroomMember *myMember;
|
||||
|
||||
@end
|
||||
|
||||
@implementation XPRoomFaceView
|
||||
@@ -106,7 +108,6 @@
|
||||
|
||||
self.roomUid = uid;
|
||||
[self initView];
|
||||
// [self addCore];
|
||||
[self initConstrations];
|
||||
}
|
||||
return self;
|
||||
@@ -183,6 +184,8 @@
|
||||
((XCGameRoomFaceTitleCell *)cell).displayModel = [self.displayModel.titles lookin_safeObjectAtIndex:indexPath.row];
|
||||
}else if ([cell isKindOfClass:[XCGameRoomFaceContainerCell class]]) {
|
||||
((XCGameRoomFaceContainerCell *)cell).faceInfos = [self.faceInfos lookin_safeObjectAtIndex:indexPath.section];
|
||||
XCGameRoomFaceContainerCell *faceCell = (XCGameRoomFaceContainerCell *)cell;
|
||||
faceCell.delegate = self;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,6 +221,12 @@
|
||||
self.pageControl.currentPage = intPage;
|
||||
}
|
||||
|
||||
#pragma mark - XCGameRoomFaceContainerCellDelegate
|
||||
///选中的表情
|
||||
- (void)onSelectFace:(FaceConfigInfo *)faceInfo {
|
||||
[self.facePresenter sendFace:faceInfo roomId:[self.delegate getRoomInfo].roomId sendUser:[self.delegate getUserInfo] member:self.myMember];
|
||||
}
|
||||
|
||||
#pragma mark - FaceSourceClient
|
||||
|
||||
- (void)loadFaceSourceSuccess {
|
||||
@@ -248,11 +257,11 @@
|
||||
[self.faceCollectionView registerClass:[XCGameRoomFaceCell class] forCellWithReuseIdentifier:@"XCGameRoomFaceCell"];
|
||||
[self.faceCollectionView registerClass:[XCGameRoomFaceContainerCell class] forCellWithReuseIdentifier:@"XCGameRoomFaceContainerCell"];
|
||||
|
||||
// if (GetCore(FaceCore).isLoadFace) {
|
||||
// [self loadFace];
|
||||
// }else {
|
||||
if ([XPFaceParser shareParser].isLoadFace) {
|
||||
[self loadFace];
|
||||
}else {
|
||||
// [UIView showToastInKeyWindow:@"表情准备中" duration:3.0 position:(YYToastPosition)YYToastPositionBottomWithRecordButton];
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
- (void)initConstrations {
|
||||
@@ -314,7 +323,7 @@
|
||||
//如果没有贵族,默认只显示男爵表情,因为没有枚举,这里 hard code =1
|
||||
__block NSUInteger nobleLevel = 1;
|
||||
|
||||
// if (self.userInfo == nil) {
|
||||
// if (self.delegate.getUserInfo == nil) {
|
||||
// [[GetCore(UserCore) getUserInfoByRac:GetCore(AuthCore).getUid.userIDValue refresh:NO] subscribeNext:^(id x) {
|
||||
// if ([x isKindOfClass:UserInfo.class]) {
|
||||
// self.userInfo = x;
|
||||
@@ -332,7 +341,7 @@
|
||||
self.faceInfos = [[self nobleFaceFilterByNobleLevel:nobleLevel] mutableCopy];
|
||||
|
||||
}else{
|
||||
// self.faceInfos = [GetCore(FaceCore) getFaceInfosType:RoomFaceTypeNormal];
|
||||
self.faceInfos = [[XPFaceParser shareParser] getFaceInfosType:RoomFaceTypeNormal];
|
||||
}
|
||||
|
||||
self.pageControl.hidden = NO;
|
||||
@@ -340,7 +349,14 @@
|
||||
[self.faceCollectionView reloadData];
|
||||
}
|
||||
|
||||
|
||||
- (void)getMember {
|
||||
[[self rac_queryChartRoomMemberByUid:[NSString stringWithFormat:@"%zd",self.delegate.getUserInfo.uid]] subscribeNext:^(id x) {
|
||||
NIMChatroomMember *roomOwner = x;
|
||||
if (roomOwner.isOnline) {
|
||||
self.myMember = roomOwner;
|
||||
}
|
||||
}];
|
||||
}
|
||||
/**
|
||||
根据贵族等级筛选贵族表情,只获取不大于当前等级的表情
|
||||
|
||||
@@ -349,31 +365,55 @@
|
||||
@return 贵族表情列表
|
||||
*/
|
||||
- (NSArray<FaceConfigInfo *> *)nobleFaceFilterByNobleLevel:(NSUInteger)level {
|
||||
// NSArray *faces = [[[GetCore(FaceCore) getFaceInfosType:RoomFaceTypeNoble] copy] firstObject];
|
||||
// if (faces.count == 0) {
|
||||
// return @[];
|
||||
// }
|
||||
//
|
||||
// //默认获取最低贵族男爵
|
||||
// if (level < 1) {
|
||||
// level = 1;
|
||||
// }
|
||||
//
|
||||
// NSMutableArray *mArray = [NSMutableArray array];
|
||||
// for (FaceConfigInfo *face in faces) {
|
||||
// if (face.nobleId <= level) {
|
||||
// [mArray addObject:face];
|
||||
// }
|
||||
// }
|
||||
NSArray *faces = [[[[XPFaceParser shareParser] getFaceInfosType:RoomFaceTypeNoble] copy] firstObject];
|
||||
if (faces.count == 0) {
|
||||
return @[];
|
||||
}
|
||||
|
||||
//默认获取最低贵族男爵
|
||||
if (level < 1) {
|
||||
level = 1;
|
||||
}
|
||||
|
||||
NSMutableArray *mArray = [NSMutableArray array];
|
||||
for (FaceConfigInfo *face in faces) {
|
||||
if (face.nobleId <= level) {
|
||||
[mArray addObject:face];
|
||||
}
|
||||
}
|
||||
|
||||
NSArray *conbineArray = @[];
|
||||
// if (mArray.count > 0) {
|
||||
// conbineArray = @[[mArray copy]];
|
||||
// }
|
||||
if (mArray.count > 0) {
|
||||
conbineArray = @[[mArray copy]];
|
||||
}
|
||||
return conbineArray;
|
||||
}
|
||||
|
||||
//根据uid获取chartroommember
|
||||
- (RACSignal *)rac_queryChartRoomMemberByUid:(NSString *)uid {
|
||||
if (uid == nil || uid.length<=0) return nil;
|
||||
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
|
||||
NIMChatroomMembersByIdsRequest *request = [[NIMChatroomMembersByIdsRequest alloc]init];
|
||||
request.roomId = [NSString stringWithFormat:@"%zd", self.delegate.getRoomInfo.roomId];
|
||||
request.userIds = @[uid];
|
||||
[[NIMSDK sharedSDK].chatroomManager fetchChatroomMembersByIds:request completion:^(NSError * _Nullable error, NSArray<NIMChatroomMember *> * _Nullable members) {
|
||||
if (error == nil) {
|
||||
[subscriber sendNext:members.firstObject];
|
||||
[subscriber sendCompleted];
|
||||
}else {
|
||||
[subscriber sendNext:nil];
|
||||
}
|
||||
|
||||
}];
|
||||
return nil;
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Getter & Setter
|
||||
- (void)setDelegate:(id<RoomHostDelegate>)delegate {
|
||||
_delegate = delegate;
|
||||
[self getMember];
|
||||
}
|
||||
|
||||
- (UICollectionView *)titlesCollectionView {
|
||||
if (!_titlesCollectionView) {
|
||||
@@ -450,4 +490,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (XPFacePresenter *)facePresenter {
|
||||
if (!_facePresenter) {
|
||||
_facePresenter = [[XPFacePresenter alloc] init];
|
||||
[_facePresenter attatchView:self];
|
||||
}
|
||||
return _facePresenter;
|
||||
}
|
||||
|
||||
@end
|
||||
|
155
xplan-ios/Main/ModuleKit/FaceView/XPFaceParser/XPFaceParser.h
Normal file
155
xplan-ios/Main/ModuleKit/FaceView/XPFaceParser/XPFaceParser.h
Normal file
@@ -0,0 +1,155 @@
|
||||
//
|
||||
// XPFaceParser.h
|
||||
// xplan-ios
|
||||
//
|
||||
// Created by GreenLand on 2022/1/8.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "FaceInfo.h"
|
||||
#import "FaceConfigInfo.h"
|
||||
#import "AttachmentModel.h"
|
||||
#import "XCGameRoomFaceTitleDisplayModel.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface XPFaceParser : NSObject
|
||||
|
||||
+ (instancetype)shareParser;
|
||||
|
||||
- (void)getFaceDataSuccess:(NSArray *)array;
|
||||
|
||||
@property (copy, nonatomic) NSString *version;
|
||||
@property (copy, nonatomic) NSString *zipMd5;
|
||||
@property (strong, nonatomic) NSURL *zipUrl;
|
||||
|
||||
@property (assign, nonatomic) BOOL isShowingFace;
|
||||
@property (copy, nonatomic) NSString *destinationUrl;
|
||||
@property (assign, nonatomic) BOOL isLoadFace;
|
||||
@property (nonatomic, strong) FaceConfigInfo *dragonConfigInfo;//龙族资源
|
||||
@property (nonatomic, assign) BOOL isSendingDragon;//是否正在发送 龙珠 也就是是否 发送云信消息 成功
|
||||
@property (nonatomic, assign) BOOL canPlayTogether; //是否可以一起玩
|
||||
|
||||
/**
|
||||
清除表情的内存缓存(收到内存警告的时候使用)
|
||||
*/
|
||||
- (void)cleanFaceMemoryCache;
|
||||
|
||||
/**
|
||||
获取表情列表
|
||||
|
||||
@return 表情列表
|
||||
*/
|
||||
- (NSMutableArray *)getFaceInfosType:(RoomFaceType)faceType;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
是否正在播放表情
|
||||
|
||||
@return return value description
|
||||
*/
|
||||
- (BOOL)getShowingFace;
|
||||
|
||||
|
||||
/**
|
||||
群发表情
|
||||
|
||||
@param faceInfo 表情信息
|
||||
*/
|
||||
- (void)sendAllFace:(FaceConfigInfo *)faceInfo;
|
||||
|
||||
/**
|
||||
发送表情给cp
|
||||
|
||||
@param faceInfo 表情信息
|
||||
*/
|
||||
- (void)sendToCpFace:(FaceConfigInfo *)faceInfo;
|
||||
|
||||
/**
|
||||
发送龙珠
|
||||
|
||||
@param state 龙珠状态
|
||||
*/
|
||||
//- (void)sendDragonWithState:(CustomNotificationDragon)state;
|
||||
|
||||
|
||||
/**
|
||||
获取一起玩表情(骰子)
|
||||
|
||||
@return 表情信息
|
||||
*/
|
||||
- (FaceConfigInfo *)getPlayTogetherFace;
|
||||
|
||||
|
||||
/**
|
||||
通过表情ID找表情
|
||||
|
||||
@param faceId 表情ID
|
||||
@return 表情信息
|
||||
*/
|
||||
- (FaceConfigInfo *)findFaceInfoById:(NSInteger)faceId;
|
||||
|
||||
|
||||
/**
|
||||
通过表情ID查到图片对象
|
||||
|
||||
@param faceId 表情ID
|
||||
@return 表情图片对象
|
||||
*/
|
||||
- (UIImage *)findFaceIconImageById:(NSInteger)faceId;
|
||||
|
||||
|
||||
/**
|
||||
通过表情ID与Index找图片对象
|
||||
|
||||
@param faceId 表情ID
|
||||
@param index 表情Index
|
||||
@return 表情对象
|
||||
*/
|
||||
- (UIImage *)findFaceImageById:(NSInteger)faceId index:(NSInteger)index;
|
||||
|
||||
|
||||
/**
|
||||
通过表情ConfigInfo查找图片
|
||||
|
||||
@param configInfo 表情配置
|
||||
@param index 位置pos
|
||||
@return 表情图片对象
|
||||
*/
|
||||
- (UIImage *)findFaceImageByConfig:(FaceConfigInfo *)configInfo index:(NSInteger)index;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
通过Config查找图片数组
|
||||
|
||||
@param configInfo 表情配置
|
||||
@return 表情图片对象数组
|
||||
*/
|
||||
- (NSMutableArray<UIImage *> *)findFaceFrameArrByConfig:(FaceConfigInfo *)configInfo;
|
||||
|
||||
|
||||
/**
|
||||
通过FaceId查找图片对象数组
|
||||
|
||||
@param faceId 表情ID
|
||||
@return 图片对象数组
|
||||
*/
|
||||
- (NSMutableArray<UIImage *> *)findFaceFrameArrByFaceId:(NSInteger)faceId;
|
||||
|
||||
|
||||
/**
|
||||
请求Face数据
|
||||
*/
|
||||
//- (void)requestFaceJson;
|
||||
|
||||
|
||||
/**
|
||||
测试使用接口,发送一起玩表情
|
||||
*/
|
||||
- (void)startFaceTimer;
|
||||
- (void)cancelFaceTimer;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
855
xplan-ios/Main/ModuleKit/FaceView/XPFaceParser/XPFaceParser.m
Normal file
855
xplan-ios/Main/ModuleKit/FaceView/XPFaceParser/XPFaceParser.m
Normal file
@@ -0,0 +1,855 @@
|
||||
//
|
||||
// XPFaceParser.m
|
||||
// xplan-ios
|
||||
//
|
||||
// Created by GreenLand on 2022/1/8.
|
||||
//
|
||||
|
||||
#import "XPFaceParser.h"
|
||||
#import "FaceInfoStorage.h"
|
||||
|
||||
#import "FaceReceiveInfo.h"
|
||||
#import "FaceSendInfo.h"
|
||||
#import "FaceInfo.h"
|
||||
//#import "RoomInfo.h"
|
||||
#import "FacePlayInfo.h"
|
||||
#import "FaceConfigInfo.h"
|
||||
///tool
|
||||
#import "YYWebResourceDownloader.h"
|
||||
#import "CommonFileUtils.h"
|
||||
#import "SSKeychain.h"
|
||||
#import "SSZipArchive.h"
|
||||
#import <ReactiveObjC/ReactiveObjC.h>
|
||||
#import "GCDHelper.h"
|
||||
|
||||
///third
|
||||
#import "NSObject+MJExtension.h"
|
||||
#import <MJExtension/MJExtension.h>
|
||||
// model
|
||||
#import "AttachmentModel.h"
|
||||
//#import "NSObject+YYModel.h"
|
||||
|
||||
//#import "VersionCore.h"
|
||||
//#import "ImRoomCoreV2.h"
|
||||
//#import "RoomCoreV2.h"
|
||||
//#import "UserCore.h"
|
||||
//#import "AuthCore.h"
|
||||
//#import "ImMessageCore.h"
|
||||
//#import "ImMessageCoreClient.h"
|
||||
//#import "FaceCoreClient.h"
|
||||
//#import "FaceSourceClient.h"
|
||||
//#import "AuthCoreClient.h"
|
||||
//#import "AppInitClient.h"
|
||||
|
||||
@interface XPFaceParser()
|
||||
<
|
||||
SSZipArchiveDelegate
|
||||
>
|
||||
|
||||
#define RETRYCOUNT 5;
|
||||
|
||||
@property(nonatomic, strong)NSMutableArray *faceInfos; //FaceConfigInfo
|
||||
@property(nonatomic, strong)NSMutableArray *tempFaceInfos; //获取下来的新数据,需要等新的zip包下载完才会去复制到faceInfos
|
||||
@property (nonatomic ,strong)dispatch_source_t timer;
|
||||
@property (nonatomic ,strong)dispatch_source_t testTimer; //测试用定时器
|
||||
@property(atomic, strong)NSMutableArray *receiveFace;
|
||||
@property (strong, nonatomic) NSCache *faceCache;
|
||||
@property (nonatomic, assign) NSInteger *requestJsonCount; //请求json重试计数器
|
||||
@property (nonatomic,assign) NSInteger retryDelay;
|
||||
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@implementation XPFaceParser
|
||||
{
|
||||
dispatch_queue_t zipQueue;
|
||||
}
|
||||
|
||||
+ (instancetype)shareParser {
|
||||
static dispatch_once_t onceToken;
|
||||
static XPFaceParser * parser;
|
||||
dispatch_once(&onceToken, ^{
|
||||
parser = [[XPFaceParser alloc] init];
|
||||
});
|
||||
return parser;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
// AddCoreClient(ImMessageCoreClient, self);
|
||||
// AddCoreClient(AuthCoreClient, self);
|
||||
// AddCoreClient(AppInitClient, self);
|
||||
zipQueue = dispatch_queue_create("com.yy.face.xcface.unzipFace", DISPATCH_QUEUE_SERIAL);
|
||||
_faceInfos = [FaceInfoStorage getFaceInfos];
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
//- (void)dealloc {
|
||||
// RemoveCoreClientAll(self);
|
||||
//}
|
||||
|
||||
- (void)cleanFaceMemoryCache {
|
||||
[self.faceCache removeAllObjects];
|
||||
}
|
||||
|
||||
- (void)faceDownloadManager {
|
||||
NSString *version = [[NSUserDefaults standardUserDefaults]objectForKey:@"faceJsonVersion"];
|
||||
if (version) {
|
||||
if ([version integerValue] < [self.version integerValue]) {
|
||||
[self downloadZipForFace];
|
||||
return;
|
||||
}else {
|
||||
self.isLoadFace = YES;
|
||||
[self syncTheTmpJsonToNormalJson];//save
|
||||
self.destinationUrl = [self getDestinationUrlStr];
|
||||
// NotifyCoreClient(FaceSourceClient, @selector(loadFaceSourceSuccess), loadFaceSourceSuccess);
|
||||
}
|
||||
}else {
|
||||
[self downloadZipForFace];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)syncTheTmpJsonToNormalJson {
|
||||
self.faceInfos = [self.tempFaceInfos mutableCopy];
|
||||
// [[self.faceInfos model2dictionary] toJSONString]
|
||||
// NSData *data = [NSJSONSerialization dataWithJSONObject:self.faceInfos options:NSJSONWritingPrettyPrinted error:nil];
|
||||
// NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
||||
NSArray *array = [FaceConfigInfo mj_keyValuesArrayWithObjectArray:self.faceInfos];
|
||||
[FaceInfoStorage saveFaceInfos:[array toJSONString]];
|
||||
}
|
||||
|
||||
- (void)downloadZipForFace {
|
||||
if ([self.zipUrl absoluteString].length > 0 && [[self.zipUrl absoluteString] containsString:@"http"]) {
|
||||
@weakify(self);
|
||||
[[YYWebResourceDownloader sharedDownloader]downloadWithURL:self.zipUrl fileName:@"face.zip" options:(YYWebResourceDownloaderOptions)YYWebResourceDownloaderProgressiveDownload progress:^(int64_t received, int64_t expected, CGFloat progress) {
|
||||
|
||||
} completion:^(NSURL *filePath, NSError *error, BOOL finished) {
|
||||
|
||||
@strongify(self);
|
||||
if (error == nil) {
|
||||
NSString *desPath = [self getFaceImagePath];
|
||||
[CommonFileUtils createDirForPath:desPath];
|
||||
NSString *filePathStr = [filePath path];
|
||||
NSString *fileMD5Str = [CommonFileUtils getFileMD5WithPath:filePathStr];
|
||||
fileMD5Str = [fileMD5Str uppercaseString];
|
||||
if (![self.zipMd5 isEqualToString:fileMD5Str]) { //MD5校验 如果不相等就重新下载
|
||||
[self performSelector:@selector(downloadZipForFace) withObject:nil afterDelay:3];
|
||||
}else {
|
||||
dispatch_async(self->zipQueue, ^{ //子线程解压
|
||||
|
||||
[SSZipArchive unzipFileAtPath:filePathStr toDestination:desPath overwrite:YES password:nil progressHandler:^(NSString * _Nonnull entry, unz_file_info zipInfo, long entryNumber, long total) {
|
||||
|
||||
} completionHandler:^(NSString * _Nonnull path, BOOL succeeded, NSError * _Nullable error) {
|
||||
dispatch_main_sync_safe(^{
|
||||
if (succeeded) {
|
||||
self.isLoadFace = YES;
|
||||
[self syncTheTmpJsonToNormalJson];
|
||||
self.destinationUrl = [self getDestinationUrlStr];
|
||||
[[NSUserDefaults standardUserDefaults]setObject:self.version forKey:@"faceJsonVersion"];
|
||||
// NotifyCoreClient(FaceSourceClient, @selector(loadFaceSourceSuccess), loadFaceSourceSuccess);
|
||||
}else {
|
||||
[self performSelector:@selector(downloadZipForFace) withObject:nil afterDelay:3];
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}];
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}else {
|
||||
[self performSelector:@selector(downloadZipForFace) withObject:nil afterDelay:3];
|
||||
}
|
||||
|
||||
|
||||
}];
|
||||
}else {
|
||||
self.isLoadFace = NO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (NSString *)getFaceImagePath {
|
||||
NSString *path = @"Documents/Face/";
|
||||
NSString *savePath = [NSHomeDirectory() stringByAppendingPathComponent:path];
|
||||
return savePath;
|
||||
}
|
||||
|
||||
- (NSString *)getDestinationUrlStr {
|
||||
NSString *path = @"Documents/Face/";
|
||||
NSString *savePath = [NSHomeDirectory() stringByAppendingPathComponent:path];
|
||||
NSFileManager *fm = [NSFileManager defaultManager];
|
||||
NSArray *arr = [fm contentsOfDirectoryAtPath:savePath error:nil];
|
||||
NSMutableArray *tempArr = [NSMutableArray array];
|
||||
|
||||
for (NSString *item in arr) {
|
||||
if (![item containsString:@"."]) {
|
||||
[tempArr addObject:item];
|
||||
}
|
||||
}
|
||||
|
||||
while(tempArr.count < 5 && tempArr){
|
||||
if (tempArr.count > 0) {
|
||||
for (NSString *item in arr) {
|
||||
if (![item containsString:@"."]) {
|
||||
savePath = [savePath stringByAppendingString:[NSString stringWithFormat:@"/%@",tempArr[0]]];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
tempArr = [[fm contentsOfDirectoryAtPath:savePath error:nil] mutableCopy];
|
||||
}
|
||||
|
||||
return savePath;
|
||||
}
|
||||
|
||||
|
||||
- (FaceConfigInfo *)findFaceInfoById:(NSInteger)faceId{
|
||||
if (self.faceInfos != nil) {
|
||||
for (int i = 0; i < self.faceInfos.count; i++) {
|
||||
FaceConfigInfo *faceInfo = self.faceInfos[i];
|
||||
if (faceInfo.id == faceId) {
|
||||
return faceInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
//根据id查找表情iCON图片对象
|
||||
- (UIImage *)findFaceIconImageById:(NSInteger)faceId {
|
||||
FaceConfigInfo *configInfo = [self findFaceInfoById:faceId];
|
||||
NSString *faceName = [NSString stringWithFormat:@"%@_%d_%ld",configInfo.pinyin,configInfo.id,configInfo.iconPos];
|
||||
UIImage *face;
|
||||
face = [self.faceCache objectForKey:faceName];
|
||||
if (face) {
|
||||
return face;
|
||||
}else {
|
||||
NSString *dirName = [NSString stringWithFormat:@"%@_%d",configInfo.pinyin,configInfo.id];
|
||||
NSString *targetPath = [NSString stringWithFormat:@"%@/%@/%@",self.destinationUrl,dirName,faceName];
|
||||
face = [UIImage imageWithContentsOfFile:targetPath];
|
||||
if (face) {
|
||||
[self.faceCache setObject:face forKey:faceName];
|
||||
}
|
||||
return face;
|
||||
}
|
||||
}
|
||||
|
||||
//查找图片数组
|
||||
- (NSMutableArray<UIImage *> *)findFaceFrameArrByFaceId:(NSInteger)faceId {
|
||||
FaceConfigInfo *configInfo = [self findFaceInfoById:faceId];
|
||||
return [self findFaceFrameArrByConfig:configInfo];
|
||||
}
|
||||
|
||||
//查找图片数组
|
||||
- (NSMutableArray<UIImage *> *)findFaceFrameArrByConfig:(FaceConfigInfo *)configInfo {
|
||||
NSMutableArray *faceArr = [NSMutableArray array];
|
||||
for (int i = (short)configInfo.animStartPos; i <= (short)configInfo.animEndPos; i++) {
|
||||
[faceArr addObject:[self findFaceImageByConfig:configInfo index:i]];
|
||||
}
|
||||
return faceArr;
|
||||
}
|
||||
|
||||
//查找图片
|
||||
- (UIImage *)findFaceImageById:(NSInteger)faceId index:(NSInteger)index {
|
||||
FaceConfigInfo *configInfo = [self findFaceInfoById:faceId];
|
||||
return [self findFaceImageByConfig:configInfo index:index];
|
||||
}
|
||||
|
||||
//查找图片
|
||||
- (UIImage *)findFaceImageByConfig:(FaceConfigInfo *)configInfo index:(NSInteger)index {
|
||||
NSString *faceName = [NSString stringWithFormat:@"%@_%d_%ld",configInfo.pinyin,configInfo.id,(long)index];
|
||||
UIImage *face;
|
||||
face = [self.faceCache objectForKey:faceName];
|
||||
if (face) {
|
||||
return face;
|
||||
}else {
|
||||
NSString *dirName = [NSString stringWithFormat:@"%@_%d",configInfo.pinyin,configInfo.id];
|
||||
NSString *targetPath = [NSString stringWithFormat:@"%@/%@/%@",self.destinationUrl,dirName,faceName];
|
||||
face = [UIImage imageWithContentsOfFile:targetPath];
|
||||
if (face) {
|
||||
[self.faceCache setObject:face forKey:faceName];
|
||||
}
|
||||
return face;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSMutableArray *)sortFaceInfosWithfaceInfoArr:(NSMutableArray *)faceInfoArr {
|
||||
NSMutableArray *temp = [NSMutableArray array];
|
||||
NSMutableArray *temp2 = [NSMutableArray array]; //运气表情
|
||||
for (FaceConfigInfo *item in faceInfoArr) {
|
||||
if (item.resultCount <= 0) {
|
||||
[temp addObject:item];
|
||||
}else {
|
||||
[temp2 addObject:item];
|
||||
}
|
||||
}
|
||||
[temp addObjectsFromArray:temp2];
|
||||
return temp;
|
||||
}
|
||||
|
||||
- (NSMutableArray *)getFaceInfosType:(RoomFaceType)faceType {
|
||||
NSMutableArray *arr = [NSMutableArray array];
|
||||
NSMutableArray *resultArr = [NSMutableArray array];
|
||||
|
||||
for (int i = 0; i < self.faceInfos.count; i++) {
|
||||
FaceConfigInfo *item = self.faceInfos[i];
|
||||
if (faceType == RoomFaceTypeNormal && !item.faceVipInfo) {
|
||||
// if (GetCore(VersionCore).loadingData) {
|
||||
if (!item.isLuckFace && item.faceType == XCFaceType_Face) {
|
||||
[arr addObject:item];
|
||||
}
|
||||
// }else{
|
||||
// if (item.faceType == XCFaceType_Face) {
|
||||
// [arr addObject:item];
|
||||
// }
|
||||
// }
|
||||
|
||||
}else if(faceType == RoomFaceTypeNoble && item.faceVipInfo){///贵族表情
|
||||
// UserInfo *myInfo = [GetCore(UserCore) getUserInfoInDB:GetCore(AuthCore).getUid.userIDValue];
|
||||
if (item.nobleId<=1) {
|
||||
[arr addObject:item];
|
||||
}
|
||||
|
||||
}
|
||||
if (arr.count == 15) {
|
||||
[resultArr addObject:arr];
|
||||
arr = [NSMutableArray array];
|
||||
}
|
||||
if ( i%15 != 0 && i == self.faceInfos.count - 1) {
|
||||
if (arr.count) {
|
||||
[resultArr addObject:arr];
|
||||
}
|
||||
}
|
||||
}
|
||||
return resultArr;
|
||||
}
|
||||
|
||||
//一起玩
|
||||
- (void)sendAllFace:(FaceConfigInfo *)faceInfo {
|
||||
if (faceInfo) {
|
||||
// if (GetCore(ImRoomCoreV2).isInRoom) {
|
||||
// NSMutableArray *chatroomMembers = GetCore(ImRoomCoreV2).micMembers;
|
||||
// NSMutableArray *faceRecieveInfos = [NSMutableArray array];
|
||||
// // FaceConfigInfo *child = [[FaceConfigInfo alloc]init];
|
||||
// //麦序成员的配置
|
||||
// if (chatroomMembers != nil && chatroomMembers.count > 0) {
|
||||
// for (int i = 0; i < chatroomMembers.count; i++) {
|
||||
// FaceReceiveInfo *faceRecieveInfo = [[FaceReceiveInfo alloc]init];
|
||||
// if (faceInfo.resultStartPos > 0 && faceInfo.resultEndPos > 0) {
|
||||
// int value = [self getRandomNumber:(short)faceInfo.resultStartPos to:(short)faceInfo.resultEndPos];
|
||||
// //插入结果
|
||||
// faceRecieveInfo.resultIndexes = [@[@(value)]mutableCopy];
|
||||
// }
|
||||
// NIMChatroomMember *chatRoomMember = chatroomMembers[i];
|
||||
//
|
||||
// faceRecieveInfo.nick = chatRoomMember.roomNickname;
|
||||
// faceRecieveInfo.uid = chatRoomMember.userId.userIDValue;
|
||||
// faceRecieveInfo.faceId = faceInfo.id;
|
||||
// // if (child != nil) {
|
||||
// // faceRecieveInfo.faceId = child.faceId;
|
||||
// // }else {
|
||||
// // faceRecieveInfo.faceId = faceInfo.faceId;
|
||||
// // }
|
||||
//
|
||||
// [faceRecieveInfos addObject:faceRecieveInfo];
|
||||
//
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// FaceSendInfo *sendInfo = [[FaceSendInfo alloc]init];
|
||||
// sendInfo.data = faceRecieveInfos;
|
||||
// // sendInfo.uid = info.uid;
|
||||
// sendInfo.uid = [GetCore(AuthCore)getUid].userIDValue;
|
||||
//
|
||||
// Attachment *attachment = [[Attachment alloc]init];
|
||||
// attachment.first = Custom_Noti_Header_Face;
|
||||
// attachment.second = Custom_Noti_Sub_Face_Send;
|
||||
// attachment.data = sendInfo.encodeAttachemt;
|
||||
//
|
||||
// NSString *sessionID = [NSString stringWithFormat:@"%ld",GetCore(ImRoomCoreV2).currentRoomInfo.roomId];
|
||||
// [GetCore(ImMessageCore)sendCustomMessageAttachement:attachment sessionId:sessionID type:NIMSessionTypeChatroom];
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
- (void)sendFace:(FaceConfigInfo *)faceInfo {
|
||||
// RoomInfo *info = GetCore(ImRoomCoreV2).currentRoomInfo;
|
||||
// if (info != nil) {
|
||||
// FaceReceiveInfo *faceRecieveInfo = [[FaceReceiveInfo alloc]init];
|
||||
// NSMutableArray *resultIndexs = [NSMutableArray array];
|
||||
// if (faceInfo.resultStartPos > 0 && faceInfo.resultEndPos > 0) {
|
||||
// int value;
|
||||
// if (faceInfo.canResultRepeat) { //结果可以重复
|
||||
// for (int i = 0; i < faceInfo.resultCount; i++) {
|
||||
// value = [self getRandomNumber:(short)faceInfo.resultStartPos to:(short)faceInfo.resultEndPos];
|
||||
// [resultIndexs addObject:@(value)];
|
||||
// faceRecieveInfo.resultIndexes = [resultIndexs copy];
|
||||
// }
|
||||
//
|
||||
// }else {
|
||||
// faceRecieveInfo.resultIndexes = [[self randomArray:(short)faceInfo.resultStartPos to:(short)faceInfo.resultEndPos count:(short)faceInfo.resultCount] mutableCopy];
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // UserInfo *info = [GetCore(UserCore)getUserInfo:[GetCore(AuthCore)getUid].userIDValue refresh:NO];
|
||||
// UserInfo *info = [GetCore(UserCore) getUserInfoInDB:[GetCore(AuthCore)getUid].userIDValue];
|
||||
// NSMutableArray *faceRecieveInfos = [NSMutableArray array];
|
||||
//
|
||||
// faceRecieveInfo.nick = info.nick;
|
||||
// faceRecieveInfo.faceId = faceInfo.id;
|
||||
// faceRecieveInfo.uid = info.uid;
|
||||
// [faceRecieveInfos addObject:faceRecieveInfo];
|
||||
//
|
||||
// FaceSendInfo *sendInfo = [[FaceSendInfo alloc]init];
|
||||
// sendInfo.data = faceRecieveInfos;
|
||||
// sendInfo.uid = info.uid;
|
||||
//
|
||||
// Attachment *attachment = [[Attachment alloc]init];
|
||||
// attachment.first = Custom_Noti_Header_Face;
|
||||
// attachment.second = Custom_Noti_Sub_Face_Send;
|
||||
// attachment.data = sendInfo.encodeAttachemt;
|
||||
// NSString *sessionID = [NSString stringWithFormat:@"%ld",GetCore(ImRoomCoreV2).currentRoomInfo.roomId];
|
||||
// [GetCore(ImMessageCore)sendCustomMessageAttachement:attachment sessionId:sessionID type:NIMSessionTypeChatroom];
|
||||
//
|
||||
// }
|
||||
}
|
||||
- (void)sendToCpFace:(FaceConfigInfo *)faceInfo {
|
||||
// GetCore(ImRoomCoreV2).myMember.roomExt = @"";
|
||||
// if ( GetCore(ImRoomCoreV2).p2pUid > 0) {
|
||||
// FaceReceiveInfo *faceRecieveInfo = [[FaceReceiveInfo alloc]init];
|
||||
// NSMutableArray *resultIndexs = [NSMutableArray array];
|
||||
// if (faceInfo.resultStartPos > 0 && faceInfo.resultEndPos > 0) {
|
||||
// int value;
|
||||
// if (faceInfo.canResultRepeat) { //结果可以重复
|
||||
// for (int i = 0; i < faceInfo.resultCount; i++) {
|
||||
// value = [self getRandomNumber:(short)faceInfo.resultStartPos to:(short)faceInfo.resultEndPos];
|
||||
// [resultIndexs addObject:@(value)];
|
||||
// faceRecieveInfo.resultIndexes = [resultIndexs copy];
|
||||
// }
|
||||
//
|
||||
// }else {
|
||||
// faceRecieveInfo.resultIndexes = [[self randomArray:(short)faceInfo.resultStartPos to:(short)faceInfo.resultEndPos count:(short)faceInfo.resultCount] mutableCopy];
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // UserInfo *info = [GetCore(UserCore)getUserInfo:[GetCore(AuthCore)getUid].userIDValue refresh:NO];
|
||||
// UserInfo *info = [GetCore(UserCore) getUserInfoInDB:[GetCore(AuthCore)getUid].userIDValue];
|
||||
// NSMutableArray *faceRecieveInfos = [NSMutableArray array];
|
||||
//
|
||||
// faceRecieveInfo.nick = info.nick;
|
||||
// faceRecieveInfo.faceId = faceInfo.id;
|
||||
// faceRecieveInfo.uid = info.uid;
|
||||
// [faceRecieveInfos addObject:faceRecieveInfo];
|
||||
//
|
||||
// FaceSendInfo *sendInfo = [[FaceSendInfo alloc]init];
|
||||
// sendInfo.data = faceRecieveInfos;
|
||||
// sendInfo.uid = info.uid;
|
||||
//
|
||||
// Attachment *attachment = [[Attachment alloc]init];
|
||||
// attachment.first = Custom_Noti_Header_Face;
|
||||
// attachment.second = Custom_Noti_Sub_Face_Send;
|
||||
// attachment.data = sendInfo.encodeAttachemt;
|
||||
// NSString *sessionID = [NSString stringWithFormat:@"%ld",GetCore(ImRoomCoreV2).p2pUid];
|
||||
// [GetCore(ImMessageCore)sendCustomMessageAttachement:attachment sessionId:sessionID type:NIMSessionTypeP2P];
|
||||
//
|
||||
// }
|
||||
}
|
||||
|
||||
//发送龙珠
|
||||
//- (void)sendDragonWithState:(CustomNotificationDragon)state {
|
||||
// if (state == Custom_Noti_Sub_Dragon_Start) {
|
||||
// RoomInfo *info = GetCore(ImRoomCoreV2).currentRoomInfo;
|
||||
// UserID uid = GetCore(AuthCore).getUid.longLongValue;
|
||||
// @weakify(self);
|
||||
// [GetCore(RoomCoreV2) getDragonWithRoomUid:info.uid uid:uid success:^(NSArray *ballList,BOOL isNew) {
|
||||
// @strongify(self);
|
||||
// FaceConfigInfo *dragonInfo = self.dragonConfigInfo;
|
||||
// if (info != nil) {
|
||||
// FaceReceiveInfo *faceRecieveInfo = [[FaceReceiveInfo alloc]init];
|
||||
// NSMutableArray *resultIndexs = [NSMutableArray array];
|
||||
// if (dragonInfo.resultStartPos > 0 && dragonInfo.resultEndPos > 0) {
|
||||
// for (NSString *number in ballList) {
|
||||
// [resultIndexs addObject:@(number.intValue+dragonInfo.resultStartPos)];
|
||||
// }
|
||||
// faceRecieveInfo.resultIndexes = [resultIndexs copy];
|
||||
//
|
||||
// }
|
||||
// UserInfo *info = [GetCore(UserCore) getUserInfoInDB:[GetCore(AuthCore)getUid].userIDValue];
|
||||
// NSMutableArray *faceRecieveInfos = [NSMutableArray array];
|
||||
//
|
||||
// faceRecieveInfo.nick = info.nick;
|
||||
// faceRecieveInfo.faceId = dragonInfo.id;
|
||||
// faceRecieveInfo.uid = info.uid;
|
||||
// [faceRecieveInfos addObject:faceRecieveInfo];
|
||||
//
|
||||
//
|
||||
//
|
||||
// // 17,34,40
|
||||
// FaceSendInfo *sendInfo = [[FaceSendInfo alloc]init];
|
||||
// sendInfo.data = faceRecieveInfos;
|
||||
// sendInfo.uid = info.uid;
|
||||
//
|
||||
// //保存当前结果 用于发送 开启龙珠 或 放弃龙珠
|
||||
//
|
||||
// GetCore(RoomCoreV2).currenDragonFaceSendInfo = sendInfo;
|
||||
// Attachment *attachment = [[Attachment alloc]init];
|
||||
// attachment.first = Custom_Noti_Header_Dragon;
|
||||
// if (isNew) {
|
||||
// attachment.second = Custom_Noti_Sub_Dragon_Start;
|
||||
// }else {
|
||||
// attachment.second = Custom_Noti_Sub_Dragon_Continue;
|
||||
// }
|
||||
// attachment.data = sendInfo.encodeAttachemt;
|
||||
// NSString *sessionID = [NSString stringWithFormat:@"%ld",GetCore(ImRoomCoreV2).currentRoomInfo.roomId];
|
||||
// [GetCore(ImMessageCore)sendCustomMessageAttachement:attachment sessionId:sessionID type:NIMSessionTypeChatroom];
|
||||
// }
|
||||
// } failure:^(NSNumber *code, NSString *msg) {
|
||||
//
|
||||
//
|
||||
//
|
||||
// }];
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// }else {
|
||||
// //开启龙珠或是 弃牌
|
||||
// if (!GetCore(RoomCoreV2).currenDragonFaceSendInfo) {
|
||||
// return;
|
||||
// }
|
||||
// Attachment *attachment = [[Attachment alloc]init];
|
||||
// attachment.first = Custom_Noti_Header_Dragon;
|
||||
// attachment.second = state;
|
||||
// attachment.data = GetCore(RoomCoreV2).currenDragonFaceSendInfo.encodeAttachemt;
|
||||
// NSString *sessionID = [NSString stringWithFormat:@"%ld",GetCore(ImRoomCoreV2).currentRoomInfo.roomId];
|
||||
// [GetCore(ImMessageCore)sendCustomMessageAttachement:attachment sessionId:sessionID type:NIMSessionTypeChatroom];
|
||||
// }
|
||||
//
|
||||
//
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma mark - ImMessageCoreClient
|
||||
- (void)onSendMessageSuccess:(NIMMessage *)msg {
|
||||
if (msg.messageType == NIMMessageTypeCustom) {
|
||||
NIMCustomObject *obj = (NIMCustomObject *)msg.messageObject;
|
||||
// if (obj.attachment != nil && [obj.attachment isKindOfClass:[Attachment class]]) {
|
||||
// Attachment *attachment = (Attachment *)obj.attachment;
|
||||
// if (attachment.first == Custom_Noti_Header_Face) {
|
||||
// if (attachment.second == Custom_Noti_Sub_Face_Send) {
|
||||
// FaceSendInfo *faceattachement = [FaceSendInfo yy_modelWithJSON:attachment.data];
|
||||
// NSMutableArray *arr = [faceattachement.data mutableCopy];
|
||||
// NotifyCoreClient(FaceCoreClient, @selector(onReceiveFace:), onReceiveFace:arr);
|
||||
// if (arr.count > 0) {
|
||||
// FaceReceiveInfo *faceRecieveInfo = arr.firstObject;
|
||||
// FaceConfigInfo *faceInfo = [self findFaceInfoById:faceRecieveInfo.faceId];
|
||||
// if (faceInfo.id > 1 && faceInfo != nil && faceRecieveInfo.resultIndexes.count > 0) {
|
||||
// FacePlayInfo *playInfo = [[FacePlayInfo alloc]init];
|
||||
// playInfo.delay = 3;
|
||||
// playInfo.faceReceiveInfo = arr.firstObject;
|
||||
// playInfo.message = msg;
|
||||
// for (FaceReceiveInfo *item in arr) {
|
||||
// if (item.uid == [GetCore(AuthCore) getUid].userIDValue) {
|
||||
// self.isShowingFace = YES;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// [self handleFaceMessage:playInfo];
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }else if (attachment.first == Custom_Noti_Header_Dragon){
|
||||
// //模拟自己接受自己的信息
|
||||
// NotifyCoreClient(RoomCoreClient, @selector(onRecvChatRoomDragonMsg:), onRecvChatRoomDragonMsg:msg);
|
||||
//
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
- (void)onRecvChatRoomCustomMsg:(NIMMessage *)msg {
|
||||
if (msg.messageType == NIMMessageTypeCustom) {
|
||||
NIMCustomObject *obj = (NIMCustomObject *)msg.messageObject;
|
||||
// if (obj.attachment != nil && [obj.attachment isKindOfClass:[Attachment class]]) {
|
||||
// Attachment *attachment = (Attachment *)obj.attachment;
|
||||
// if (attachment.first == Custom_Noti_Header_Face) {
|
||||
// if (attachment.second == Custom_Noti_Sub_Face_Send) {
|
||||
// FaceSendInfo *faceattachement = [FaceSendInfo yy_modelWithJSON:attachment.data];
|
||||
//
|
||||
// NSMutableArray *arr = [faceattachement.data mutableCopy];
|
||||
// NotifyCoreClient(FaceCoreClient, @selector(onReceiveFace:), onReceiveFace:arr);
|
||||
// if (arr.count > 0) {
|
||||
// FaceReceiveInfo *faceRecieveInfo = arr.firstObject;
|
||||
// FaceConfigInfo *faceInfo = [self findFaceInfoById:faceRecieveInfo.faceId];
|
||||
// if (faceInfo.id > 1 && faceInfo != nil && faceRecieveInfo.resultIndexes.count > 0) {
|
||||
// FacePlayInfo *playInfo = [[FacePlayInfo alloc]init];
|
||||
// playInfo.delay = 3;
|
||||
// playInfo.faceReceiveInfo = arr.firstObject;
|
||||
// playInfo.message = msg;
|
||||
// for (FaceReceiveInfo *item in arr) {
|
||||
// if (item.uid == [GetCore(AuthCore) getUid].userIDValue) {
|
||||
// self.isShowingFace = YES;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// [self handleFaceMessage:playInfo];
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// }else if (attachment.first == Custom_Noti_Header_Dragon) {
|
||||
// //龙珠信息
|
||||
//
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//龙珠 发送失败
|
||||
- (void)onSendDragonMessageFailthWithMsg:(NIMMessage *)msg error:(NSError *)error {
|
||||
NSString *errormsg = [NSString stringWithFormat:@"错误码%ld,%@",(long)error.code,error.description];
|
||||
// NotifyCoreClient(FaceCoreClient, @selector(onDragonSendFailth:), onDragonSendFailth:errormsg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma mark - AppInitClient
|
||||
- (void)getFaceDataSuccess:(NSArray *)faceArr {
|
||||
self.tempFaceInfos = [self sortFaceInfosWithfaceInfoArr:[faceArr mutableCopy]]; //表情排序
|
||||
|
||||
[self faceDownloadManager];
|
||||
// NotifyCoreClient(FaceCoreClient, @selector(onGetFaceJsonSuccess), onGetFaceJsonSuccess);
|
||||
}
|
||||
|
||||
#pragma mark - Face Play Method
|
||||
|
||||
- (void)handleFaceMessage:(FacePlayInfo *)facePlayInfo {
|
||||
[self.receiveFace addObject:facePlayInfo];
|
||||
if (self.timer== nil) {
|
||||
[self startTheFaceQueueScanner];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)startTheFaceQueueScanner {
|
||||
NSTimeInterval period = 1; //设置时间间隔
|
||||
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
|
||||
dispatch_source_set_timer(_timer, dispatch_walltime(NULL, 0), period * NSEC_PER_SEC, 0); //每1秒执行
|
||||
@weakify(self);
|
||||
dispatch_source_set_event_handler(_timer, ^{
|
||||
@strongify(self);
|
||||
if (self.receiveFace.count > 0) {
|
||||
NSMutableArray *tempArr = [NSMutableArray array];
|
||||
NSMutableArray *temp = [self.receiveFace mutableCopy];
|
||||
for (FacePlayInfo *item in temp) {
|
||||
item.delay = item.delay - 1;
|
||||
if (item.delay == 0) {
|
||||
self.isShowingFace = NO;
|
||||
if ([NSThread isMainThread])
|
||||
{
|
||||
// NotifyCoreClient(FaceCoreClient, @selector(onFaceIsResult:), onFaceIsResult:item);
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
//Update UI in UI thread here
|
||||
// NotifyCoreClient(FaceCoreClient, @selector(onFaceIsResult:), onFaceIsResult:item);
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
}else {
|
||||
[tempArr addObject:item];
|
||||
}
|
||||
}
|
||||
self.receiveFace = tempArr;
|
||||
} else {
|
||||
dispatch_source_cancel(_timer);
|
||||
self.timer = nil;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
dispatch_resume(_timer);
|
||||
self.timer = _timer;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
|
||||
/**
|
||||
生成固定区间的不重复随机数
|
||||
|
||||
@param from 最小值
|
||||
@param to 最大值
|
||||
@param count 数量
|
||||
@return 返回值
|
||||
*/
|
||||
- (NSArray *)randomArray:(int)from to:(int)to count:(int)count {
|
||||
|
||||
//随机数从这里边产生
|
||||
NSMutableArray *startArray= [NSMutableArray array];
|
||||
for (int i = from; i <= to; i++) {
|
||||
[startArray addObject:@(i)];
|
||||
}
|
||||
|
||||
//随机数产生结果
|
||||
NSMutableArray *resultArray=[[NSMutableArray alloc] initWithCapacity:0];
|
||||
//随机数个数
|
||||
NSInteger m = count;
|
||||
for (int i=0; i<m; i++) {
|
||||
int t = arc4random()%startArray.count;
|
||||
resultArray[i]=startArray[t];
|
||||
startArray[t]=[startArray lastObject]; //为更好的乱序,故交换下位置
|
||||
[startArray removeLastObject];
|
||||
}
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
/**
|
||||
生成随机数
|
||||
|
||||
@param from 最小值
|
||||
@param to 最大值
|
||||
@return 随机数
|
||||
*/
|
||||
- (int)getRandomNumber:(int)from to:(int)to {
|
||||
return (int)(from + (arc4random() % (to - from + 1)));
|
||||
}
|
||||
|
||||
- (BOOL)isEnableFace:(FaceConfigInfo *)info {
|
||||
if (info.displayType != XCFaceDisplayTypeOnlyOne && info.displayType != XCFaceDisplayTypeFlow && info.displayType != XCFaceDisplayTypeOverLay) {
|
||||
return NO;
|
||||
}else {
|
||||
return YES;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#pragma mark - Getter
|
||||
|
||||
|
||||
- (FaceConfigInfo *)dragonConfigInfo {
|
||||
if (_dragonConfigInfo) {
|
||||
return _dragonConfigInfo;
|
||||
}
|
||||
__block FaceConfigInfo *find;
|
||||
[self.faceInfos enumerateObjectsUsingBlock:^(FaceConfigInfo* _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
//龙珠表情
|
||||
|
||||
if (obj.id == 40) {
|
||||
find = obj;
|
||||
*stop = YES;
|
||||
}
|
||||
|
||||
}];
|
||||
|
||||
_dragonConfigInfo = find;
|
||||
return _dragonConfigInfo;
|
||||
}
|
||||
|
||||
|
||||
- (NSMutableArray *)receiveFace {
|
||||
if (_receiveFace == nil) {
|
||||
_receiveFace = [NSMutableArray array];
|
||||
}
|
||||
return _receiveFace;
|
||||
}
|
||||
|
||||
- (BOOL)getShowingFace {
|
||||
return self.isShowingFace;
|
||||
}
|
||||
|
||||
- (NSCache *)faceCache {
|
||||
if (_faceCache == nil) {
|
||||
_faceCache = [[NSCache alloc]init];
|
||||
}
|
||||
return _faceCache;
|
||||
}
|
||||
|
||||
|
||||
- (FaceConfigInfo *)getPlayTogetherFace {
|
||||
//一起玩
|
||||
|
||||
|
||||
if (self.faceInfos != nil && self.faceInfos.count > 0) {
|
||||
for (int i = 0; i < self.faceInfos.count; i++) {
|
||||
FaceConfigInfo *faceInfo = self.faceInfos[i];
|
||||
if (faceInfo.id == 17) {
|
||||
return faceInfo;
|
||||
}
|
||||
}
|
||||
}else {
|
||||
[self requestFaceJson];
|
||||
}
|
||||
return nil;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
- (void)requestFaceJson {
|
||||
@weakify(self);
|
||||
self.isLoadFace = NO;
|
||||
self.requestJsonCount += 1;
|
||||
// [HttpRequestHelper getTheFaceJson:^(NSArray *faceJsonList) {
|
||||
// @strongify(self);
|
||||
// self.tempFaceInfos = [self sortFaceInfosWithfaceInfoArr:[faceJsonList mutableCopy]]; //表情排序
|
||||
//
|
||||
// [self faceDownloadManager];
|
||||
// NotifyCoreClient(FaceCoreClient, @selector(onGetFaceJsonSuccess), onGetFaceJsonSuccess);
|
||||
// } failure:^(NSNumber *resCode, NSString *message) {
|
||||
// @strongify(self);
|
||||
// if ((int)self.requestJsonCount < 3) {
|
||||
// if (self.retryDelay == 0) {
|
||||
// self.retryDelay = 1;
|
||||
// }
|
||||
// [self performSelector:@selector(requestFaceJson) withObject:nil afterDelay:self.retryDelay * 4];
|
||||
// }
|
||||
// }];
|
||||
}
|
||||
|
||||
#pragma mark - Test //测试使用
|
||||
- (void)cancelFaceTimer {
|
||||
self.timer = nil;
|
||||
}
|
||||
|
||||
- (void)startFaceTimer {
|
||||
// 获得队列
|
||||
dispatch_queue_t queue = dispatch_get_main_queue();
|
||||
// 创建一个定时器(dispatch_source_t本质还是个OC对象)
|
||||
self.testTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
|
||||
// 设置定时器的各种属性(几时开始任务,每隔多长时间执行一次)
|
||||
// GCD的时间参数,一般是纳秒(1秒 == 10的9次方纳秒)
|
||||
// 何时开始执行第一个任务
|
||||
// dispatch_time(DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC) 比当前时间晚3秒
|
||||
dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(8 * NSEC_PER_SEC));
|
||||
uint64_t interval = (uint64_t)(60.0 * NSEC_PER_SEC);
|
||||
dispatch_source_set_timer(self.testTimer, start, interval, 0);
|
||||
|
||||
// 设置回调
|
||||
@weakify(self);
|
||||
dispatch_source_set_event_handler(self.testTimer, ^{
|
||||
@strongify(self);
|
||||
[self sendAllFace:[self getPlayTogetherFace]];
|
||||
});
|
||||
// 启动定时器
|
||||
dispatch_resume(self.testTimer);
|
||||
}
|
||||
|
||||
@end
|
@@ -18,7 +18,7 @@
|
||||
#import "XPCandyTreeAnimationManager.h"
|
||||
///Model
|
||||
#import "RoomInfoModel.h"
|
||||
#import "AttachMentModel.h"
|
||||
#import "AttachmentModel.h"
|
||||
#import "CandyTreeInfoModel.h"
|
||||
#import "CandyTreeResultModel.h"
|
||||
///View
|
||||
|
@@ -17,7 +17,7 @@
|
||||
#import "XPGiftStorage.h"
|
||||
///Model
|
||||
#import "XPMessageRemoteExtModel.h"
|
||||
#import "AttachMentModel.h"
|
||||
#import "AttachmentModel.h"
|
||||
#import "GiftReceiveInfoModel.h"
|
||||
#import "XPKickUserModel.h"
|
||||
#import "MicroQueueModel.h"
|
||||
|
@@ -19,7 +19,7 @@
|
||||
#import "XPRoomMiniManager.h"
|
||||
///Model
|
||||
#import "RoomInfoModel.h"
|
||||
#import "AttachMentModel.h"
|
||||
#import "AttachmentModel.h"
|
||||
///View
|
||||
#import "XPRoomMessageTableViewCell.h"
|
||||
#import "XPRoomMessageHeaderView.h"
|
||||
|
@@ -27,7 +27,7 @@
|
||||
///Model
|
||||
#import "RoomInfoModel.h"
|
||||
#import "UserInfoModel.h"
|
||||
#import "AttachMentModel.h"
|
||||
#import "AttachmentModel.h"
|
||||
///View
|
||||
#import "XPShareView.h"
|
||||
///VC
|
||||
|
@@ -393,6 +393,8 @@
|
||||
[self giftValueUpdate:attachment.data];
|
||||
}else if(attachment.first == CustomMessageType_AllMicroSend && (attachment.second == Custom_Message_Sub_AllMicroSend || attachment.second == Custom_Message_Sub_AllBatchSend || attachment.second == Custom_Message_Sub_AllMicroLuckySend || attachment.second == Custom_Message_Sub_AllBatchMicroLuckySend)) {
|
||||
[self giftValueUpdate:attachment.data];
|
||||
} else if (attachment.first == CustomMessageType_Face && attachment.second == Custom_Message_Sub_Face_Send) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -22,6 +22,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@property (nonatomic,strong) ClientDataModel *configInfo;
|
||||
///开箱子 大于等级 展示
|
||||
@property (nonatomic, assign) NSInteger openCandyTreeLimitLevel;
|
||||
///表情---
|
||||
@property (nonatomic, copy) NSString *version;
|
||||
@property (nonatomic, copy) NSString *zipMd5;
|
||||
@property (nonatomic, strong) NSURL *zipUrl;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
@@ -10,6 +10,11 @@
|
||||
/// tool
|
||||
#import "DESEncrypt.h"
|
||||
#import "XPConstant.h"
|
||||
#import "NSString+JsonToDic.h"
|
||||
#import <MJExtension/MJExtension.h>
|
||||
#import "XPFaceParser.h"
|
||||
///Model
|
||||
#import "FaceConfigInfo.h"
|
||||
|
||||
@interface ClientConfig ()
|
||||
///重试的次数 10次 如果你还是失败的话 那就算了 没办法了
|
||||
@@ -40,18 +45,19 @@
|
||||
self.configInfo = model;
|
||||
/* 表情包 */
|
||||
NSString *json = initData[@"faceJson"][@"json"];
|
||||
// NSString *deJson = [DESEncrypt decryptUseDES:json key:keyWithType(KeyType_FAcePwdEncode, NO)];
|
||||
// NSDictionary *faceInitData = [NSString dictionaryWithJsonString:deJson];
|
||||
// if (faceInitData) {
|
||||
// NSArray *arr = [NSArray yy_modelArrayWithClass:[FaceConfigInfo class] json:faceInitData[@"faces"]];
|
||||
// GetCore(FaceCore).version = [NSString stringWithFormat:@"%@",faceInitData[@"version"]];
|
||||
// GetCore(FaceCore).zipMd5 = [[NSString stringWithFormat:@"%@",faceInitData[@"zipMd5"]] uppercaseString];
|
||||
// GetCore(FaceCore).zipUrl = [NSURL URLWithString:[NSString stringWithFormat:@"%@",faceInitData[@"zipUrl"]]];
|
||||
//
|
||||
// NotifyCoreClient(AppInitClient, @selector(onGetFaceDataSuccess:), onGetFaceDataSuccess:arr);
|
||||
//
|
||||
// }
|
||||
|
||||
NSString *deJson = [DESEncrypt decryptUseDES:json key:KeyWithType(KeyType_FacePwdEncode)];
|
||||
NSDictionary *faceInitData = [NSString dictionaryWithJsonString:deJson];
|
||||
if (faceInitData) {
|
||||
NSArray *arr = [FaceConfigInfo modelsWithArray:faceInitData[@"faces"]];
|
||||
NSArray *nobleArray = [FaceConfigInfo modelsWithArray:faceInitData[@"vipFaces"]];
|
||||
NSMutableArray *array = [NSMutableArray arrayWithArray:arr];
|
||||
[array addObjectsFromArray:nobleArray];
|
||||
[XPFaceParser shareParser].version = [NSString stringWithFormat:@"%@",faceInitData[@"version"]];
|
||||
[XPFaceParser shareParser].zipMd5 = [[NSString stringWithFormat:@"%@",faceInitData[@"zipMd5"]] uppercaseString];
|
||||
[XPFaceParser shareParser].zipUrl = [NSURL URLWithString:[NSString stringWithFormat:@"%@",faceInitData[@"zipUrl"]]];
|
||||
[[XPFaceParser shareParser] getFaceDataSuccess:array];
|
||||
// NotifyCoreClient(AppInitClient, @selector(onGetFaceDataSuccess:), onGetFaceDataSuccess:arr);
|
||||
}
|
||||
} else {
|
||||
if (self.retryCount < 10) {
|
||||
[self clientInit];
|
||||
|
Reference in New Issue
Block a user